Algorithm to compute a Voronoi diagram on a sphere? - algorithm

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.

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:
Effort to improve the plotting of spherical polygons in matplotlib
Effort to improve the handling of spherical polygon surface area calculations in scipy
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:
Nikolai PyData London 2016 talk
Tyler PyData London 2015 talk
Tyler PyCon 2016 Computational Geometry tutorial
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)
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

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

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.

In short, try cssgrid from NCAR Graphics. I wrote a longer answer for a similar question at codereview.stackexchange.com.

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:
Hull, a program for convex hulls.
Qhull.
Three-dimensional convex hulls. in FORTRAN.Three-dimensional convex hulls.
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.

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.
"Sweeping the Sphere" by Dinis and Mamede, published in the 2010 International Symposium on Voronoi Diagrams in Science and Engineering. Can be purchased at http://dx.doi.org/10.1109/ISVD.2010.32
"A Plane Sweep Algorithm for the Voronoi Tessellation of the Sphere" by Zheng et al. I'm not sure it was published because of the first one, but it is dated 13 December 2011. It is available for free at http://www.e-lc.org/tmp/Xiaoyu__Zheng_2011_12_05_14_35_11.pdf
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.

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..

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 :)

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

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.

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.

Related

Packing an irregular polygon with different sized circles

I'm trying to write a program in Python with Shapely that takes in shape files (right now congressional districts) and "packs" them with circles. The end goal is to have the center points and radii of the circles. I'd like to cover the maximum area with the least amount of circles.
All of the resources I've found via Google so far are about circle packing within standard geometric objects like squares/circles/triangles etc... So my instinct is to try and turn these shapes into triangles or something and then apply some existing algorithm to the simpler shapes.
Does this seem like the right path for problem solving if the shapes have lots of small concave edges? Or is there some algorithm I haven't been able to find via Google that anyone knows of that does this already?
You might start with this seminal paper, and then move backward & forward in time using Google Scholar:
Bern, Marshall, and David Eppstein. "Quadrilateral meshing by circle packing." International Journal of Computational Geometry & Applications 10.04 (2000): 347-360.
Part of Fig.1
In particular, much of the paper is on packing polygons with circles
to achieve specific properties, e.g.,

Boost::geometry : calculation of the centroid of a polygon

I've been working with the Boost geometry, mostly for manipulating polygons; I was using the centroid built-in method (http://www.boost.org/doc/libs/1_55_0/libs/geometry/doc/html/geometry/reference/algorithms/centroid/centroid_2.html) for calculating the geometric (bary) center of my polygons, but recently after outputting the coordinates of my points (composing a specific polygon) (and analyzing them on the side with some Python scripts) I realized that the centroid coordinates the previous method was giving me do not correspond to the geometric mean of the points of the polygon.
I'm in two dimensions and putting it into equations, I should have:
x_centroid = \frac{1}{number of points composing the polygon} \sum{point i} x_i
and the same for the y coordinates. I'm now suspecting that this could have to do with the fact that the boost geometry library is not just looking at the points on the edge of the polygon (its outer ring) but treating it as a filled object.
Does any of you have some experience in manipulating these functions?
Btw, I using:
point my_center(0,0);
bg::centroid(my_polygon,my_center);
to compute the centroid.
Thank you.
In Boost.Geometry the algorithm proposed by Bashein and Detmer [1] is used by default for the calculation of a centroid of Areal Geometries.
The reason is that the simple average method fails for a case where many closely spaced vertices are placed at one side of a Polygon.
[1] Gerard Bashein and Paul R. Detmer. “Centroid of a Polygon”. Graphics Gems IV, Academic Press, 1994, pp. 3–6
That's what the centroid is -- the mean of the infinite number of points making up the filled polygon. It sounds like what you want is not the centroid, but just the average of the vertices.
Incidentally, "geometric mean" has a different definition than you think, and is not in any way applicable to this situation.
Centroid of polygon is considered as mass center of plane figure (for example, paper sheet), not center of vertices only

reference algorithm for weighted voronoi diagrams?

Can someone point me to a reference implementation on how to construct a (multiplicatively and/or additively) weighted voronoi diagram, which is preferably based on Fortune's voronoi algorithm?
My goal:
Given a set of points(each point has a weight) and a set of boundary edges(usually a rectangle) I want to construct a weighted voronoi diagram using either python or the processing.org-framework. Here is an example.
What I have worked on so far:
So far I have implemented Fortune's algorithm as well as the "centroidal voronoi tessellation" presented in Michael Balzer's paper. Algorithm 3 states how the weights need to be adjusted, however, when I implement this my geometry does not work anymore. To fix this the sweep-line algorithm has to be updated to take weights into account, but I have been unable to do this so far.
Hence I would like to see how other people solved this problem.
For additively weighted Voronoi Diagram: Remember that a power diagram in dimension n is only a(n unweighted) Voronoi diagram in dimension n+1.
For that, just recall that the Voronoi diagram of a point set is invariant if you add any constant to the coordinates, and that the weighted Voronoi diagram can thus be written as a non weighted Voronoi diagram using the coordinates, for example in 2D lifted to 3D:
(x_i, y_i, sqrt(C - w_i))
where w_i is the weight of the seed, and C is any arbitrarily large constant (in practice, one just small enough such that C-w_i is positive).
Once your diagram is computed, just discard the last component.
So, basically, you only need to find a library that is able to handle Voronoi diagrams in dimension n+1 compared to your problem. CGAL can do that. This also makes the implementation extremely easy.
This computation is not easy, but it is available in CGAL. See the manual pages here.
See also the Effective Computational Geometry project, which employs and
supports CGAL:
There is little `off-the-shelf' open source code out there, for the case where distances to the centers are weighted with a multiplicative factor.
To my knowledge, none of the current CGAL packages covers this case.
Takashi Ohyama's beautifully colorful website provides java implementations
http://www.nirarebakun.com/voro/emwvoro.html
for up to 100 points with a SIMPLE algorithm (Euclidean and Manhattan distances).
There is also a paper describing this simple intersection algorithm and an approximate implementation within O(n^3) time, as a plugin to TerraView.
However, I cannot find the source of this plugin in the TerraView / TerraLib repository:
http://www.geoinfo.info/geoinfo2011/papers/mauricio1.pdf
Aurenhammer and Edelsbrunner describe an optimal n^2 time algorithm, but I'm unaware of available code of that.
If you are comfortable digging into Octave, you could reference the code provided in their library.

Remeshing algorithm

I need an algorithm to re-triangulate a given 3D solid object.
Input: A triangular mesh
Output: A new triangular mesh where the triangles - as far as possible - have equal edge lengths. Some tolerance is allowed.
Currently I reflect on a clustering algorithm in order to distribute points
equally over the surface. Then I could use a 2D Delaunay triangulation and
project the triangles to the surface. But this is just a vague idea, not an
algorithm. It would be great if somebody could suggest an algorithm or a
reference to related scientific work.
CGAL provides a surface meshing algorithm that can be used for remeshing.
The documentation page is here.
You can directly try it in the demo. On windows precompiled demo is available here. You'll also need the following dll's.
References to scientific publications are available on the aforementioned page.

Water-tight surface reconstruction algorithm for organized point cloud

I have a 3D Cartesian cube. For each point in this cube there is a corresponding density value. When the density changes suddenly it means that there is a cavity. Now to find the cavity I calculate the gradient at each point in the cube. This gives me a point cloud on the surface of the cavity. I would now like to mesh the surface of the cavity given the point cloud.
Unfortunately I don't have any experience with surface reconstruction and was wondering if someone can recommend a suitable algorithm which will produce a closed surface of the cavity?
The cube is quite big so a point cloud of the surface of a cavity can easily be 500.000 points or more. I have read this post: robust algorithm for surface reconstruction from 3D point cloud? which I find useful. However it seems that the problem I am facing is simpler, given that:
The coordinates of the points are always integer
The point distribution is even
The distance from one point to its closest neighbour is either 1, sqrt(2) or sqrt(3)
You probably want the marching cubes algorithm.
The Marching Cubes algorithm will do exactly what you want. For a working implementation (using Three.js for rendering the graphics), check out:
http://stemkoski.github.com/Three.js/Marching-Cubes.html
For more details on the theory, I think the best article is the website:
http://paulbourke.net/geometry/polygonise/

Resources