计算球体上的 Voronoi 图的算法?

发布于 2024-07-13 05:40:34 字数 97 浏览 16 评论 0 原文

我正在寻找一种简单的(如果存在)算法来查找球体表面上一组点的 Voronoi 图。 源代码会很棒。 我是一个 Delphi 人(是的,我知道......),但我也吃 C 代码。

I'm looking for a simple (if exists) algorithm to find the Voronoi diagram for a set of points on the surface of a sphere. Source code would be great. I'm a Delphi man (yes, I know...), but I eat C-code too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

呆° 2024-07-20 05:40:34

2016 年 7 月更新:

感谢许多志愿者(特别是 Nikolai Nowaczyk 和我),现在有了更强大/正确的代码来处理 Python 中球体表面的 Voronoi 图。 从 scipy 版本 0.18 开始,它以 scipy.spatial.SphericalVoronoi 形式正式提供。 官方文档中有一个使用和绘图的工作示例。

该算法遵循二次时间复杂度。 虽然对数线性是球体表面 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 的网站 (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

Update in July 2016:

Thanks to a number of volunteers (especially Nikolai Nowaczyk and I), there is now far more robust / correct code for handling Voronoi diagrams on the surface of a sphere in Python. This is officially available as scipy.spatial.SphericalVoronoi from version 0.18 of scipy onwards. There's a working example of usage and plotting in the official docs.

The algorithm follows quadratic time complexity. While loglinear is the theoretical optimum for Voronoi diagrams on the surfaces of spheres, this is currently the best we've been able to implement. If you'd like to find out more and help with the development effort there are some open issues related to improving the way Python handles spherical Voronoi diagrams and the related data structures:

For further background on the theory / development / challenges related to this Python code and related computational geometry efforts you can also check out some talks from Nikolai and I:


Original Answer:

I've actually recently written some open source Python code for Voronoi diagrams on the surface of a sphere: https://github.com/tylerjereddy/py_sphere_Voronoi

The usage, algorithm, and limitations are documented on readthedocs (http://py-sphere-voronoi.readthedocs.org/en/latest/voronoi_utility.html). There are some detailed examples there but I'll place one or two below as well. The module also handles the calculation of the Voronoi region surface areas, albeit with some numerical weaknesses in the current development version.

I haven't seen many well-documented open source implementations for spherical Voronoi diagrams, but there has been a bit of buzz about the JavaScript implementation on Jason Davies' website (http://www.jasondavies.com/maps/voronoi/). I don't think his code is open though. I also saw a blog post about using Python to deal with part of the problem (http://jellymatter.com/2014/01/29/voronoi-tessellation-on-the-surface-of-a-sphere-python-code/). Many of the primary literature sources cited in the above posts seemed very challenging to implement (I tried some of them) but maybe some people will find my implementation useful or even suggest ways to improve it.

Examples:

1) Produce a Voronoi diagram for a pseudo-random set of points on the unit sphere:

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)

enter image description here

2) Calculate the surface areas of the Voronoi region polygons and verify that the reconstituted surface area is sensible:

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
一杆小烟枪 2024-07-20 05:40:34

这是一篇关于球形 Voronoi 图的论文。

或者,如果您精通 Fortran(天啊!),那么这个网站

原始链接(已失效): https://people.sc.fsu .edu/~jburkardt/f_src/sxyz_voronoi/sxyz_voronoi.html

Here's a paper on spherical Voronoi diagrams.

Or if you grok Fortran (bleah!) there's this site.

Original link (dead): https://people.sc.fsu.edu/~jburkardt/f_src/sxyz_voronoi/sxyz_voronoi.html

可爱咩 2024-07-20 05:40:34

请注意,球体上的 Delaunay 三角剖分只是凸包。
因此您可以计算 3D 凸包(例如使用 CGAL)
并采取双重。

Notice that Delaunay triangulation on a sphere is just the convex hull.
Thus you can compute the 3D convex hull (e.g. using CGAL)
and take the dual.

避讳 2024-07-20 05:40:34

INRIA 有一篇关于球体上点的 Delaunay 三角测量 (DT) 的论文:CAROLI,Manuel,等人。 对球体上或球体附近的点进行稳健且高效的 Delaunay 三角剖分。 2009 年。 他们讨论了 CGAL 中的实现。

本文参考了 DT 算法的各种可用实现。

引用论文:

一个简单且标准的答案在于计算 3D 凸包
点,这是众所周知的等价。

为了计算凸包,论文建议:

  1. Hull,一个凸包程序。
  2. Qhull
  3. 三维凸包。 FORTRAN 格式。三维凸包。
  4. FORTRAN 语言中的 STRIPACK

CGAL 的 DT C++ 类具有方法 dual 获取 Voronoi 图。

根据这篇文章< /a> 作者:Monique Teillaud(上述论文的作者之一) 在我看来,2012 年 11 月,实施尚未准备就绪。

There is a paper from INRIA about the Delaunay Triangulation (DT) of points lying on a sphere: CAROLI, Manuel, et al. Robust and Efficient Delaunay triangulations of points on or close to a sphere. 2009. where they talk about an implementation in CGAL.

The paper refers to various available implementation of DT algorithms.

Quoting from the paper:

An easy and standard answer consists in computing the 3D convex hull
of the points, which is notoriously equivalent.

for computing the convex hull the paper suggests:

  1. Hull, a program for convex hulls.
  2. Qhull.
  3. Three-dimensional convex hulls. in FORTRAN.Three-dimensional convex hulls.
  4. STRIPACK in FORTRAN.

The DT C++ class of CGAL has the method dual to get the Voronoi Diagram.

According to this post by Monique Teillaud (one of the author of the above mentioned paper) it seems to me that in November 2012 the implementation was not still ready.

初熏 2024-07-20 05:40:34

这个问题已经有一段时间了,但我发现了两篇实现Fortune 算法< /a> (效率 O(N lg N),内存 O(N))在球体表面。 也许未来的观看者会发现这些信息很有用。

我现在正在自己研究它们,所以我无法很好地解释。 基本思想是,只要正确计算点的边界抛物线,《财富》算法就适用于球体表面。 由于球体的表面是包裹的,因此您还可以使用圆形列表来包含海滩线,而不必担心处理矩形空间边缘的单元格。 这样,您可以从球体的北极向南扫过,然后再次返回,跳至向海滩线引入新点(向海滩线添加抛物线)或引入单元顶点(删除单元顶点)的站点。海滩线的抛物线)。

这两篇论文都希望读者能够对线性代数有较高的了解,以理解这些概念,但在开始解释算法本身时,它们都让我迷失了方向。 不幸的是,两者都没有提供源代码。

It's been a while since the question has been answered, but I've found two papers that implement Fortune's algorithm (efficiency O(N lg N), memory O(N)) over the surface of the sphere. Maybe a future viewer will find this information useful.

I'm working through them myself at the moment, so I can't explain it well. The basic idea is that Fortune's algorithm works on the surface of the sphere so long as you calculate the points' bounding parabolas correctly. Because the surface of the sphere wraps, you can also use a circular list to contain the beach line and not worry about handling cells at the edge of rectangular space. With that, you can sweep from the north pole of the sphere to the south and back up again, skipping to sites that introduce new points to the beach line (adding a parabola to the beach line) or the introduction of cell vertices (removing a parabola from the beach line).

Both papers expect a high level of comfort with linear algebra to understand the concepts, and they both keep losing me at the point they start explaining the algorithm itself. Neither provide source code, unfortunately.

治碍 2024-07-20 05:40:34

我认为每个点的 Voronoi 平面可以使用非欧几里德几何构造。 通常是二维平面上的一条线,现在是球体上的一个“大圆”(参见维基百科:椭圆几何)。 很容易找到哪些点位于两点之间的任何大圆的错误一侧,只需旋转球体,使分割大圆为赤道,然后所有点都位于与您所在的点不同的另一个半球上构建 Voronoi 平面。

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

I think the Voronoi plane for each point can be constructed using non-Euclidian geometry. What was normally a line on a 2d plane, is now a 'great circle' on the sphere (see Wikipedia:elliptic geometry). It is easy to find which points are on the wrong side of any great circle between two points, by simply rotating the sphere such that the dividing great circle is the equator, and then it's all points on the other hemisphere than the point you're constructing the Voronoi plane for.

This is not the entire answer, but this is where I'd start..

往事风中埋 2024-07-20 05:40:34

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

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

另请注意,Voronoi 图将具有错误的拓扑(它位于矩形内并且不会“环绕”),这里它可以帮助将 (0,0)-(x, y) 中的所有点复制到邻居上方 (0, -y * 2)-(x, 0)、下方 (0, y)-(x, y * 2)、左侧 (-x, 0)-(0, y) 和右侧 (x, 0)-(x*2,y)。 我希望您明白我的意思,请随时询问:)

There's a nice Voronoi diagram example program here (including source code for Delphi 5/6).

I think "points on the surface of a sphere" means that you first have to remap them to 2D-coordinates, create the Voronoi diagram and then remap them to sphere surface coordinates. Are the two formulas from Wikipedia UV mapping article working here?

Also notice that the Voronoi diagram will have the wrong topology (it is inside a rectangle and does not "wrap around"), here it could help to copy all the points from (0,0)-(x, y) to the neighbour regions above (0, -y * 2)-(x, 0), below (0, y)-(x, y * 2), left (-x, 0)-(0, y) and right (x, 0)-(x*2, y). I hope you know what I mean, feel free to ask :)

将军与妓 2024-07-20 05:40:34

CGAL 正在开发“spherical kernel”包,它可以精确地计算这类事情。 不幸的是,尚未发布,但也许会在下一个版本中发布,因为他们已经在 3 月份的 Google 技术演讲中提到过

CGAL is working on the "spherical kernel" package, which would allow to compute exactly these kind of things. Unfortunately, is not released yet, but maybe it will be in their next release, since they already mentioned it in a google tech talk in march

黑白记忆 2024-07-20 05:40:34

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

If your points are within one hemisphere, you could do a gnomonic projection from spherical to planar coordinates, and then triangulate, since great-circles become straight lines of shortest distance.

情归归情 2024-07-20 05:40:34

引用此参考文献: http://www.qhull.org/html/qdelaun.htm

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

Quoting from this reference: http://www.qhull.org/html/qdelaun.htm

To compute the Delaunay triangulation of points on a sphere, compute their convex hull. If the sphere is the unit sphere at the origin, the facet normals are the Voronoi vertices of the input.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文