计算圆内的随机x,y坐标

时间:2013-09-20 10:47:30

标签: objective-c math

如何计算圆内的随机点(稍微均匀分布)?

我找到了这个答案(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

请帮助数学傻瓜:)

/索伦

3 个答案:

答案 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);
}

干杯!