Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voronoi diagrams and Delaunay triangulations #1545

Merged
merged 12 commits into from Jul 13, 2016
58 changes: 58 additions & 0 deletions docs/vector/images/halfedge.fig
@@ -0,0 +1,58 @@
#FIG 3.2 Produced by xfig version 3.2.5c
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
5 1 1 2 0 7 50 -1 -1 4.000 0 0 1 0 1395.000 5861.250 1845 5805 1620 6255 1170 6255
2 1 1.00 60.00 120.00
5 1 0 2 0 7 50 -1 -1 4.000 0 0 1 0 5265.000 5343.750 4815 5400 5040 4950 5490 4950
2 1 1.00 60.00 120.00
1 3 0 2 0 0 50 -1 20 4.000 1 0.0000 5355 5625 90 90 5355 5625 5355 5535
1 3 0 1 0 0 50 -1 20 4.000 1 0.0000 1305 5580 90 90 1305 5580 1305 5490
1 3 0 2 0 0 50 -1 20 4.000 1 0.0000 135 7695 90 90 135 7695 135 7605
1 3 0 2 0 0 50 -1 20 4.000 1 0.0000 3375 10395 90 90 3375 10395 3375 10305
1 3 0 2 0 0 50 -1 20 4.000 1 0.0000 6480 7830 90 90 6480 7830 6480 7740
2 1 1 3 0 0 50 -1 20 6.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
1305 5760 180 7560
2 1 2 3 0 0 50 -1 20 3.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
180 3600 1305 5400
2 1 0 3 0 0 50 -1 20 0.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
1530 5490 5130 5490
2 1 1 3 0 0 50 -1 20 4.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
5130 5715 1530 5715
2 1 1 3 0 0 50 -1 20 4.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
6480 7605 5355 5805
2 1 2 3 0 0 50 -1 20 3.000 0 0 7 1 0 2
2 1 1.00 60.00 120.00
5355 5400 6480 3600
2 1 1 3 0 0 50 -1 20 8.000 0 0 -1 1 0 2
2 1 1.00 60.00 120.00
3510 10260 6300 7920
2 1 1 3 0 0 50 -1 20 8.000 0 0 -1 1 0 2
2 1 1.00 60.00 120.00
270 7830 3240 10260
3 0 0 2 0 7 50 -1 -1 4.000 0 1 0 6
2 1 1.00 60.00 120.00
2655 5490 2655 5265 2205 5265 2205 5940 2655 5940 2655 5715
0.000 1.000 1.000 1.000 1.000 0.000
3 0 1 2 0 7 50 -1 -1 4.000 0 1 0 6
2 1 1.00 60.00 120.00
3555 5715 3555 5940 4005 5940 4005 5265 3555 5265 3555 5490
0.000 1.000 1.000 1.000 1.000 0.000
4 0 0 50 -1 4 12 0.0000 0 150 495 1395 6615 f.next\001
4 0 0 50 -1 4 12 0.0000 0 135 540 4860 4680 e.next\001
4 0 0 50 -1 4 12 0.0000 0 150 60 3015 5940 f\001
4 0 0 50 -1 4 12 0.0000 0 105 105 3015 5400 e\001
4 0 0 50 -1 4 12 0.0000 0 195 720 1935 5220 e.flip = f\001
4 0 0 50 -1 4 12 0.0000 0 195 720 3555 6165 f.flip = e\001
4 0 0 50 -1 4 12 0.0000 0 135 840 5535 5580 a = e.vert\001
4 0 0 50 -1 4 12 0.0000 0 150 795 360 5625 b = f.vert\001
Binary file added docs/vector/images/halfedge.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions docs/vector/images/stitch-triangles.fig
@@ -0,0 +1,32 @@
#FIG 3.2 Produced by xfig version 3.2.5c
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 2250 4500 45 45 2250 4500 2295 4500
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 3600 4050 45 45 3600 4050 3645 4050
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 2700 3150 45 45 2700 3150 2745 3150
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 5850 3150 45 45 5850 3150 5895 3150
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 5400 2250 45 45 5400 2250 5445 2250
1 3 0 1 0 0 50 -1 20 0.000 1 0.0000 4050 1350 45 45 4050 1350 4095 1350
1 4 2 1 1 0 51 -1 -1 3.000 1 0.0000 2812 3937 796 796 2700 3150 2925 4725
1 4 2 1 4 0 51 -1 -1 3.000 1 0.0000 3375 3825 2565 2565 4050 1350 2700 6300
1 4 0 2 0 0 50 -1 -1 6.000 1 0.0000 4545 3195 1274 1274 3600 4050 5490 2340
1 4 2 1 0 0 50 -1 -1 3.000 1 0.0000 5175 4725 1714 1714 3600 4050 6750 5400
1 4 2 1 0 0 50 -1 -1 3.000 1 0.0000 4815 3825 1236 1236 3600 4050 6030 3600
1 4 2 1 0 0 50 -1 -1 3.000 1 0.0000 4995 4275 1413 1413 3600 4050 6390 4500
1 4 2 1 0 0 50 -1 -1 3.000 1 0.0000 4680 3375 1198 1198 3690 4050 5670 2700
2 3 0 2 4 0 51 -1 -1 0.000 1 0 -1 0 0 4
4050 1350 5850 3150 5400 2250 4050 1350
2 3 0 2 1 0 51 -1 -1 0.000 1 0 -1 0 0 4
2700 3150 2250 4500 3600 4050 2700 3150
2 1 1 2 0 0 50 -1 -1 6.000 1 0 -1 0 0 2
3600 4050 5850 3150
3 0 0 1 0 0 50 -1 -1 4.000 0 1 0 3
1 1 1.00 60.00 120.00
4860 7200 5130 3870 4230 2340
0.000 1.000 0.000
Binary file added docs/vector/images/stitch-triangles.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions docs/vector/voronoi.md
@@ -0,0 +1,26 @@
# Voronoi Diagrams and Delaunay Triangulations

Voronoi diagrams specify a partitioning of the plane into convex polygonal regions based on an input set of points, with the points being in one-to-one correspondence with the polygons. Given the set of points `P`, let `p` be a point in that set; then `V(p)` is the Voronoi polygon corresponding to `p`. The interior of `V(p)` contains the part of the plane closer to `p` than any other point in `P`.

To compute the Voronoi diagram, one actually goes about creating a triangulation of the input points called the _Delaunay triangulation_. In this structure, all the points in `P` are vertices of a set of non-overlapping triangles that comprise the set `T(P)`. Each triangle `t` in `T(P)` has the property that the unique circle passing through the vertices of `t` has no points of `P` in its interior.

`T(P)` and `V(P)` (with the latter defined as `{V(p) | p in P}`) are _dual_ to each other in the following sense. Each triangle in `T(P)` corresponds to a vertex in `V(P)` (a corner of some `V(p)`), each vertex in `T(P)` (which is just a point in `P`) corresponds to a polygon in `V(P)`, and each edge in `T(P)` corresponds to an edge in `V(P)`. The vertices of `V(P)` are defined as the centers of the circumscribing circles of the triangles in `T(P)`. These vertices are connected by edges such that if `t(p1)` and `t(p2)` share an edge, then the Voronoi vertices corresponding to those two triangles are connected in `V(P)`. This duality between structures is important because it is much easier to compute the Delaunay triangulation and to take its dual than it is to directly compute the Voronoi diagram.

This PR provides a divide-and-conquer approach to computing the Delaunay triangulation based on Guibas and Stolfi's 1985 ACM Transactions on Graphics paper. In this case, the oldies are still the goodies, since only minor performance increases have been achieved over this baseline result---hardly worth the increase in complexity.

The triangulation algorithm starts by ordering vertices according to (ascending) x-coordinate, breaking ties with the y-coordinate. Duplicate vertices are ignored. Then, the right and left halves of the vertices are recursively triangulated. To stitch the resulting triangulations, we find a vertex from each of the left and right results so that the connecting edge is guaranteed to be in the convex hull of the merged triangulations; call this edge `base`. Now, consider a circle that floats upwards and comes into contact with the endpoints of `base`. This bubble will, by changing its radius, squeeze through the gap between the endpoints of `base`, and rise until it encounters another vertex. By definition, this ball has no vertices of `P` in its interior, and so the three points on its boundary are the vertices of a Delaunay triangle. See the following image for clarification:
<center>
![Merging Delaunay triangulations](images/stitch-triangles.png)
</center>
Here, we note that the red triangle's circumscribing ball contains vertices of the blue triangle, and so we will expect that the red triangle will not be part of the final triangulation. As such the leftmost edge of the red triangle be deleted before the triangulation can be updated to include the triangle circumscribed by the solid black circle.

This process continues, with the newly created edge serving as the new `base`, and the ball rising through until another vertex is encountered and so on, until the ball exits out the top and the triangulation is complete.

## Mesh Representation

The output of Delaunay triangulation and Voronoi diagrams are in the form of meshes represented by the half-edge structure. These structures can be thought of as directed edges between points in space, where an edge needs two half-edges to complete its representation. A half-edge, `e`, has three vital pieces of information: a vertex to which it points, `e.vert`; a pointer to its complementary half-edge, `e.flip`; and a pointer to the next half-edge in the polygon, `e.next`. The following image might be useful:
<center>
![Half-edge structure](images/halfedge.png)
</center>

Note that half-edges are only useful for representing orientable manifolds with boundary. As such, half edge structures couldn't be used to represent a Moebius strip, nor could they be used for meshes where two polygons share a vertex without sharing an edge. Furthermore, by convention, polygon edges are wound in counter-clockwise order. We also allow each half-edge to point to an attribute structure for the face that it bounds. In the case of a Delaunay triangle, that face attribute would be the circumscribing circle's center; edges on the boundary of a mesh have no face attribute (they are stored as `Option[F]` where `F` is the type of the face attribute).
17 changes: 17 additions & 0 deletions util/src/main/scala/geotrellis/util/Constants.scala
@@ -0,0 +1,17 @@
package geotrellis.util

object Constants {
/**
* Defines machine epsilon for double-precision floating point ops. This is,
* roughly speaking, the minimum distance between distinct floating point numbers.
* Double values closer than DOUBLE_EPSILON should be considered identical.
*/
val DOUBLE_EPSILON = 1.11e-16

/**
* Defines machine epsilon for single-precision floating point ops. This is,
* roughly speaking, the minimum distance between distinct floating point numbers.
* Float values closer than FLOAT_EPSILON should be considered identical.
*/
val FLOAT_EPSILON = 5.96e-8
}