椭圆内的随机点,更接近中心点的概率更高?

时间:2015-07-17 02:21:52

标签: algorithm

我觉得这个问题很具描述性,但用文字来说明。

画出一个径向渐变(中心为黑色,边缘为白色)我想生成一个随机点,它更容易落入黑色,不太可能掉入灰色,甚至不太可能掉入白色

有人能指出我正确的方向吗?我很难过:/

2 个答案:

答案 0 :(得分:1)

获得所需要的方法是生成截断的正态分布随机半径r,其中\ sigma = 1,范围为+ -R,均匀分布的随机值\ theta,0..pi为极角。如果A和B是与x和y对齐的长轴和短轴,那么相对于原点的点是

x = r A/R cos \theta,   y = r B/R sin \theta

当您选择参数R为大时,值将集中在椭圆的中心。当它很小时,它们将均匀地分布在它上面。

生成截断 - 正态分布的伪随机值并非易事,但也不是太难。参见例如Chopin's paper进行了很好的讨论。 This C++ implementation看起来很有用。

如果您不关心椭圆内的所有点,则可以使用完全正态分布。 Box Muller算法实现起来非常简单,它内置于许多库including Java's中。

答案 1 :(得分:1)

如果B是一个矩阵,y = c + Bx是一个仿射变换,将单位圆映射到椭圆(我假设你的意思是“椭圆”),那么概率分布看起来像你似乎想要的东西由y ~ N(c, BB^T)给出,其中B^TB的转置。

您可以通过生成两个正态分布变量的列向量x并应用转换y = c + Bx来从分布中进行抽样。有许多库用于生成一对正态分布的变量;在Java中,x0=rand.nextGaussian(); x1=rand.nextGaussian()将起作用。

这有时会在椭圆外产生点。你可以通过简单地拒绝这些点来避免这种情况。只需测试是x0*x0 + x1*x1 > 1并拒绝是否为真。

还有一件事:如果你想在椭圆边缘附近“更白”,你可以将你生成的高斯的标准偏差改为小于1的数字:

sd = 0.5; 
do 
  x0 = sd * rand.nextGaussian(); 
  x1 = sd * rand.nextGaussian();
while (x0*x0 + x1*x1 > 1);
y0 = c0 + B[0][0] * x0 + B[0][1] * x1
y1 = c1 + B[1][0] * x0 + B[1][1] * x1

如果您想要“减去白色”,请将sd设置为大于1的某个数字。