如何在正方形内生成随机点,但不在正方形内切出的圆内

时间:2015-07-07 20:09:05

标签: math random

参考图片:

红色圆圈的半径为r

蓝色方块的边长为s

目标是在蓝色区域内生成随机点,但不在红色区域内生成 我已经有了一个解决方案,但它涉及反复试验,这不是我喜欢的方法,是否有某种数学解决方案来解决这个问题?

这是我的方法

设rx和ry为随机变量

rx = random number between 0 and s
ry = random number between 0 and s
while (distance(rx,ry,0,0) < r)
{
   rx = random number between 0 and s
   ry = random number between 0 and s
}
return rx ry;

6 个答案:

答案 0 :(得分:6)

我建议你坚持现在的想法,这被正式称为rejection sampling,并且是一种相对常见的技术,仅使用统一的随机数生成器从任意概率分布中进行采样。

随着维数增加而减速的问题根本不可避免 - 这通常被称为curse of dimensionality

虽然有些人建议&#34;推动&#34;最终在圆圈中的点到可接受/蓝色区域中的点,在不牺牲完全均匀的概率分布的情况下很难做到这一点。 (例如,我可以将圆中的所有点推到圆的边界上的最近点,但这会使分布不均匀,因为圆的边界将被更频繁地采样。)

为了使您的代码尽可能高效,您应该在不调用任何函数的情况下计算(distance(rx,ry,0,0),并使用+*等主要运算符,而不是任何库函数比如exp(x,2)。换句话说,直接在x*x + y*y < r2语句中使用if(在某处预定义r2 = r*r;)。

答案 1 :(得分:3)

我可以看到两种可能性。如果圆圈比正方形小很多,则在正方形内生成一个点,并检查它是否在圆圈内部或外部。如果圆是方形的大部分,则找到距离圆心最远的方形角的最大可能半径。生成一个在给定圆外的半径,但不大于到最远角的距离。也生成一个theta。如果得到的(r,theta)点在正方形内,则接受它。构造方法确保它在圆圈之外。

答案 2 :(得分:2)

我不会参加讨论数学与编程。对我来说这个问题都有。这是我的看法。

您可以尝试将[0,1]间隔中生成的点映射到蓝色区域。如果两个形状都是同心圆,则应该给出正态分布。当你有一个正方形时,你越接近对角线,点就越稀疏。

想法是在极坐标中工作:

  1. 假设您的图片中心位于笛卡尔(x,y)位置(0,0)
  2. a间隔中生成一个[0,1]个数字。
  3. 将此数字转换为角度w = 2 * pi * a。这将是你的极角。等式y = x * tan(w)定义了穿过图片中心的直线。
  4. 现在棘手的部分:计算数字的径向部分(rho)可接受的限制。它必须大于圆r的半径,并且小于步骤3中定义的直线截取正方形的点。
  5. 将有四种可能性,一个用于广场的每一侧。 &#34;顶部&#34;侧面是w的值从pi/43pi/4的情况; &#34;左侧&#34;适用于w,范围从3pi/45pi/4; &#34;底部&#34;在w5pi/4之间有7pi/4;和'#34;对&#34;一方有w7pi/42pi以及0pi/4
  6. 让我们以顶线为例:它位于y = s / 2位置。然后截取3中与顶侧定义的线在s/2 = xi tan(w)位置。
  7. 笛卡儿点(xi, s/2)定义了rho的最大值:R = sqrt(xi^2 + (s/2)^2)
  8. 现在在b间隔
  9. 中生成另一个值[0,1]
  10. 将此值映射到[r,R]区间:rho = r + b * R
  11. 最后得到你的号码X = rho * cos(w)Y = rho * sin(w)应该在蓝色区域。
  12. 请注意,从第5步开始,您必须检查广场的哪一侧是您应该考虑的那一侧(w的值)。

    如上所述,问题在于对角线比沿主轴的方向长,产生更稀疏的分布。您可以自行决定是否存在问题。请注意,映射不会堆积靠近圆边的点。还要问问自己,方向检查是否切实可行(我假设方形和圆形形状与您真正想要的粗略近似)。

答案 3 :(得分:0)

然而,正如@Marc所说,技术上它是数学,而不是编程。然而,答案是生成随机点,然后确定从该正方形的中心到该点绘制的线的长度是否小于或等于圆的半径。如果是这样,请拒绝并生成另一个。

答案 4 :(得分:0)

您可以在[0..1]范围内生成两个数字,然后定义一个函数,将某个y的x映射到圆外的一个点。

答案 5 :(得分:0)

好的,如果不是rx和ry,为什么要拒​​绝它们? [-s,s]中的任何rx都可以作为我们的选择。因此;

rx = -s + 2*s*rand();

if(rx<-R || rx>R) % if rx is outside the critical area, you are free on ry
    ry = -s + 2*s*rand();
else % if rx is critical, we are restricted about choosing ry not within [-sqrt(R^2-rx^2),sqrt(R^2-rx^2)]
{
    rand_inst = rand();
    if(rand_inst<0.5) % for the first possible interval [-s, -sqrt(R^2-rx^2)]
        ry = -s + 2*(s-sqrt(R^2-rx^2))*rand_inst;
    else % for the second possible interval [sqrt(R^2-rx^2), s]
        ry = (sqrt(R^2-rx^2) - (s-sqrt(R^2-rx^2)) ) + 2*(s-sqrt(R^2-rx^2))*rand_inst;
}