Random 二维随机点的均匀分布

Random 二维随机点的均匀分布,random,plot,2d,distribution,pseudocode,Random,Plot,2d,Distribution,Pseudocode,我试图做一个简单的“人群”模型,需要在二维区域内分布随机点。这个半伪代码是我最好的尝试,但我甚至在运行它之前就已经看到了大问题,因为对于密集的人群,新的点太近的可能性可能会很快变得非常高,这使得它非常低效,并且很容易失败,除非对值进行微调。可能有符号值也有问题,但为了简单起见,我不考虑这个问题 int numPoints = 100; int x[numPoints]; int y[numPoints]; int testX, testY; tooCloseRadius = 20; maxPo

我试图做一个简单的“人群”模型,需要在二维区域内分布随机点。这个半伪代码是我最好的尝试,但我甚至在运行它之前就已经看到了大问题,因为对于密集的人群,新的点太近的可能性可能会很快变得非常高,这使得它非常低效,并且很容易失败,除非对值进行微调。可能有符号值也有问题,但为了简单起见,我不考虑这个问题

int numPoints = 100;
int x[numPoints];
int y[numPoints];
int testX, testY;

tooCloseRadius = 20;
maxPointChecks = 100;
pointCheckCount = 0;

for (int newPoint = 0; newPoint < numPoints; newPoint++ ){

    //Keep checking random points until one is found with no other points in close proximity, or maxPointChecks reached.
    while (pointCheckCount < maxPointChecks){
        tooClose = false;
        // Make a new random point and check against all previous points
        testX = random(1000);
        testY = random(1000);
        for ( testPoint = 0; testPoint < newPoint; testPoint++ ){
            if  ( (isTooClose (x[testPoint] , y[testPoint], textX, testY, tooCloseRadius) ) {
            tooClose = true;
            break; // (exit for loop)
        }
        if (tooClose == false){
            // Yay found a point with some space!
            x[newPoint] = testX;
            y[newPoint] = testY;
            break; // (exit do loop)
        }
        //Too close to one of the points, start over.
        pointCheckCount++;
    }
    if (tooClose){
        // maxPointChecks reached without finding a point that has some space.
        // FAILURE DEPARTMENT
    } else {
        // SUCCESS
    }
}

// Simple Trig to check if a point lies within a circle.
(bool) isTooClose(centerX, centerY, testX, testY, testRadius){
    return (testX - centreX)^2 + (testY - centreY)^2)  < testRadius ^2
}
int numPoints=100;
整数x[numPoints];
整数y[numPoints];
int testX,testY;
半径=20;
maxPointChecks=100;
pointCheckCount=0;
对于(int newPoint=0;newPoint
在谷歌搜索了这个主题之后,我相信我所做的就是拒绝采样(?),自适应拒绝采样可能是一个更好的方法,但是数学太复杂了


有没有不需要统计学学位就可以实现这一目标的优雅方法?

对于您提出的问题,生成随机样本的最佳方法是使用泊松圆盘采样

现在,如果你想用一种简单的方法在一个矩形中随机取样点 从0到最大标注的长度,每个点采样两个值

如果表示较小维度的值大于该维度,请丢弃该对并重试

伪代码:

while (need more points)
begin
   range = max (rect_width, rect_height);

   x = uniform_random(0,range);
   y = uniform_random(0,range);

   if (x > rect_width) or (y > rect_height)
    continue;
   else
     insert point(x,y) into point_list;
end
您最多采样两个长度中较大的一个,是为了在长度不同时使统一选择标准等效

例如,假设一侧的长度为K,另一侧的长度为10K。并且假设使用的数字类型的分辨率为K的1/1000,那么对于较短的一侧,只有1000个可能值,而对于较长的一侧,有10000个可能值可供选择。1/1000的概率与1/10000的概率不同。简单地说,put短边的坐标值发生的概率比长边的坐标值大10倍,这意味着采样并不真正均匀


要确保生成的点与任何已生成点之间的距离不小于某个距离的场景的伪代码:

while (need more points)
begin
   range = max (rect_width, rect_height)

   x = uniform_random(0,range);
   y = uniform_random(0,range);

   if (x > rect_width) or (y > rect_height)
    continue;

   new_point = point(x,y);

   too_close = false;

   for (p : all points)
   begin
     if (distance(p, new_point) < minimum_distance)
     begin
       too_close = true;
       break;
     end
   end

   if (too_close)
      continue;

   insert point(x,y) into point_list;
end
while(需要更多积分)
开始
范围=最大值(矩形宽度、矩形高度)
x=均匀随机(0,范围);
y=均匀随机(0,范围);
如果(x>矩形宽度)或(y>矩形高度)
继续;
新的_点=点(x,y);
太接近=错误;
对于(p:所有点)
开始
if(距离(p,新点)<最小距离)
开始
太接近=正确;
打破
结束
结束
如果(太近)
继续;
将点(x,y)插入点列表;
结束

虽然泊松盘解通常很好,但我想用准随机数指出另一种解决方案。对于准随机Sobol序列,有一种说法说,点之间存在最小正距离,即0.5*sqrt(d)/N,其中
d
是问题的维度(在您的例子中为2),和
N
是在超立方体中采样的点数。这张纸是从这个人自己那里得到的


为什么我认为它应该是Python?对不起,我的错。对于类C语言来说,最好调用GSL,函数名是
GSL\u qrng\u sobol
。在d=2处使用它的示例是链接的

你能解释均匀随机吗?这只是0->range中的一个标准随机函数吗?@Kez是的。它将返回范围[0,上限]中的值均匀概率-其中上界是最大边的长度。好的,但为什么使用范围而不仅仅是x=均匀随机(0,矩形宽度);等等?此外,Poisson Disc采样def似乎是正确的方法。但您的快速伪代码与我的一样效率低下,事实上更糟糕,因为它可以在没有超时检查的情况下卡在无限循环中。无论如何,我将Poisson Disc链接标记为正确,因为它确实是一个很好的解决方案,即使它需要大量代码。Thanks Severin Pappadeux,这是另一个很好的技巧,不过我得先弄清楚这个数学。泊松盘解决方案的一个问题是,你总是得到“紧密堆积”的点,这可能是不可取的。@Kez泊松盘实际上有很多问题。首先,是O(N)算法,这使得真实模拟的速度很慢(比如,百万个点)。其次,不清楚基本分布是什么,比如说,与蒙特卡罗积分一起使用。对于U(0,1),你会得到通常的蒙特卡罗收敛作为逆sqrt(N)。对于准随机,它更接近逆N。PD?谁知道…更多的链接需要查看:,你可以查看点的一致性。另一个链接: