Squ*_*uis 13 javascript random 3d geometry
我想选择给定球体上的随机点.这个页面解释得很好:
http://mathworld.wolfram.com/SpherePointPicking.html ("获取球体上任何小区域的点......")
但我不完全确定我是否在JavaScript中正确实现它,因为我几乎无法正确测试它:
var u = random();
var v = random();
var angle1 = 2 * Math.PI * u;
var angle2 = Math.pow(Math.cos (2 * v - 1), -1);
X = X0 + (radius * Math.sin(angle1) * Math.cos(angle2));
Y = Y0 + (radius * Math.sin(angle1) * Math.sin(angle1));
Z = Z0 + (radius * Math.cos(angle1));
Run Code Online (Sandbox Code Playgroud)
我特别不确定我是否正确地理解了cos(-1),我将其实现为"余弦为-1的幂".
小智 29
立方体算法不会在球体上产生均匀分布 - 特别是角落投影附近的区域将具有最密集的点分布,并且立方体的面的中心附近将是最低的.
您可以直观地理解这一点,因为投影到底层球体上的立方体体积在靠近立方体中心的角落附近较大.事实上,一小块(投射在球体上的一个小圆圈上)的体积与从原点到小圆圈的中心到它与之相交的球体上的点的矢量大小的立方成正比.
所以立方体面中心的相对体积(如(1,0,0))是1,但是对于一个角(例如,(1,1,1))是sqrt(3)或1.73立方体的立方体,大约5.2 ,所以几乎密度超过5倍!
spreadPoints()函数可能做得更好,但我不确定.
JavaScript中有一些错误 - 使用pow(.., - 1)函数而不是acos(),混合角度和缺少随机()调用的Math对象.
这里有类似但正确的JavaScript来执行Wolfram链接所说的内容:
/*
Returns a random point of a sphere, evenly distributed over the sphere.
The sphere is centered at (x0,y0,z0) with the passed in radius.
The returned point is returned as a three element array [x,y,z].
*/
function randomSpherePoint(x0,y0,z0,radius){
var u = Math.random();
var v = Math.random();
var theta = 2 * Math.PI * u;
var phi = Math.acos(2 * v - 1);
var x = x0 + (radius * Math.sin(phi) * Math.cos(theta));
var y = y0 + (radius * Math.sin(phi) * Math.sin(theta));
var z = z0 + (radius * Math.cos(phi));
return [x,y,z];
}
Run Code Online (Sandbox Code Playgroud)
650*_*502 23
我认为更简单的算法是
[-1,1]x[-1,1]x[-1,1]
立方体内选择一个随机点x*x + y*y + z*z > 1
从1开始重复x
,y
并z
通过Math.sqrt(x*x + y*y + z*z)
换句话说,只需在球体内选择一个随机点并在球体上投射.不要太担心"循环",因为点在球体外的概率大约是0.4764,并且平均来说循环将需要少于两次迭代.
您可以在此链接上查看此算法.请注意,如果你使用chrome,那么在赤道周围会有一些条带,我认为它是Math.random中的一个错误,或者只是一个低质量的随机生成器(在Firefox或Safari上工作正常,但同样的问题在Android浏览器上也可见).带有更多的点(例如10000而不是我现在使用的1000点以保持动画平滑),条带更加明显.编辑:此错误现已修复Chrome和Android.
请注意,如果您正在寻找一种在球体上均匀分布点的方法,您可以通过选择上面描述的十个随机点然后仅接受与已选择的点集合具有最大3d距离的点来做更好的事情.这仍然是全局随机的(即,具有规定半径的光盘将接收点的光盘对于球体上的所有光盘都是相同的),但如果需要对球体进行"采样",则会更好地分布点.此函数编码为spreadPoints()
链接指向的html文件.
你可以在这里看到两种方法之间的区别:
两个球体上都有1000个随机点:左边的球体使用均匀的随机点,右边的球体通过挑选十个随机候选者中的每个点来做出选择,以最大化已经选择的点的距离.