首先,如何定义这个题目中的“均布”,理解为“evenly distributed”,也就是尽可能尽可能减少跟“uniform distribution”的discrepancy。写得更加准确一点就是:
其中球面两点的夹角(等价于测地距离),是球面上以为中心,为最大夹角的圆覆盖区域,表示球面上某个区域的测度(面积)。
如何在球体上均匀分布点的问题由来已久,在数学、物理、化学和计算的许多领域都具有巨大的意义,包括但不仅限于数值分析、逼近论、晶体学、病毒形态、静电、编码理论和计算机图形学,所以从各种角度研究这个问题的方法都有。除了少数情况外(比如等价于正多面体顶点的情形),这个问题仍没有完全解决。因此,一般只能求得近似解决方案。
下面介绍两种方法:
其中一种方法是将散点想象为同种电荷的相同粒子,分布在球面上,使得总势能最小,也就是寻找一组个点:
使得最小化
不难知道上式是可以取到最小值的,但上面的函数有非常多的局部极小值。如何选取到最小值就是典型的流形上的光滑优化问题,需要通过优化数值求解,参考汇总的结果
对于49个点,其中一个近似解如下(北极方向的正交投影):
再多一些点也有近似解,比如2500个点,北极的正交投影就是:
另一种比较“美观”的做法是构造斐波那契网格,本质是上区域上的斐波那契网格经过保面积变换投影到球面上的样子(Lambert azimuthal equal-area projection)
首先是上的斐波那契网格,也就是
def gen_fib_lattice(N): phi = (1 + np.sqrt(5)) / 2 x = (np.arange(1, N + 1) / phi) % 1 y = np.arange(1, N + 1) / N return x, y
看起来就是:
斐波那契格点在平面上有均匀分布的特性,然后通过保面积变换,将其变到圆上:
def area_preserve_rec2circ(x, y): theta = 2 * np.pi * x r = np.sqrt(y) return theta, r
看起来就是
最后还是通过保面积变换,将平面上的圆变换到球面,也就是前面提到的Lambert azimuthal equal-area projection
def area_preserve_circ2sphere(theta, r): phi = 2 * np.arcsin(r) # latitude x = np.cos(theta) * np.sin(phi) y = np.sin(theta) * np.sin(phi) z = np.cos(phi) return x, y, z
对于N=49,长得是这个样子:
也可以求任意给定点数的排布,比如N=2500,看起来比最小能量的结果更加诡异一点:
-------加更一个Halton序列生成的球面“拟均匀”分布,浅色点表示在球的背面:
方法介绍见:
这次介绍了逼近球面上“evenly distributed”均匀布点的两种方法,一种是计算势能,类似光滑曲面上的带电粒子排布,另一种是平面的某种均布(斐波那契格点)通过两步保积变换投影到球面上。 当然还有一些基于距离的做法。不管怎样,所谓球面上均布的网格、插值、积分以及各种数值方法有非常紧密联系,非常重要就是了~ @派大西
参考链接: