Algorithm 球面上Voronoi图的计算算法?

Algorithm 球面上Voronoi图的计算算法?,algorithm,math,geometry,computational-geometry,voronoi,Algorithm,Math,Geometry,Computational Geometry,Voronoi,我正在寻找一个简单的(如果存在的话)算法来找到球面上一组点的Voronoi图。源代码将是伟大的。我是一个Delphi人(是的,我知道…),但我也吃C代码。有一个很好的Voronoi图表示例程序(包括Delphi 5/6的源代码) 我认为“球体表面上的点”意味着首先必须将它们重新映射到2D坐标,创建Voronoi图,然后将它们重新映射到球体表面坐标。这两个公式在这里有效吗 还请注意,Voronoi图的拓扑结构将错误(它位于矩形内,并且不会“环绕”),在这里,它可以帮助将所有点从(0,0)-(x,y

我正在寻找一个简单的(如果存在的话)算法来找到球面上一组点的Voronoi图。源代码将是伟大的。我是一个Delphi人(是的,我知道…),但我也吃C代码。

有一个很好的Voronoi图表示例程序(包括Delphi 5/6的源代码)

我认为“球体表面上的点”意味着首先必须将它们重新映射到2D坐标,创建Voronoi图,然后将它们重新映射到球体表面坐标。这两个公式在这里有效吗

还请注意,Voronoi图的拓扑结构将错误(它位于矩形内,并且不会“环绕”),在这里,它可以帮助将所有点从(0,0)-(x,y)复制到(0,-y*2)-(x,0)上方、下方(0,y)-(x,y*2)、左侧(-x,0)-(0,y)和右侧(x,0)-(x*2,y)的相邻区域。我希望你知道我的意思,请随便问:)

这是一篇关于

或者,如果你摸索Fortran(荒凉!),那就有了


原始链接(死):

正在开发“球形内核”包,该包允许精确计算此类内容。不幸的是,尚未发布,但可能会在下一版本中发布,因为它们已经发布了

我认为每个点的Voronoi平面都可以使用非欧几里德几何构造。通常是二维平面上的一条线,现在是球体上的一个“大圆”(参见维基百科:)。通过简单地旋转球体,使得分割的大圆是赤道,然后它是另一个半球上的所有点,而不是构建Voronoi平面的点,很容易找到两点之间任何大圆的错边


这不是完整的答案,但这是我要开始的地方。

如果你的点在一个半球内,你可以做一个从球面坐标到平面坐标的gnomonic投影,然后三角化,因为大圆变成了距离最短的直线。

简言之,试试看。我写道。

注意,球面上的Delaunay三角剖分就是凸包。 因此,您可以计算3D凸包(例如,使用CGAL)
并从参考资料中引用双引号。

要计算球面上点的Delaunay三角剖分,请计算它们的凸包。如果球体是原点处的单位球体,则镶嵌面法线是输入的Voronoi顶点


INRIA有一篇关于球面上点的Delaunay三角剖分(DT)的论文:他们在这篇文章中讨论了一个在中的实现

本文介绍了DT算法的各种可用实现

引述该报的话:

一个简单而标准的答案在于计算三维凸包 这是出了名的等价点

对于凸壳的计算,本文建议:

  • 在FORTRAN语言中,三维凸面外壳
  • 用FORTRAN语言
  • CdAL的DC++类具有获得Voronoi图的方法。</P>


    根据Monique Teillaud(上述论文的作者之一)的说法,在我看来,2012年11月的实现还没有准备好。

    这个问题已经有一段时间没有得到回答,但我发现有两篇论文在球体表面实现了(效率O(N lg N),内存O(N))。也许未来的观众会发现这些信息很有用

    • Dinis和Mamede在2010年科学与工程Voronoi图国际研讨会上发表的《扫球》。可于
    • Zheng等人的“球面Voronoi细分的平面扫描算法”。我不确定该算法是否因第一个算法而出版,但日期为2011年12月13日。可在以下网址免费获取:
    目前我自己也在研究这些问题,所以我无法很好地解释。基本思想是,只要正确计算点的边界抛物线,福琼的算法就可以在球体的表面上工作。因为球体的曲面是包裹的,所以也可以使用圆形列表来包含海滩线,而不用担心处理矩形空间边缘的单元。使用该选项,可以从球体的北极点向南扫掠,然后再次向上扫掠,跳转到向海滩线引入新点(向海滩线添加抛物线)或引入单元顶点(从海滩线删除抛物线)的场地

    这两篇论文都希望通过线性代数来理解这些概念,而且在开始解释算法本身时,他们都让我不知所措。遗憾的是,两者均未提供源代码。

    2016年7月更新: 多亏了许多志愿者(特别是Nikolai Nowaczyk和我),现在有了更健壮/正确的代码来处理Python中球体表面上的Voronoi图。从scipy的
    0.18
    版本开始,该版本正式以
    scipy.spatial.sphereicalvoronoi提供。在官方网站上有一个使用和绘图的工作示例

    该算法遵循二次时间复杂度。虽然对数线性是球体表面Voronoi图的理论最佳值,但这是目前我们能够实现的最佳值。如果您想了解更多信息并帮助开发工作,那么与改进Python处理球形Voronoi图和相关数据结构的方式相关的一些未决问题如下:

    有关与此Python代码相关的理论/开发/挑战以及相关计算几何工作的进一步背景,您还可以查看Nikolai和I的一些谈话:


    原始答复: 实际上,我最近为球体表面上的Voronoi图编写了一些开源Python代码:

    用法,阿尔戈
    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)
    
    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