在圆形rect内生成均匀分布的随机位置

时间:2016-07-19 19:58:54

标签: algorithm math

无法发明可接受的东西。 我的第一个(也是唯一的)方法很尴尬:

  1. 计算面积= non_rounded_area + area_of_rounded corner * 4.我们将此区域视为矩形中的像素数。
  2. 从范围[0..area]中获取随机数,以便说出一个像素索引。
  3. 以某种方式从该索引获取x和y坐标。
  4. 主要的尴尬是如何执行第3步? 我认为它甚至可以考虑直方(和一个角)的1/4部分,只是将结果旋转到其他季度。
    好吧,假设我知道有多少像素属于'到了给定的角落。 并且从索引属于非圆形区域获取x和y坐标很容易。

    但如何为属于角落的像素执行此操作? 我的想法是关于"确定像素是否属于圆圈"但不能明白地表达它们。

1 个答案:

答案 0 :(得分:2)

这是一种方法,可以为一个象限进行推广,可以推广到一个完整的矩形: enter image description here

首先计算象限中的总像素数(红色+橙色+绿色):

int totalPixels = w * h;

然后计算红色区域(角落中圆角矩形之外的像素):

int invalidCornerPixels = (int)((float)(r * r) * ((4.0f - PI) / 4.0f));

橙色区域等于红色区域。您可以对红色+绿色区域中的像素进行采样,如果它们位于红色区域,则会在橙色区域中采样一个随机像素。

int redGreenArea = totalPixels - invalidCornerPixels;

假设randomValue(n)返回从0到n - 1的随机int:

int pixelIndex = randomValue(redGreenArea);
int pixelX = pixelIndex % w;
int pixelY = pixelIndex / w;

测试采样像素是否在红色区域,并在必要时重新采样:

if((pixelX < r) && (pixelY < r))
{
    int circleX = r - pixelX;
    int circleY = r - pixelY;
    if(((circleX * circleX) + (circleY * circleY)) > (r * r))
    {
         pixelIndex = randomValue(invalidCornerPixels) + redGreenArea;
         pixelX = pixelIndex % w;
         pixelY = pixelIndex / w;
    }
}

这需要最多2个随机数生成(通常只有1个),并且不比拒绝采样复杂,因为您也必须为此实现相同的测试。 totalPixelsinvalidCornerPixelsredGreenArea的计算可以完成一次并存储给定矩形。

一个缺点是由于舍入误差,在实践中未通过测试的像素数可能不完全等于invalidCornerPixels,这将给出非常轻微的非均匀分布。您可以通过离线强力计算invalidCornerPixels(计算r x r平方中未通过测试的像素)并为r的每个值创建查找表来解决此问题。我怀疑如果用于粒子发生器则会引人注意。另一个缺点是,如果红色区域与橙色区域重叠,它将失败。