我希望在一个正方形中创建一组具有以下约束的N个点(通常为1e2 - 1e4):
所有点之间应该有一个最小距离(硬核禁区)
预先给出填充正方形的点数(或接近估计值),因为我想获得固定密度(如果需要,我可以稍微调整一下正方形的大小)。
该模式应该是合理的"随机"
首选快速解决方案
之前我在包spatstat中使用了rStrauss,但是我永远无法弄清楚如何可靠地获得给定数量的点,并且通常该函数会使我的机器停顿10分钟,可能是因为任务太难了。我猜测可能有更合适的功能。
## regular grid of 1e2 points in [-10, 10]^2
xy = expand.grid(x=seq(-10, 10, length=10), y=seq(-10, 10, length=10))
N = NROW(xy)
编辑:如答案所示
xyr = rSSI(r=0.1, N, win = owin(c(-10,10),c(-10,10)), N)
plot(xyr)
答案 0 :(得分:3)
rSSI
可以处理您的问题,除了可能的速度,这取决于您的标准。它具有硬核禁止距离,并且会达到目标点数(或放弃尝试 - 您可以设置放弃的阈值),并且放置是随机的。我不认为它特别快,但我能够在单位正方形中创建1e6
点,在约30秒内禁止距离为1e-4
。速度和成功率在很大程度上取决于您相对于点数的抑制距离。
答案 1 :(得分:2)
主要是作为学习更多关于Rcpp的借口,这是我尝试做一些小功能:
require(inline)
require(Rcpp)
randPoints = cxxfunction(signature(r_n='int', r_mindist='float', r_maxiter='int'), body =
'
using namespace std;
int n = as<int> (r_n);
float mindist = as<float> (r_mindist);
int maxiter = as<int> (r_maxiter);
RNGScope scope;
bool tooclose;
int iter;
NumericVector rands (2);
NumericMatrix points (n, 2);
NumericVector dist (2);
for (int i=0; i < n; i++) {
iter = 0;
do {
iter++;
tooclose = false;
rands = runif(2, 0, 1);
for (int idist=0; idist < i; idist++) {
dist = rands - points(idist, _);
dist = dist * dist;
if (sqrt(accumulate(dist.begin(), dist.end(), 0.0)) < mindist) {
tooclose = true;
break;
}
}
} while (tooclose & iter < maxiter);
if (iter == maxiter) {
Rprintf("%d iterations reached\\nOnly %d points found\\n", maxiter, i+1);
break;
}
NumericMatrix::Row target(points, i);
target = rands;
}
return(wrap(points));
'
, plugin='Rcpp')
然后你就可以使用它:
> x = randPoints(1000, 0.05, 10000)
10000 iterations reached
Only 288 points found
这是情节:
x = x[as.logical(rowMeans(x != 0)), ]
dev.new(width=4, height=4)
plot(x)