我觉得这个问题很具描述性,但用文字来说明。
画出一个径向渐变(中心为黑色,边缘为白色)我想生成一个随机点,它更容易落入黑色,不太可能掉入灰色,甚至不太可能掉入白色
有人能指出我正确的方向吗?我很难过:/
答案 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^T
是B
的转置。
您可以通过生成两个正态分布变量的列向量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的某个数字。