Constrained Delaunay triangulation of a set of points in the plane, built one point at a time. More...
#include <XYIncrementalDelaunay.h>
Classes | |
| struct | Point2D |
| A point of the triangulation, held as plain coordinates. More... | |
| struct | Triangle |
| A triangle of the triangulation. More... | |
Public Types | |
| using | Segment = std::pair< std::size_t, std::size_t > |
| A constrained segment, held as a vertex id pair with the smaller id first. | |
Public Member Functions | |
| void | initialize (const std::vector< Point2D > &points, const std::vector< Segment > &segments) |
| Triangulates points and recovers every entry of segments as an edge of the result. | |
| std::size_t | insertPoint (const Point2D &p) |
| Inserts a point, restoring the constrained Delaunay property around it. | |
| void | insertSegment (std::size_t v0, std::size_t v1) |
| Makes the segment between two vertices an edge of the triangulation and records it as constrained, so that later insertions neither remove nor cross it. | |
| std::size_t | numPoints () const |
| const Point2D & | point (std::size_t id) const |
| std::vector< Triangle > | getTriangles () const |
| bool | isConstrainedSegment (std::size_t v0, std::size_t v1) const |
| const std::set< Segment > & | constrainedSegments () const |
| std::vector< std::string > | checkInvariants () const |
| Checks everything this class promises: that every triangle is counter-clockwise, that the neighbor entries agree with each other, that every constrained segment is an edge, and that every edge that is not constrained is locally Delaunay. | |
| std::vector< std::string > | checkEmptyCircumcircle () const |
| Tests every vertex against the circumcircle of every triangle. | |
Static Public Member Functions | |
| static Segment | makeSegment (std::size_t v0, std::size_t v1) |
Static Public Attributes | |
| static constexpr std::size_t | invalid_index = std::numeric_limits<std::size_t>::max() |
| Sentinel for a vertex, triangle or neighbor that does not exist. | |
Private Member Functions | |
| const double * | xy (std::size_t v) const |
| std::size_t | toInternal (std::size_t id) const |
| std::size_t | toCaller (std::size_t v) const |
| bool | isConstrainedEdge (std::size_t v0, std::size_t v1) const |
| unsigned int | localVertexIndex (std::size_t t, std::size_t v) const |
| unsigned int | localEdgeIndex (std::size_t t, const Segment &edge) const |
| bool | containsPoint (std::size_t t, const Point2D &p) const |
| std::size_t | locate (const Point2D &p) const |
| Finds the triangle a point falls in by walking from the triangle the last insertion produced, which keeps the search short when successive points are close together. | |
| void | growCavity (std::size_t seed, std::size_t v_new, std::set< std::size_t > &cavity) const |
| Collects the triangles of the triangulation built so far that have to make way for a new vertex, the Delaunay cavity of its insertion, starting from the triangle it falls in and spreading to every neighbor whose circumcircle contains it. | |
| std::vector< std::size_t > | retriangulate (const std::vector< std::size_t > &removed, const std::vector< std::array< std::size_t, 3 > > &added) |
| Swaps one triangulation of a region for another, reusing the slots of the triangles it removes and rebuilding the neighbor entries both inside the region and along its boundary. | |
| void | triangulatePseudopolygon (std::size_t v_start, std::size_t v_end, const std::vector< std::size_t > &chain, std::size_t first, std::size_t last, std::vector< std::array< std::size_t, 3 > > &triangles) const |
| Triangulates a polygon whose vertices are all visible from one of its edges, which is the shape a recovered segment leaves on either side of itself. | |
| bool | isStrictlyBetween (std::size_t v_first, std::size_t v_mid, std::size_t v_last) const |
| std::string | vertexName (std::size_t v) const |
Static Private Member Functions | |
| static bool | isBounding (std::size_t v) |
Private Attributes | |
| std::vector< Point2D > | _vertices |
| The bounding triangle vertices followed by the caller's points. | |
| std::vector< Triangle > | _triangles |
| The triangles, every one of them live and counter-clockwise. | |
| std::vector< std::size_t > | _vertex_triangle |
| One triangle touching each vertex of _vertices, which is where a walk around it starts. | |
| std::set< Segment > | _constraints |
| The constrained segments, in caller vertex ids with the smaller id first. | |
| std::size_t | _last_triangle = invalid_index |
| A triangle the last insertion produced, which is where the next point walk starts. | |
Static Private Attributes | |
| static constexpr std::size_t | _num_bounding = 3 |
| The number of bounding triangle vertices padding the front of the vertex list. | |
| static constexpr double | _bounding_reach = 1000.0 |
| How far the bounding triangle reaches beyond the points, as a multiple of their extent. | |
Constrained Delaunay triangulation of a set of points in the plane, built one point at a time.
Points are inserted with the Bowyer-Watson construction: the triangle containing the new point is found by walking the triangulation, the Delaunay cavity (the triangles whose circumcircle contains the point) is deleted, and the point is connected to the boundary of that cavity. Constrained segments are edges that the triangulation is required to contain; the Delaunay cavity never grows across one, and a segment that is not an edge once the points are in is recovered by retriangulating the strip of triangles it crosses.
After every insertion no vertex lies strictly inside the circumcircle of any triangle, except where a constrained segment separates the two. Cocircular and collinear configurations are resolved consistently rather than arbitrarily, so the same input always gives the same triangulation. Every geometric decision is made with the exact predicates in framework/contrib/predicates, so no tolerance enters the algorithm.
The triangulation carries no mesh types: points are plain coordinate pairs and triangles are plain index triples, so it can be exercised on its own.
Internally the point set is padded with the three vertices of a bounding triangle that encloses everything, which is what lets the Delaunay cavity of every insertion be a closed polygon. Those three vertices are not part of the caller's point set and never appear in the public interface: the vertex ids used here run from 0 to numPoints() - 1 in the order the points were added, and getTriangles() drops the triangles that touch the bounding triangle.
Definition at line 45 of file XYIncrementalDelaunay.h.
| using XYIncrementalDelaunay::Segment = std::pair<std::size_t, std::size_t> |
A constrained segment, held as a vertex id pair with the smaller id first.
Definition at line 72 of file XYIncrementalDelaunay.h.
| std::vector< std::string > XYIncrementalDelaunay::checkEmptyCircumcircle | ( | ) | const |
Tests every vertex against the circumcircle of every triangle.
This ignores constrained segments, which a vertex is allowed to sit behind, so it is the right criterion only for a triangulation with no constrained segments; use checkInvariants() otherwise.
Definition at line 710 of file XYIncrementalDelaunay.C.
| std::vector< std::string > XYIncrementalDelaunay::checkInvariants | ( | ) | const |
Checks everything this class promises: that every triangle is counter-clockwise, that the neighbor entries agree with each other, that every constrained segment is an edge, and that every edge that is not constrained is locally Delaunay.
A triangulation whose unconstrained edges are all locally Delaunay is a constrained Delaunay triangulation.
Definition at line 643 of file XYIncrementalDelaunay.C.
|
inline |
Definition at line 127 of file XYIncrementalDelaunay.h.
Referenced by XYFrontalDelaunayGenerator::advanceFront(), and XYFrontalDelaunayGenerator::recordSplitBoundaryIds().
|
private |
Definition at line 110 of file XYIncrementalDelaunay.C.
Referenced by locate().
| std::vector< XYIncrementalDelaunay::Triangle > XYIncrementalDelaunay::getTriangles | ( | ) | const |
Definition at line 616 of file XYIncrementalDelaunay.C.
Referenced by XYFrontalDelaunayGenerator::advanceFront(), and XYFrontalDelaunayGenerator::buildTriangleMesh().
|
private |
Collects the triangles of the triangulation built so far that have to make way for a new vertex, the Delaunay cavity of its insertion, starting from the triangle it falls in and spreading to every neighbor whose circumcircle contains it.
Constrained segments stop the spread. A neighbor is also taken in when the shared edge would otherwise produce a triangle of zero or negative area, which is what keeps the cavity star shaped about the vertex.
| seed | The triangle the new vertex falls in |
| v_new | The internal vertex id of the new vertex |
| cavity | Filled with the triangles to remove |
Definition at line 185 of file XYIncrementalDelaunay.C.
Referenced by insertPoint().
| void XYIncrementalDelaunay::initialize | ( | const std::vector< Point2D > & | points, |
| const std::vector< Segment > & | segments | ||
| ) |
Triangulates points and recovers every entry of segments as an edge of the result.
Points are inserted in the order given, so vertex id i refers to points[i]. Any later insertPoint() must lie within the region this call encloses, which is the bounding box of points grown by a large multiple of its own size; the interior points a frontal advance adds always do.
| points | The points to triangulate, which must not contain two identical points |
| segments | The segments the triangulation is required to contain, as vertex id pairs in either order |
Definition at line 346 of file XYIncrementalDelaunay.C.
| std::size_t XYIncrementalDelaunay::insertPoint | ( | const Point2D & | p | ) |
Inserts a point, restoring the constrained Delaunay property around it.
| p | The point to insert |
Definition at line 407 of file XYIncrementalDelaunay.C.
Referenced by XYFrontalDelaunayGenerator::advanceFront(), and initialize().
| void XYIncrementalDelaunay::insertSegment | ( | std::size_t | v0, |
| std::size_t | v1 | ||
| ) |
Makes the segment between two vertices an edge of the triangulation and records it as constrained, so that later insertions neither remove nor cross it.
Doing this to a segment that is already an edge only records the constraint.
A segment that runs exactly through a third vertex cannot be a single edge, and is recorded as the pieces that vertex divides it into rather than as itself.
| v0 | The vertex id of one end of the segment |
| v1 | The vertex id of the other end of the segment |
Definition at line 486 of file XYIncrementalDelaunay.C.
Referenced by initialize(), and insertSegment().
|
inlinestaticprivate |
Definition at line 158 of file XYIncrementalDelaunay.h.
Referenced by getTriangles(), insertPoint(), isConstrainedEdge(), toCaller(), and vertexName().
|
private |
Definition at line 77 of file XYIncrementalDelaunay.C.
Referenced by checkInvariants(), growCavity(), insertPoint(), and insertSegment().
| bool XYIncrementalDelaunay::isConstrainedSegment | ( | std::size_t | v0, |
| std::size_t | v1 | ||
| ) | const |
Definition at line 71 of file XYIncrementalDelaunay.C.
|
private |
Definition at line 121 of file XYIncrementalDelaunay.C.
Referenced by insertSegment().
|
private |
Definition at line 94 of file XYIncrementalDelaunay.C.
Referenced by insertSegment(), and retriangulate().
|
private |
Definition at line 85 of file XYIncrementalDelaunay.C.
Referenced by insertSegment().
|
private |
Finds the triangle a point falls in by walking from the triangle the last insertion produced, which keeps the search short when successive points are close together.
Falls back to a scan of every triangle if the walk leaves the triangulation or fails to settle.
Definition at line 146 of file XYIncrementalDelaunay.C.
Referenced by insertPoint().
|
static |
Definition at line 65 of file XYIncrementalDelaunay.C.
Referenced by XYFrontalDelaunayGenerator::appendLoop(), XYFrontalDelaunayGenerator::buildTriangleMesh(), checkInvariants(), insertPoint(), insertSegment(), isConstrainedEdge(), isConstrainedSegment(), localEdgeIndex(), XYFrontalDelaunayGenerator::recordSplitBoundaryIds(), and retriangulate().
| std::size_t XYIncrementalDelaunay::numPoints | ( | ) | const |
Definition at line 34 of file XYIncrementalDelaunay.C.
Referenced by XYFrontalDelaunayGenerator::advanceFront(), and toInternal().
| const XYIncrementalDelaunay::Point2D & XYIncrementalDelaunay::point | ( | std::size_t | id | ) | const |
Definition at line 59 of file XYIncrementalDelaunay.C.
Referenced by XYFrontalDelaunayGenerator::buildTriangleMesh(), XYFrontalDelaunayGenerator::collectFront(), XYFrontalDelaunayGenerator::hasVertexWithin(), and XYFrontalDelaunayGenerator::placePoint().
|
private |
Swaps one triangulation of a region for another, reusing the slots of the triangles it removes and rebuilding the neighbor entries both inside the region and along its boundary.
| removed | The triangles covering the region, in any order |
| added | The vertices of the triangles to cover it with, counter-clockwise |
Definition at line 238 of file XYIncrementalDelaunay.C.
Referenced by insertSegment().
|
private |
Definition at line 52 of file XYIncrementalDelaunay.C.
Referenced by getTriangles(), growCavity(), insertPoint(), insertSegment(), isConstrainedEdge(), and vertexName().
|
private |
Definition at line 40 of file XYIncrementalDelaunay.C.
Referenced by checkInvariants(), insertSegment(), and point().
|
private |
Triangulates a polygon whose vertices are all visible from one of its edges, which is the shape a recovered segment leaves on either side of itself.
The polygon runs counter-clockwise from v_start to v_end and back along chain[first] to chain[last - 1]. Splitting it at the vertex whose circumcircle holds no other and recursing on the two halves makes it Delaunay.
| v_start | The internal vertex at the start of the edge every vertex sees |
| v_end | The internal vertex at the end of that edge |
| chain | The internal vertices of the rest of the polygon, in counter-clockwise order |
| first | The position in chain where this polygon begins |
| last | One past the position in chain where this polygon ends |
| triangles | Appended with the vertices of the triangles covering the polygon |
Definition at line 315 of file XYIncrementalDelaunay.C.
Referenced by insertSegment(), and triangulatePseudopolygon().
|
private |
Definition at line 138 of file XYIncrementalDelaunay.C.
Referenced by checkEmptyCircumcircle(), and checkInvariants().
|
inlineprivate |
Definition at line 155 of file XYIncrementalDelaunay.h.
Referenced by checkEmptyCircumcircle(), checkInvariants(), containsPoint(), growCavity(), insertPoint(), insertSegment(), isStrictlyBetween(), locate(), and triangulatePseudopolygon().
|
staticconstexprprivate |
How far the bounding triangle reaches beyond the points, as a multiple of their extent.
Definition at line 152 of file XYIncrementalDelaunay.h.
Referenced by initialize().
|
private |
The constrained segments, in caller vertex ids with the smaller id first.
Definition at line 243 of file XYIncrementalDelaunay.h.
Referenced by checkInvariants(), constrainedSegments(), initialize(), insertPoint(), insertSegment(), isConstrainedEdge(), and isConstrainedSegment().
|
private |
A triangle the last insertion produced, which is where the next point walk starts.
Definition at line 246 of file XYIncrementalDelaunay.h.
Referenced by initialize(), and locate().
|
staticconstexprprivate |
The number of bounding triangle vertices padding the front of the vertex list.
Definition at line 149 of file XYIncrementalDelaunay.h.
Referenced by initialize(), isBounding(), numPoints(), toCaller(), and toInternal().
|
private |
The triangles, every one of them live and counter-clockwise.
Definition at line 237 of file XYIncrementalDelaunay.h.
Referenced by checkEmptyCircumcircle(), checkInvariants(), containsPoint(), getTriangles(), growCavity(), initialize(), insertPoint(), insertSegment(), localEdgeIndex(), localVertexIndex(), locate(), and retriangulate().
|
private |
One triangle touching each vertex of _vertices, which is where a walk around it starts.
Definition at line 240 of file XYIncrementalDelaunay.h.
Referenced by initialize(), insertPoint(), insertSegment(), and retriangulate().
|
private |
The bounding triangle vertices followed by the caller's points.
Definition at line 234 of file XYIncrementalDelaunay.h.
Referenced by checkEmptyCircumcircle(), growCavity(), initialize(), insertPoint(), isStrictlyBetween(), numPoints(), point(), and xy().
|
staticconstexpr |
Sentinel for a vertex, triangle or neighbor that does not exist.
Definition at line 49 of file XYIncrementalDelaunay.h.
Referenced by XYFrontalDelaunayGenerator::buildTriangleMesh(), checkInvariants(), XYFrontalDelaunayGenerator::collectFront(), getTriangles(), growCavity(), initialize(), insertPoint(), insertSegment(), locate(), and retriangulate().