一个简单的DEMO展示了如何在球面上随机均匀分布点,2022年更新了新版本,点击这里查看更新的内容
基于变换抽样的Marsaglia方法
效果最好,最均匀的算法,但是它其实是一种伪随机数生成器
伪随机数生成器(pseudo random number generator,PRNG),又被称为确定性随机比特生成器(deterministic random bit generator,DRBG),是一个生成数字序列的算法,其特性近似于随机数序列的特性。PRNG生成的序列并不是真随机,因此它完全由一个初始值决定,这个初始值被称为PRNG的随机种子(seed,但这个种子可能包含真随机数)。尽管接近于真随机的序列可以通过硬件随机数生成器生成,但伪随机数生成器因为其生成速度和可再现的优势,在实践中也很重要。
大致的步骤如下
1 2 3 4 5 6 7 8 9 10 11 12 13 step1: 随机抽样产生一对均匀分布的随机数 u ,v ;这里u,v 在[-1,1] 范围内 step2 : 计算 r^2 = u^2+v^2; 如果 r^2 > 1 则重新抽样,直到满足 r^2 < 1 . step3 : 计算 x=2*u*sqrt(1-r2); y=2*v*sqrt(1-r2); z=1-2*r2;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 const getRandomFloat = (min, max ) => Math .random () * (max - min) + min;export function MarsagliaRandom (maxRadius,num ) { let res = [] num = num || 100 for (let i=0 ;i<num;){ let x1,x2 while (true ){ x1 = getRandomFloat (0 ,maxRadius) x2 = getRandomFloat (0 ,maxRadius) x1 = 2 *(x1-0.5 ) x2 = 2 *(x2-0.5 ) if ((x1*x1+x2*x2)<1 ) { i++ break } } let obj = { x :(2 *x1*Math .sqrt (1 -x1*x1-x2*x2))*maxRadius, y :(2 *x2*Math .sqrt (1 -x1*x1-x2*x2))*maxRadius, z :(1 -2 *(x1*x1+x2*x2))*maxRadius, } res.push (obj) } return res }
一次随机角度和方向的方法
效果不是很好,但效率稍高一些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 export function Simple2SphereRandom (maxRadius,num ) { let res = [] num = num || 100 let rotval,phi,theta const {sin,cos} = Math for (let i=0 ;i<num;i++){ let obj = {} rotval = getRandomFloat (0 ,maxRadius) theta = Math .PI * rotval rotval = getRandomFloat (0 ,maxRadius) phi = 2 *Math .PI *rotval obj.x = sin (theta)*cos (phi) * maxRadius obj.y = sin (theta)*sin (phi) * maxRadius obj.z = cos (theta) * maxRadius res.push (obj) } return res }