如何计算圆内的随机点(稍微均匀分布)?
我找到了这个答案(Udo Klein的答案):Use X,Y coordinates to plot points inside a circle和我的Objective C实现如下:
-(CGPoint)getRandomPointInCircle:(CGPoint)cCenter radius:(float)cRadius {
float r = cRadius * sqrtf(arc4random());
float angle = sqrtf(2 * M_PI);
float x = cCenter.x + r * cosf(angle);
float y = cCenter.y + r * sinf(angle);
CCLOG(@"--> rand point: %f,%f", x, y);
return ccp(x,y);
}
现在有一个给定的圆,中心为5000,5000,半径为7100,它给出了我这样的疯狂值: -324893408.000000,239372544.000000
请帮助数学傻瓜:)
/索伦
答案 0 :(得分:3)
您的问题是您没有将arc4random
的输出放入某个范围,但您也没有将该角度随机化。
首先,圈内随机分布的数学:
对于每个半径a
,半径为r
的圆内的随机点位于半径a
的圆内的概率为pi*a^2 / pi*r^2
= {{1} }。
(a/r)^2
为我们提供了一个均匀分布的随机数,但我们想要一个根据我们刚刚计算的分布(累积概率)偏差的数字。存在一种方法:http://en.wikipedia.org/wiki/Inverse_transform_sampling
我们累积概率的倒数为arc4random
(其中a = sqrt(p*(r^2))
在p
内)。这简化为[0 1]
。 (这就是你已经拥有的,所以恭喜!我不必要地计算了)
角度更容易;我们只需要在a = r * sqrt( p )
或[-pi pi)
等内部进行统一分发。
[0 pi*2)
请注意,对于包含范围,我使用float r = cRadius * sqrtf( arc4random( ) / (float) 0xFFFFFFFFul );
float angle = arc4random( ) * (float) (M_PI * 2) / (float) 0x100000000ul;
(= 2 ^ 32-1,作为无符号长整数,因此它适合编译)和0xFFFFFFFFul
(= 2 ^ 32)范围。这是一个你从未注意到的微小差异,但从数学上来说,这是转换分布的最正确方法。
您使用的随机化功能取决于您,但在目标C中通常建议使用0x100000000ul
,因为它不需要播种(它将比当前时间播种的分布“更随机”)
答案 1 :(得分:1)
最简单的方法是使用arc4random
,因为其他人建议生成两个随机数,然后将它们映射到R和theta的范围。像:
#import <tgmath.h>
// ...
CGFloat r = ((CGFloat)arc4random()) * cRadius / ((CGFloat)UINT32_MAX);
CGFloat theta = ((CGFloat)arc4random()) * (M_PI + M_PI) / ((CGFloat)UINT32_MAX);
CGPoint randomXY = CGPointMake(cCenter.x + r * cos(theta), cCenter.y + r * sin(theta));
答案 2 :(得分:0)
半径为R且中心(x0,y0)的圆上的点都是(x,y),这样:
x = x0 + R * cos(theta)
y = y0 + R * sin(theta)
theta从0到2 * PI。
如果你想要圆圈内的点,你需要点:
x = x0 + r * cos(theta)
y = y0 + r * sin(theta)
theta从0到2 * PI,r从0到R。
所以你需要做的就是为[0,R]中的r和[0,2 * PI]中的theta的随机值生成随机值!
在Objective-C中:
-(CGPoint)getRandomPointInCircle:(CGPoint)cCenter radius:(float)cRadius {
// Since it's a 2D problem, you want to generate two different random numbers to have a
// uniform distribution. So generate a number in [0,R] and another between [0,2*PI],
// without forgetting to seed.
srand48(time(0));
float r = (float)(drand48()*cRadius);
float angle = (float)(drand48()*2*M_PI);
// Now use the equations above!
float x = cCenter.x + r * cosf(angle);
float y = cCenter.y + r * sinf(angle);
CCLOG(@"--> rand point: %f,%f", x, y);
return ccp(x,y);
}
干杯!