我加上这个答案:
--没有其他选择符合“一致性”需要“准确无误”(或者不那么明显)。(注意到在原始请求中特别需要像行星一样的分布行为,你只需要随机地从 k 均匀创建的点的有限列表中拒绝(随机地写回 k 项中的索引计数)
--最接近的其他暗示迫使你通过“角轴”来决定“ N”,而在两个角轴值之间只有“ N 的一个值”(在 N 数较少的情况下,很难知道什么可能重要,什么可能不重要(例如,你想要“5”点——玩得开心))
此外,如果没有任何图像,很难“理解”如何区分其他选项,所以下面是这个选项的样子(下图) ,以及随之而来的准备运行的实现。< br >
from math import cos, sin, pi, sqrt
def GetPointsEquiAngularlyDistancedOnSphere(numberOfPoints=45):
""" each point you get will be of form 'x, y, z'; in cartesian coordinates
eg. the 'l2 distance' from the origion [0., 0., 0.] for each point will be 1.0
------------
converted from: http://web.archive.org/web/20120421191837/http://www.cgafaq.info/wiki/Evenly_distributed_points_on_sphere )
"""
dlong = pi*(3.0-sqrt(5.0)) # ~2.39996323
dz = 2.0/numberOfPoints
long = 0.0
z = 1.0 - dz/2.0
ptsOnSphere =[]
for k in range( 0, numberOfPoints):
r = sqrt(1.0-z*z)
ptNew = (cos(long)*r, sin(long)*r, z)
ptsOnSphere.append( ptNew )
z = z - dz
long = long + dlong
return ptsOnSphere
if __name__ == '__main__':
ptsOnSphere = GetPointsEquiAngularlyDistancedOnSphere( 80)
#toggle True/False to print them
if( True ):
for pt in ptsOnSphere: print( pt)
#toggle True/False to plot them
if(True):
from numpy import *
import pylab as p
import mpl_toolkits.mplot3d.axes3d as p3
fig=p.figure()
ax = p3.Axes3D(fig)
x_s=[];y_s=[]; z_s=[]
for pt in ptsOnSphere:
x_s.append( pt[0]); y_s.append( pt[1]); z_s.append( pt[2])
ax.scatter3D( array( x_s), array( y_s), array( z_s) )
ax.set_xlabel('X'); ax.set_ylabel('Y'); ax.set_zlabel('Z')
p.show()
#end
function sphere ( N:float,k:int):Vector3 {
var inc = Mathf.PI * (3 - Mathf.Sqrt(5));
var off = 2 / N;
var y = k * off - 1 + (off / 2);
var r = Mathf.Sqrt(1 - y*y);
var phi = k * inc;
return Vector3((Mathf.Cos(phi)*r), y, Mathf.Sin(phi)*r);
};
import math
def fibonacci_sphere(samples=1000):
points = []
phi = math.pi * (3. - math.sqrt(5.)) # golden angle in radians
for i in range(samples):
y = 1 - (i / float(samples - 1)) * 2 # y goes from 1 to -1
radius = math.sqrt(1 - y * y) # radius at y
theta = phi * i # golden angle increment
x = math.cos(theta) * radius
z = math.sin(theta) * radius
points.append((x, y, z))
return points
我们的 area 元素是 R dR dΘ,现在变成了不太复杂的 sin (Φ) dΦ dΘ。因此,均匀间距的联合密度是 sin (Φ)/4π。积分出 Θ,我们发现 F(Φ) = sin (Φ)/2,因此 R1(Φ) = (1-cos (Φ))/2。反过来,我们可以看到一个统一的随机变量看起来像 acos (1-2 R4) ,但是我们是统一采样而不是随机采样,所以我们使用 ΦR6 = acos (1-2(R7 + 0.5)/R8)。算法的其他部分只是把它投影到 x,y 和 z 坐标上:
from numpy import pi, cos, sin, arccos, arange
import mpl_toolkits.mplot3d
import matplotlib.pyplot as pp
num_pts = 1000
indices = arange(0, num_pts, dtype=float) + 0.5
phi = arccos(1 - 2*indices/num_pts)
theta = pi * (1 + 5**0.5) * indices
x, y, z = cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi);
pp.figure().add_subplot(111, projection='3d').scatter(x, y, z);
pp.show()
对于 n = 100和 n = 1000,结果同样如下:
进一步研究
我想为马丁 · 罗伯茨的博客大声疾呼。请注意,上面我通过向每个索引添加0.5来创建索引的偏移量。这只是视觉上吸引我,但 事实证明,补偿的选择非常重要和不是恒定的间隔,可以意味着获得多达8% 更好的准确性包装,如果选择正确。也应该有一种方法让 他的 R < sub > 2 序列覆盖一个球体,这将是有趣的,看看这是否也产生一个不错的均匀覆盖,也许是-是,但也许需要,说,从只有一半的单位方形斜切或左右,并拉伸周围得到一个圆。