CDT  1.3.0
C++ library for constrained Delaunay triangulation
Triangulation.h
Go to the documentation of this file.
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
10#ifndef CDT_vW1vZ0lO8rS4gY4uI4fB
11#define CDT_vW1vZ0lO8rS4gY4uI4fB
12
13#include "CDTUtils.h"
14#include "LocatorKDTree.h"
15
16#include <algorithm>
17#include <cstdlib>
18#include <iterator>
19#include <stack>
20#include <stdexcept>
21#include <utility>
22#include <vector>
23
25namespace CDT
26{
27
30
38{
43 enum Enum
44 {
53 };
54};
55
58{
63 enum Enum
64 {
67 };
68};
69
74{
79 enum Enum
80 {
83 };
84};
85
91typedef unsigned short LayerDepth;
92typedef LayerDepth BoundaryOverlapCount;
93
99
108template <typename T, typename TNearPointLocator = LocatorKDTree<T> >
110{
111public:
112 typedef std::vector<V2d<T> > V2dVec;
116
124 unordered_map<Edge, BoundaryOverlapCount> overlapCount;
125
131 unordered_map<Edge, EdgeVec> pieceToOriginals;
132
133 /*____ API _____*/
140 explicit Triangulation(VertexInsertionOrder::Enum vertexInsertionOrder);
151 VertexInsertionOrder::Enum vertexInsertionOrder,
152 IntersectingConstraintEdges::Enum intersectingEdgesStrategy,
153 T minDistToConstraintEdge);
166 VertexInsertionOrder::Enum vertexInsertionOrder,
167 const TNearPointLocator& nearPtLocator,
168 IntersectingConstraintEdges::Enum intersectingEdgesStrategy,
169 T minDistToConstraintEdge);
182 template <
183 typename TVertexIter,
184 typename TGetVertexCoordX,
185 typename TGetVertexCoordY>
186 void insertVertices(
187 TVertexIter first,
188 TVertexIter last,
189 TGetVertexCoordX getX,
190 TGetVertexCoordY getY);
195 void insertVertices(const std::vector<V2d<T> >& vertices);
216 template <
217 typename TEdgeIter,
218 typename TGetEdgeVertexStart,
219 typename TGetEdgeVertexEnd>
220 void insertEdges(
221 TEdgeIter first,
222 TEdgeIter last,
223 TGetEdgeVertexStart getStart,
224 TGetEdgeVertexEnd getEnd);
236 void insertEdges(const std::vector<Edge>& edges);
257 template <
258 typename TEdgeIter,
259 typename TGetEdgeVertexStart,
260 typename TGetEdgeVertexEnd>
261 void conformToEdges(
262 TEdgeIter first,
263 TEdgeIter last,
264 TGetEdgeVertexStart getStart,
265 TGetEdgeVertexEnd getEnd);
277 void conformToEdges(const std::vector<Edge>& edges);
283 void eraseSuperTriangle();
285 void eraseOuterTriangles();
292 void eraseOuterTrianglesAndHoles();
297 void initializedWithCustomSuperGeometry();
298
304 bool isFinalized() const;
305
319 std::vector<LayerDepth> calculateTriangleDepths() const;
320
327
335 void flipEdge(TriInd iT, TriInd iTopo);
336
337 void flipEdge(
338 TriInd iT,
339 TriInd iTopo,
340 VertInd v1,
341 VertInd v2,
342 VertInd v3,
343 VertInd v4,
344 TriInd n1,
345 TriInd n2,
346 TriInd n3,
347 TriInd n4);
348
354 void removeTriangles(const TriIndUSet& removedTriangles);
355
357 TriIndVec& VertTrisInternal();
359
360private:
361 /*____ Detail __*/
362 void addSuperTriangle(const Box2d<T>& box);
363 void addNewVertex(const V2d<T>& pos, TriInd iT);
364 void insertVertex(VertInd iVert);
365 void insertVertex(VertInd iVert, VertInd walkStart);
366 void ensureDelaunayByEdgeFlips(
367 const V2d<T>& v1,
368 VertInd iV1,
369 std::stack<TriInd>& triStack);
371 std::vector<Edge> insertVertex_FlipFixedEdges(VertInd iV1);
372
374 typedef tuple<IndexSizeType, IndexSizeType, TriInd, TriInd, Index>
375 TriangulatePseudopolygonTask;
376
389 void insertEdge(
390 Edge edge,
391 Edge originalEdge,
392 EdgeVec& remaining,
393 std::vector<TriangulatePseudopolygonTask>& tppIterations);
394
407 void insertEdgeIteration(
408 Edge edge,
409 Edge originalEdge,
410 EdgeVec& remaining,
411 std::vector<TriangulatePseudopolygonTask>& tppIterations);
412
417 IndexSizeType previousEdgeEncounter(
418 const VertInd v,
419 const std::vector<VertInd>& poly) const;
420
422 typedef tuple<Edge, EdgeVec, BoundaryOverlapCount> ConformToEdgeTask;
423
436 void conformToEdge(
437 Edge edge,
438 EdgeVec originals,
439 BoundaryOverlapCount overlaps,
440 std::vector<ConformToEdgeTask>& remaining);
441
453 void conformToEdgeIteration(
454 Edge edge,
455 const EdgeVec& originals,
456 BoundaryOverlapCount overlaps,
457 std::vector<ConformToEdgeTask>& remaining);
458
459 tuple<TriInd, VertInd, VertInd> intersectedTriangle(
460 VertInd iA,
461 const V2d<T>& a,
462 const V2d<T>& b,
463 T orientationTolerance = T(0)) const;
465 std::stack<TriInd> insertVertexInsideTriangle(VertInd v, TriInd iT);
467 std::stack<TriInd> insertVertexOnEdge(VertInd v, TriInd iT1, TriInd iT2);
468 array<TriInd, 2> trianglesAt(const V2d<T>& pos) const;
469 array<TriInd, 2>
470 walkingSearchTrianglesAt(const V2d<T>& pos, VertInd startVertex) const;
471 TriInd walkTriangles(VertInd startVertex, const V2d<T>& pos) const;
474 void edgeFlipInfo(
475 TriInd iT,
476 VertInd iV1,
477 TriInd& iTopo,
478 VertInd& iV2,
479 VertInd& iV3,
480 VertInd& iV4,
481 TriInd& n1,
482 TriInd& n2,
483 TriInd& n3,
484 TriInd& n4);
485 bool isFlipNeeded(
486 const V2d<T>& v,
487 VertInd iV1,
488 VertInd iV2,
489 VertInd iV3,
490 VertInd iV4) const;
491 void changeNeighbor(TriInd iT, TriInd oldNeighbor, TriInd newNeighbor);
492 void changeNeighbor(
493 TriInd iT,
494 VertInd iVedge1,
495 VertInd iVedge2,
496 TriInd newNeighbor);
497 void triangulatePseudopolygon(
498 const std::vector<VertInd>& poly,
499 const std::vector<TriInd>& outerTris,
500 TriInd iT,
501 TriInd iN,
502 std::vector<TriangulatePseudopolygonTask>& iterations);
503 void triangulatePseudopolygonIteration(
504 const std::vector<VertInd>& poly,
505 const std::vector<TriInd>& outerTris,
506 std::vector<TriangulatePseudopolygonTask>& iterations);
507 IndexSizeType findDelaunayPoint(
508 const std::vector<VertInd>& poly,
509 IndexSizeType iA,
510 IndexSizeType iB) const;
511 TriInd addTriangle(const Triangle& t); // note: invalidates iterators!
512 TriInd addTriangle(); // note: invalidates triangle iterators!
518 void finalizeTriangulation(const TriIndUSet& removedTriangles);
519 TriIndUSet growToBoundary(std::stack<TriInd> seeds) const;
520 void fixEdge(const Edge& edge, BoundaryOverlapCount overlaps);
521 void fixEdge(const Edge& edge);
522 void fixEdge(const Edge& edge, const Edge& originalEdge);
529 void makeDummy(TriInd iT);
535 void eraseDummies();
551 unordered_map<TriInd, LayerDepth> peelLayer(
552 std::stack<TriInd> seeds,
553 LayerDepth layerDepth,
554 std::vector<LayerDepth>& triDepths) const;
555
556 void insertVertices_AsProvided(VertInd superGeomVertCount);
557 void insertVertices_Randomized(VertInd superGeomVertCount);
558 void insertVertices_KDTreeBFS(
559 VertInd superGeomVertCount,
560 V2d<T> boxMin,
561 V2d<T> boxMax);
562 bool hasEdge(VertInd a, VertInd b) const;
563 void setAdjacentTriangle(const VertInd v, const TriInd t);
564 void pivotVertexTriangleCW(VertInd v);
565 void removeAdjacentTriangle(VertInd v);
567 void tryAddVertexToLocator(const VertInd v);
570 void tryInitNearestPointLocator();
571
572 std::vector<TriInd> m_dummyTris;
573 TNearPointLocator m_nearPtLocator;
574 std::size_t m_nTargetVerts;
575 SuperGeometryType::Enum m_superGeomType;
576 VertexInsertionOrder::Enum m_vertexInsertionOrder;
577 IntersectingConstraintEdges::Enum m_intersectingEdgesStrategy;
578 T m_minDistToConstraintEdge;
579 TriIndVec m_vertTris;
580};
581
584
585namespace detail
586{
587
590{
591 typedef unsigned long long uint64;
592 uint64 m_state;
593 explicit SplitMix64RandGen(uint64 state)
594 : m_state(state)
595 {}
596 explicit SplitMix64RandGen()
597 : m_state(0)
598 {}
599 uint64 operator()()
600 {
601 uint64 z = (m_state += 0x9e3779b97f4a7c15);
602 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
603 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
604 return z ^ (z >> 31);
605 }
606};
607
608template <class RandomIt>
609void random_shuffle(RandomIt first, RandomIt last)
610{
612 typename std::iterator_traits<RandomIt>::difference_type i, n;
613 n = last - first;
614 for(i = n - 1; i > 0; --i)
615 {
616 std::swap(first[i], first[prng() % (i + 1)]);
617 }
618}
619
620// backport from c++11
621template <class ForwardIt, class T>
622void iota(ForwardIt first, ForwardIt last, T value)
623{
624 while(first != last)
625 {
626 *first++ = value;
627 ++value;
628 }
629}
630
631} // namespace detail
632
633//-----------------------
634// Triangulation methods
635//-----------------------
636template <typename T, typename TNearPointLocator>
637template <
638 typename TVertexIter,
639 typename TGetVertexCoordX,
640 typename TGetVertexCoordY>
642 const TVertexIter first,
643 const TVertexIter last,
644 TGetVertexCoordX getX,
645 TGetVertexCoordY getY)
646{
647 if(isFinalized())
648 {
649 throw std::runtime_error(
650 "Triangulation was finalized with 'erase...' method. Inserting new "
651 "vertices is not possible");
652 }
653
654 const bool isFirstTime = vertices.empty();
655 Box2d<T> box;
656 if(vertices.empty()) // called first time
657 {
658 box = envelopBox<T>(first, last, getX, getY);
659 addSuperTriangle(box);
660 }
661 tryInitNearestPointLocator();
662
663 const VertInd nExistingVerts(vertices.size());
664 const VertInd nVerts(nExistingVerts + std::distance(first, last));
665 // optimization, try to pre-allocate tris
666 triangles.reserve(triangles.size() + 2 * nVerts);
667 vertices.reserve(nVerts);
668 m_vertTris.reserve(nVerts);
669 for(TVertexIter it = first; it != last; ++it)
670 addNewVertex(V2d<T>::make(getX(*it), getY(*it)), noNeighbor);
671
672 switch(m_vertexInsertionOrder)
673 {
675 insertVertices_AsProvided(nExistingVerts);
676 break;
678 isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box.min, box.max)
679 : insertVertices_Randomized(nExistingVerts);
680 break;
681 }
682}
683
684template <typename T, typename TNearPointLocator>
685template <
686 typename TEdgeIter,
687 typename TGetEdgeVertexStart,
688 typename TGetEdgeVertexEnd>
690 TEdgeIter first,
691 const TEdgeIter last,
692 TGetEdgeVertexStart getStart,
693 TGetEdgeVertexEnd getEnd)
694{
695 // state shared between different runs for performance gains
696 std::vector<TriangulatePseudopolygonTask> tppIterations;
697 EdgeVec remaining;
698 if(isFinalized())
699 {
700 throw std::runtime_error(
701 "Triangulation was finalized with 'erase...' method. Inserting new "
702 "edges is not possible");
703 }
704 for(; first != last; ++first)
705 {
706 // +3 to account for super-triangle vertices
707 const Edge edge(
708 VertInd(getStart(*first) + m_nTargetVerts),
709 VertInd(getEnd(*first) + m_nTargetVerts));
710 insertEdge(edge, edge, remaining, tppIterations);
711 }
712 eraseDummies();
713}
714
715template <typename T, typename TNearPointLocator>
716template <
717 typename TEdgeIter,
718 typename TGetEdgeVertexStart,
719 typename TGetEdgeVertexEnd>
721 TEdgeIter first,
722 const TEdgeIter last,
723 TGetEdgeVertexStart getStart,
724 TGetEdgeVertexEnd getEnd)
725{
726 if(isFinalized())
727 {
728 throw std::runtime_error(
729 "Triangulation was finalized with 'erase...' method. Conforming to "
730 "new edges is not possible");
731 }
732 tryInitNearestPointLocator();
733 // state shared between different runs for performance gains
734 std::vector<ConformToEdgeTask> remaining;
735 for(; first != last; ++first)
736 {
737 // +3 to account for super-triangle vertices
738 const Edge e(
739 VertInd(getStart(*first) + m_nTargetVerts),
740 VertInd(getEnd(*first) + m_nTargetVerts));
741 conformToEdge(e, EdgeVec(1, e), 0, remaining);
742 }
743 eraseDummies();
744}
745
746} // namespace CDT
747
748#ifndef CDT_USE_AS_COMPILED_LIBRARY
749#include "Triangulation.hpp"
750#endif
751
752#endif // header-guard
Utilities and helpers.
#define CDT_EXPORT
Export not needed in header-only mode.
Definition: CDTUtils.h:40
Adapter between for KDTree and CDT.
Triangulation class - implementation.
Data structure representing a 2D constrained Delaunay triangulation.
EdgeUSet fixedEdges
triangulation's constraints (fixed edges)
void conformToEdges(TEdgeIter first, TEdgeIter last, TGetEdgeVertexStart getStart, TGetEdgeVertexEnd getEnd)
Ensure that triangulation conforms to constraints (fixed edges)
std::vector< V2d< T > > V2dVec
Vertices vector.
V2dVec vertices
triangulation's vertices
void insertEdges(TEdgeIter first, TEdgeIter last, TGetEdgeVertexStart getStart, TGetEdgeVertexEnd getEnd)
Insert constraints (custom-type fixed edges) into triangulation.
void insertVertices(TVertexIter first, TVertexIter last, TGetVertexCoordX getX, TGetVertexCoordY getY)
Insert custom point-types specified by iterator range and X/Y-getters.
unordered_map< Edge, EdgeVec > pieceToOriginals
Stores list of original edges represented by a given fixed edge.
unordered_map< Edge, BoundaryOverlapCount > overlapCount
Stores count of overlapping boundaries for a fixed edge.
TriangleVec triangles
triangulation's triangles
unsigned short LayerDepth
Type used for storing layer depths for triangles.
Definition: CDT.h:40
Namespace containing triangulation functionality.
std::vector< Edge > EdgeVec
Vector of edges.
Definition: CDTUtils.h:245
unordered_set< Edge > EdgeUSet
Hash table of edges.
Definition: CDTUtils.h:246
std::vector< TriInd > TriIndVec
Vector of triangle indices.
Definition: CDTUtils.h:155
IndexSizeType VertInd
Vertex index.
Definition: CDTUtils.h:142
unordered_set< TriInd > TriIndUSet
Hash table of triangles.
Definition: CDTUtils.h:247
IndexSizeType TriInd
Triangle index.
Definition: CDTUtils.h:144
std::vector< Triangle > TriangleVec
Vector of triangles.
Definition: CDTUtils.h:306
2D bounding box
Definition: CDTUtils.h:162
V2d< T > max
max box corner
Definition: CDTUtils.h:164
V2d< T > min
min box corner
Definition: CDTUtils.h:163
Edge connecting two vertices: vertex with smaller index is always first.
Definition: CDTUtils.h:209
Enum of strategies for treating intersecting constraint edges.
Definition: Triangulation.h:74
@ Ignore
constraint edge intersections are not checked
Definition: Triangulation.h:81
@ Resolve
constraint edge intersections are resolved
Definition: Triangulation.h:82
Enum of what type of geometry used to embed triangulation into.
Definition: Triangulation.h:58
Enum
The Enum itself.
Definition: Triangulation.h:64
@ SuperTriangle
conventional super-triangle
Definition: Triangulation.h:65
@ Custom
user-specified custom geometry (e.g., grid)
Definition: Triangulation.h:66
Triangulation triangle (counter-clockwise winding)
Definition: CDTUtils.h:257
2D vector
Definition: CDTUtils.h:96
Enum of strategies specifying order in which a range of vertices is inserted.
Definition: Triangulation.h:38
@ AsProvided
insert vertices in same order they are provided
Definition: Triangulation.h:52
@ Auto
Automatic insertion order optimized for better performance.
Definition: Triangulation.h:50
SplitMix64 pseudo-random number generator.