木匣子

Web/Game/Programming/Life etc.

在圆内平均分布的点

要想在一个圆内随机取一个点不难,通常可以分成两个步聚:

  1. 随机选一个角度(0~360);
  2. 随机选一个小于半径的长度。

代码(processing):

float rad=random(TWO_PI);
float dist=random(1)*radius;
point(cos(rad)\*dist, sin(rad)\*dist);

这样可以确保点落在以原点为中心,半径为radius的圆内。 但是如果不断地重复这样取点,最终会发现在圆心的点更容易被取到,也就是说圆内的点被取到的概率不平均!最终会出现如图最左边这样的分布:

circle

而我们想要的效果是像图中间那个圆那样的分布。 后来在 Keith Peters 大师的 Foundation ActionScript 3 Animation Making Things Move! 一书中看到了这个非常漂亮的算法。来自他的朋友 Sean O’Shell:

float rad=random(TWO_PI);
float dist=sqrt(random(1))*radius;
point(cos(rad)\*dist, sin(rad)\*dist);

嘿,奇迹发生了。聪明的你或许已经发现了其中的奥秘。将 random(1) 开方后,原本靠近中心的点被扯开了,正好平均地分布在圆中。 至于数学证明,我还没有找到 :)

2013/03/06 UPDATED:在 Physically Based Rendering 一书中有对单位圆均匀采样的详细论述,可以参考一下 codeboycjy 的这篇日志《PBRT学习笔记:在单位圆内部均匀采样