我正在寻找一种简单的(如果存在的)算法来找到球体表面上一组点的Voronoi图。源代码会很棒。我是德尔福人(是的,我知道......),但我也吃C代码。
答案 0 :(得分:20)
感谢许多志愿者(特别是Nikolai Nowaczyk和我),现在有更强大/正确的代码用于在Python中处理球体表面上的Voronoi图。这是从scipy版本scipy.spatial.SphericalVoronoi
开始正式提供的0.18
。在官方docs中有一个使用和绘图的工作示例。
该算法遵循二次时间复杂度。虽然对数线性是球体表面上Voronoi图的理论最优值,但这是我们目前能够实现的最佳值。如果您想了解更多信息并帮助开发工作,那么有一些与改进Python处理球形Voronoi图和相关数据结构的方式相关的开放性问题:
有关与此Python代码和相关计算几何工作相关的理论/开发/挑战的进一步背景,您还可以查看来自Nikolai和我的一些演讲:
我实际上最近在球体表面上为Voronoi图编写了一些开源Python代码:https://github.com/tylerjereddy/py_sphere_Voronoi
readthedocs(http://py-sphere-voronoi.readthedocs.org/en/latest/voronoi_utility.html)记录了用法,算法和限制。那里有一些详细的例子,但我也会在下面放一两个。该模块还处理Voronoi区域表面区域的计算,尽管当前开发版本存在一些数字弱点。
我还没有看到很多有关球形Voronoi图的开源实现,但是有一些关于Jason Davies的JavaScript实现的嗡嗡声'网站(http://www.jasondavies.com/maps/voronoi/)。我不认为他的代码是开放的。我还看到一篇关于使用Python来处理部分问题的博客文章(http://jellymatter.com/2014/01/29/voronoi-tessellation-on-the-surface-of-a-sphere-python-code/)。以上帖子中引用的许多主要文献资料似乎都很难实现(我尝试了其中一些)但也许有些人会发现我的实现很有用,甚至建议改进它的方法。
<强>示例:强>
1)为单位球上的伪随机点集生成Voronoi图:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
import scipy as sp
import voronoi_utility
#pin down the pseudo random number generator (prng) object to avoid certain pathological generator sets
prng = np.random.RandomState(117) #otherwise, would need to filter the random data to ensure Voronoi diagram is possible
#produce 1000 random points on the unit sphere using the above seed
random_coordinate_array = voronoi_utility.generate_random_array_spherical_generators(1000,1.0,prng)
#produce the Voronoi diagram data
voronoi_instance = voronoi_utility.Voronoi_Sphere_Surface(random_coordinate_array,1.0)
dictionary_voronoi_polygon_vertices = voronoi_instance.voronoi_region_vertices_spherical_surface()
#plot the Voronoi diagram
fig = plt.figure()
fig.set_size_inches(2,2)
ax = fig.add_subplot(111, projection='3d')
for generator_index, voronoi_region in dictionary_voronoi_polygon_vertices.iteritems():
random_color = colors.rgb2hex(sp.rand(3))
#fill in the Voronoi region (polygon) that contains the generator:
polygon = Poly3DCollection([voronoi_region],alpha=1.0)
polygon.set_color(random_color)
ax.add_collection3d(polygon)
ax.set_xlim(-1,1);ax.set_ylim(-1,1);ax.set_zlim(-1,1);
ax.set_xticks([-1,1]);ax.set_yticks([-1,1]);ax.set_zticks([-1,1]);
plt.tick_params(axis='both', which='major', labelsize=6)
2)计算Voronoi区域多边形的表面积并验证重组表面区域是否合理:
import math
dictionary_voronoi_polygon_surface_areas = voronoi_instance.voronoi_region_surface_areas_spherical_surface()
theoretical_surface_area_unit_sphere = 4 * math.pi
reconstituted_surface_area_Voronoi_regions = sum(dictionary_voronoi_polygon_surface_areas.itervalues())
percent_area_recovery = round((reconstituted_surface_area_Voronoi_regions / theoretical_surface_area_unit_sphere) * 100., 5)
print percent_area_recovery
97.87551 #that seems reasonable for now
答案 1 :(得分:11)
这是关于spherical Voronoi diagrams的论文。
或者如果你想要Fortran(bleah!),那就是this site。
答案 2 :(得分:8)
请注意,球体上的Delaunay三角剖分只是凸包。 因此,您可以计算3D凸包(例如使用CGAL) 并采取双重。
答案 3 :(得分:3)
简而言之,请从cssgrid尝试NCAR Graphics。我写了a longer answer for a similar question at codereview.stackexchange.com。
答案 4 :(得分:3)
有一篇来自INRIA的论文,关于位于球体上的点的Delaunay三角剖分(DT):CAROLI, Manuel, et al. Robust and Efficient Delaunay triangulations of points on or close to a sphere. 2009.,他们在CGAL中讨论了一个实现。
本文提到了DT算法的各种可用实现。
引自论文:
简单而标准的答案在于计算3D凸包 这些点是众所周知的。
用于计算凸包,本文建议:
CGAL的DT C ++类使用方法dual
来获取Voronoi图。
据Monique Teillaud(上述论文的作者之一)this post所述,在我看来,2012年11月的实施还没有准备好。
答案 5 :(得分:3)
问题已经回答已经有一段时间了,但我发现两篇论文在球体表面实现Fortune's algorithm(效率O(N lg N),记忆O(N))。也许将来的观众会发现这些信息很有用。
我现在正在自己解决这些问题,所以我无法解释清楚。基本思想是,只要你正确地计算点的边界抛物线,Fortune的算法就可以在球体的表面上工作。由于球体表面包裹,您还可以使用圆形列表来包含海滩线,而不必担心处理矩形空间边缘的单元格。通过这种方式,您可以从球体的北极向南扫掠并再次向上移动,跳过到将海滩线引入新点(向海滩线添加抛物线)的位置或引入单元顶点(移除来自海滩线的抛物线。)
这两篇论文都期望线性代数具有高水平的舒适度来理解这些概念,并且他们在开始解释算法本身时都会让我失去理智。不幸的是,它们都没有提供源代码。
答案 6 :(得分:2)
我认为每个点的Voronoi平面可以使用非欧几里德几何构造。在2d平面上通常是一条线,现在是球体上的一个“大圆圈”(见维基百科:elliptic geometry)。通过简单地旋转球体使得分割的大圆是赤道,很容易找到哪个点在两个点之间的任何大圆的错误一侧,然后它是另一个半球上的所有点而不是你的点。为...构建Voronoi平面。
这不是完整的答案,但这是我开始的地方..
答案 7 :(得分:1)
有一个很好的Voronoi图示例程序here(包括Delphi 5/6的源代码)。
我认为“球体表面上的点”意味着您首先必须将它们重新映射到2D坐标,创建Voronoi图,然后将它们重新映射到球体表面坐标。 Wikipedia UV mapping article的两个公式是否在这里工作?
另请注意,Voronoi图将具有错误的拓扑结构(它位于矩形内部并且不会“环绕”),这里它可以帮助复制(0,0) - (x,y)中的所有点到(0,-y * 2) - (x,0),低于(0,y) - (x,y * 2),左( - x,0) - (0,y)和右边的相邻区域(x,0) - (x * 2,y)。我希望你知道我的意思,随便问:)
答案 8 :(得分:1)
CGAL正在研究“球形内核”软件包,它可以准确地计算出这些东西。不幸的是,尚未发布,但可能会在下一个版本中发布,因为它们已经mentioned it in a google tech talk in march
答案 9 :(得分:1)
引用此引用:http://www.qhull.org/html/qdelaun.htm
要计算球体上点的Delaunay三角剖分,请计算它们的凸包。如果球体是原点处的单位球体,则facet法线是输入的Voronoi顶点。
答案 10 :(得分:0)
如果你的点在一个半球内,你可以做一个从球面到平面坐标的gnomonic投影,然后进行三角测量,因为大圆变成最短距离的直线。