CDT  2.0.1
C++ library for constrained Delaunay triangulation
Loading...
Searching...
No Matches
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
9
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 <string>
22#include <utility>
23#include <vector>
24
26namespace CDT
27{
28
31
38struct CDT_EXPORT VertexInsertionOrder
39{
44 enum Enum
45 {
54 };
55};
56
61{
76};
77
81struct CDT_EXPORT RefinementCriterion
82{
92};
93
104struct CDT_EXPORT Unrefined
105{
114 std::size_t sharpFixedCorner;
116 std::size_t shortEdges;
121
123 Unrefined();
124};
125
131typedef unsigned short LayerDepth;
132typedef LayerDepth BoundaryOverlapCount;
133
138{
139public:
141 SourceLocation(const std::string& file, const std::string& func, int line)
142 : m_file(file)
143 , m_func(func)
144 , m_line(line)
145 {}
146
147 const std::string& file() const
148 {
149 return m_file;
150 }
151
152 const std::string& func() const
153 {
154 return m_func;
155 }
156
157 int line() const
158 {
159 return m_line;
160 }
161
162private:
163 std::string m_file;
164 std::string m_func;
165 int m_line;
166};
167
169#define CDT_SOURCE_LOCATION \
170 SourceLocation(std::string(__FILE__), std::string(__func__), __LINE__)
171
176class CDT_EXPORT Error : public std::runtime_error
177{
178public:
180 Error(const std::string& description, const SourceLocation& srcLoc)
181 : std::runtime_error(
182 description + "\nin '" + srcLoc.func() + "' at " + srcLoc.file() +
183 ":" + CDT::to_string(srcLoc.line()))
184 , m_description(description)
185 , m_srcLoc(srcLoc)
186 {}
187
188 virtual ~Error() CDT_NOEXCEPT
189 {}
190
191 const std::string& description() const
192 {
193 return m_description;
194 }
195
197 {
198 return m_srcLoc;
199 }
200
201private:
202 std::string m_description;
203 SourceLocation m_srcLoc;
204};
205
210class CDT_EXPORT FinalizedError : public Error
211{
212public:
215 : Error(
216 "Triangulation was finalized with 'erase...' method. Further "
217 "modification is not possible.",
218 srcLoc)
219 {}
220};
221
225class CDT_EXPORT DuplicateVertexError : public Error
226{
227public:
230 const VertInd v1,
231 const VertInd v2,
232 const SourceLocation& srcLoc)
233 : Error(
234 "Duplicate vertex detected: #" + CDT::to_string(v1) +
235 " is a duplicate of #" + CDT::to_string(v2),
236 srcLoc)
237 , m_v1(v1)
238 , m_v2(v2)
239 {}
240
241 VertInd v1() const
242 {
243 return m_v1;
244 }
245
246 VertInd v2() const
247 {
248 return m_v2;
249 }
250
251private:
252 VertInd m_v1, m_v2;
253};
254
259class CDT_EXPORT IntersectingConstraintsError : public Error
260{
261public:
264 const Edge& e1,
265 const Edge& e2,
266 const SourceLocation& srcLoc)
267 : Error(
268 "Intersecting constraint edges detected: (" +
269 CDT::to_string(e1.v1()) + ", " + CDT::to_string(e1.v2()) +
270 ") intersects (" + CDT::to_string(e2.v1()) + ", " +
271 CDT::to_string(e2.v2()) + ")",
272 srcLoc)
273 , m_e1(e1)
274 , m_e2(e2)
275 {}
276
277 const Edge& e1() const
278 {
279 return m_e1;
280 }
281
282 const Edge& e2() const
283 {
284 return m_e2;
285 }
286
287private:
288 Edge m_e1, m_e2;
289};
290
296class CDT_EXPORT InvalidEdgeSplitVertex : public Error
297{
298public:
301 const Edge& e1,
302 const Edge& e2,
303 const SourceLocation& srcLoc)
304 : Error(
305 "Intersection of constraint edges (" + CDT::to_string(e1.v1()) +
306 ", " + CDT::to_string(e1.v2()) + ") and (" +
307 CDT::to_string(e2.v1()) + ", " + CDT::to_string(e2.v2()) +
308 ") can not be resolved: computed split vertex is invalid",
309 srcLoc)
310 , m_e1(e1)
311 , m_e2(e2)
312 {}
313
314 const Edge& e1() const
315 {
316 return m_e1;
317 }
318
319 const Edge& e2() const
320 {
321 return m_e2;
322 }
323
324private:
325 Edge m_e1, m_e2;
326};
327
328class CDT_EXPORT AccessingInvalidIndex : public Error
329{
330public:
331 AccessingInvalidIndex(const SourceLocation& srcLoc)
332 : Error("Accessing invalid index", srcLoc)
333 {}
334};
335
336template <typename TIndex>
337class CDT_EXPORT OptionalIndex
338{
339public:
340 OptionalIndex(const TIndex index)
341 : m_index(index)
342 {}
343 bool hasValue() const
344 {
345 return m_index != TIndex(invalidIndexSizeType);
346 }
347 TIndex value() const
348 {
349 if(!hasValue())
350 handleException(AccessingInvalidIndex(CDT_SOURCE_LOCATION));
351 return m_index;
352 }
353
354private:
355 TIndex m_index;
356};
357
360
384
385#ifdef CDT_ENABLE_CALLBACK_HANDLER
386
390struct CDT_EXPORT TriangleChangeType
391{
401};
402
403// parameter names are used for documentation purposes, even if they are un-used
404// in the interface's default implementation
405#pragma GCC diagnostic push
406#pragma GCC diagnostic ignored "-Wunused-parameter"
407
412class CDT_EXPORT ICallbackHandler
413{
414public:
417 {}
418
424 virtual void onAddSuperTriangle()
425 {}
426
437 const TriInd iRepurposedTri,
438 const TriInd iNewTri1,
439 const TriInd iNewTri2)
440 {}
441
454 const TriInd iRepurposedTri1,
455 const TriInd iRepurposedTri2,
456 const TriInd iNewTri1,
457 const TriInd iNewTri2)
458 {}
459
465 virtual void onFlipEdge(const TriInd iT, const TriInd iTopo)
466 {}
467
473 virtual void
474 onAddVertexStart(const VertInd iV, const AddVertexType::Enum vertexType)
475 {}
476
481 virtual void onAddEdgeStart(const Edge& edge)
482 {}
483
490 virtual void onReTriangulatePolygon(const std::vector<TriInd>& tris)
491 {}
492
497 virtual bool isAbortCalculation() const
498 {
499 return false;
500 };
501};
502
503// parameter names are used for documentation purposes, even if they are
504// un-used in the interface's default implementation
505#pragma GCC diagnostic pop
506
507#endif
508
514
523template <typename T, typename TNearPointLocator = LocatorKDTree<T> >
524class CDT_EXPORT Triangulation
525{
526public:
527 typedef std::vector<V2d<T> > V2dVec;
531
539 unordered_map<Edge, BoundaryOverlapCount> overlapCount;
540
546 unordered_map<Edge, EdgeVec> pieceToOriginals;
547
548 /*____ API _____*/
555 explicit Triangulation(VertexInsertionOrder::Enum vertexInsertionOrder);
566 VertexInsertionOrder::Enum vertexInsertionOrder,
567 IntersectingConstraintEdges::Enum intersectingEdgesStrategy,
568 T minDistToConstraintEdge);
581 VertexInsertionOrder::Enum vertexInsertionOrder,
582 const TNearPointLocator& nearPtLocator,
583 IntersectingConstraintEdges::Enum intersectingEdgesStrategy,
584 T minDistToConstraintEdge);
599 template <
600 typename TVertexIter,
601 typename TGetVertexCoordX,
602 typename TGetVertexCoordY>
603 void insertVertices(
604 TVertexIter first,
605 TVertexIter last,
606 TGetVertexCoordX getX,
607 TGetVertexCoordY getY);
614 void insertVertices(const std::vector<V2d<T> >& vertices);
649 template <
650 typename TEdgeIter,
651 typename TGetEdgeVertexStart,
652 typename TGetEdgeVertexEnd>
653 void insertEdges(
654 TEdgeIter first,
655 TEdgeIter last,
656 TGetEdgeVertexStart getStart,
657 TGetEdgeVertexEnd getEnd);
683 void insertEdges(const std::vector<Edge>& edges);
718 template <
719 typename TEdgeIter,
720 typename TGetEdgeVertexStart,
721 typename TGetEdgeVertexEnd>
722 void conformToEdges(
723 TEdgeIter first,
724 TEdgeIter last,
725 TGetEdgeVertexStart getStart,
726 TGetEdgeVertexEnd getEnd);
752 void conformToEdges(const std::vector<Edge>& edges);
771 VertInd maxVerticesToInsert,
772 RefinementCriterion::Enum refinementCriterion =
774 T refinementThreshold = degToRad(T(20)),
775 TriIndUSet* toEraseOrNull = NULL,
776 T minEdgeLength = T(1e-6));
799 RefinementCriterion::Enum refinementCriterion =
801 T refinementThreshold = degToRad(T(20))) const;
811 void eraseOuterTriangles();
847 void finalizeTriangulation(const TriIndUSet& removedTriangles);
848
854 bool isFinalized() const;
855
869 std::vector<LayerDepth> calculateTriangleDepths() const;
870
871#ifdef CDT_ENABLE_CALLBACK_HANDLER
879 void setCallbackHandler(ICallbackHandler* callbackHandler);
880#endif
887
895 void flipEdge(TriInd iT, TriInd iTopo);
896
901 void flipEdge(
902 TriInd iT,
903 TriInd iTopo,
904 VertInd v1,
905 VertInd v2,
906 VertInd v3,
907 VertInd v4,
908 TriInd n1,
909 TriInd n2,
910 TriInd n3,
911 TriInd n4);
912
918 void removeTriangles(const TriIndUSet& removedTriangles);
919
923 const TriIndVec& VertTrisInternal() const;
925
926private:
927 /*____ Detail __*/
928 void addSuperTriangle(const Box2d<T>& box);
929 void addNewVertex(const V2d<T>& pos, TriInd iT);
930 void insertVertex(VertInd iVert);
931 void insertVertex(VertInd iVert, VertInd walkStart);
932 void ensureDelaunayByEdgeFlips(VertInd iV1, std::stack<TriInd>& triStack);
934 std::vector<Edge> insertVertex_FlipFixedEdges(VertInd iV1);
935
937 typedef tuple<IndexSizeType, IndexSizeType, TriInd, TriInd, Index>
938 TriangulatePseudoPolygonTask;
939
952 void insertEdge(
953 Edge edge,
954 Edge originalEdge,
955 EdgeVec& remaining,
956 std::vector<TriangulatePseudoPolygonTask>& tppIterations);
957
970 void insertEdgeIteration(
971 Edge edge,
972 Edge originalEdge,
973 EdgeVec& remaining,
974 std::vector<TriangulatePseudoPolygonTask>& tppIterations);
975
977 typedef tuple<Edge, EdgeVec, BoundaryOverlapCount> ConformToEdgeTask;
978
991 void conformToEdge(
992 Edge edge,
993 EdgeVec originals,
994 BoundaryOverlapCount overlaps,
995 std::vector<ConformToEdgeTask>& remaining);
996
1008 void conformToEdgeIteration(
1009 Edge edge,
1010 const EdgeVec& originals,
1011 BoundaryOverlapCount overlaps,
1012 std::vector<ConformToEdgeTask>& remaining);
1013
1014 tuple<TriInd, VertInd, VertInd> intersectedTriangle(
1015 VertInd iA,
1016 const V2d<T>& a,
1017 const V2d<T>& b,
1018 T orientationTolerance = T(0)) const;
1020 std::stack<TriInd> insertVertexInsideTriangle(VertInd v, TriInd iT);
1022 std::stack<TriInd> insertVertexOnEdge(
1023 VertInd v,
1024 TriInd iT1,
1025 TriInd iT2,
1026 const bool doHandleFixedSplitEdge = false);
1027 array<TriInd, 2> trianglesAt(const V2d<T>& pos) const;
1028 array<TriInd, 2>
1029 walkingSearchTrianglesAt(VertInd iV, VertInd startVertex) const;
1033 OptionalTriInd walkTriangles(VertInd startVertex, const V2d<T>& pos) const;
1036 void edgeFlipInfo(
1037 TriInd iT,
1038 VertInd iV1,
1039 TriInd& iTopo,
1040 VertInd& iV2,
1041 VertInd& iV3,
1042 VertInd& iV4,
1043 TriInd& n1,
1044 TriInd& n2,
1045 TriInd& n3,
1046 TriInd& n4);
1047 bool isFlipNeeded(
1048 VertInd iV1,
1049 VertInd iV2,
1050 VertInd iV3,
1051 VertInd iV4,
1052 const bool doFlipFixedEdges = false) const;
1054 bool isSameOriginalEdge(const Edge& e1, const Edge& e2) const;
1055 bool isRefinementNeeded(
1056 const Triangle& tri,
1057 RefinementCriterion::Enum refinementCriterion,
1058 T refinementThreshold) const;
1061 bool isSmallestAngleFixed(const Triangle& tri) const;
1063 bool isEdgeEncroached(const Edge& edge) const;
1064 bool isEdgeEncroachedBy(const Edge& edge, const V2d<T>& v) const;
1069 EdgeVec edgesEncroachedBy(const V2d<T>& v, TriInd iT) const;
1071 TriIndVec resolveEncroachedEdges(
1072 EdgeQueue encroachedEdges,
1073 VertInd& newVertBudget,
1074 VertInd steinerVerticesOffset,
1075 const V2d<T>* circumcenterOrNull,
1076 RefinementCriterion::Enum refinementCriterion,
1077 T badTriangleThreshold,
1078 TriIndUSet* toEraseOrNull,
1079 T minEdgeLength,
1080 Unrefined& unrefined);
1081 OptionalVertInd splitEncroachedEdge(
1082 Edge edge,
1083 VertInd steinerVerticesOffset,
1084 TriIndUSet* toEraseOrNull,
1085 Unrefined& unrefined);
1086 void changeNeighbor(TriInd iT, TriInd oldNeighbor, TriInd newNeighbor);
1087 void changeNeighbor(
1088 TriInd iT,
1089 VertInd iVedge1,
1090 VertInd iVedge2,
1091 TriInd newNeighbor);
1092 void triangulatePseudoPolygon(
1093 const std::vector<VertInd>& poly,
1094 unordered_map<Edge, TriInd>& outerTris,
1095 TriInd iT,
1096 TriInd iN,
1097 std::vector<TriInd>& trianglesToReuse,
1098 std::vector<TriangulatePseudoPolygonTask>& iterations);
1099 void triangulatePseudoPolygonIteration(
1100 const std::vector<VertInd>& poly,
1101 unordered_map<Edge, TriInd>& outerTris,
1102 std::vector<TriInd>& trianglesToReuse,
1103 std::vector<TriangulatePseudoPolygonTask>& iterations);
1104 IndexSizeType findDelaunayPoint(
1105 const std::vector<VertInd>& poly,
1106 IndexSizeType iA,
1107 IndexSizeType iB) const;
1108 TriInd addTriangle(const Triangle& t);
1109 TriInd addTriangle();
1110 VertInd verticesCount() const;
1111 TriInd trianglesCount() const;
1112 TriIndUSet growToBoundary(std::stack<TriInd> seeds) const;
1113 void fixEdge(const Edge& edge);
1114 void fixEdge(const Edge& edge, const Edge& originalEdge);
1120 void splitFixedEdge(const Edge& edge, const VertInd iSplitVert);
1131 VertInd addSplitEdgeVertex(
1132 const Edge& edge,
1133 const V2d<T>& splitVert,
1134 const TriInd iT,
1135 const TriInd iTopo,
1136 const AddVertexType::Enum vertexType);
1149 OptionalVertInd splitFixedEdgeAt(
1150 const Edge& edge,
1151 const V2d<T>& splitVert,
1152 const TriInd iT,
1153 const TriInd iTopo,
1154 const AddVertexType::Enum vertexType);
1168 bool isEdgeSplitVertexValid(
1169 const V2d<T>& splitVert,
1170 TriInd iT,
1171 TriInd iTopo) const;
1179 Edge originalInputEdge(const Edge& e) const;
1187 const Triangle& triangleAt(TriInd iT) const;
1203 unordered_map<TriInd, LayerDepth> peelLayer(
1204 std::stack<TriInd> seeds,
1205 LayerDepth layerDepth,
1206 std::vector<LayerDepth>& triDepths) const;
1207
1208 void insertVertices_AsProvided(VertInd superGeomVertCount);
1209 void insertVertices_Randomized(VertInd superGeomVertCount);
1210 void insertVertices_KDTreeBFS(VertInd superGeomVertCount, Box2d<T> box);
1211 std::pair<TriInd, TriInd> edgeTriangles(VertInd a, VertInd b) const;
1212 bool hasEdge(VertInd a, VertInd b) const;
1213 bool
1214 hasAnotherFixedEdgeAtSmallAngle(VertInd v, const Edge& excludeEdge) const;
1215 void setAdjacentTriangle(const VertInd v, const TriInd t);
1216 void pivotVertexTriangleCW(VertInd v);
1218 void tryAddVertexToLocator(const VertInd v);
1221 void tryInitNearestPointLocator();
1222
1223 TNearPointLocator m_nearPtLocator;
1224 VertexInsertionOrder::Enum m_vertexInsertionOrder;
1225 IntersectingConstraintEdges::Enum m_intersectingEdgesStrategy;
1226 T m_minDistToConstraintEdge;
1227 TriIndVec m_vertTris;
1228#ifdef CDT_ENABLE_CALLBACK_HANDLER
1229 ICallbackHandler* m_callbackHandler;
1230#endif
1231};
1232
1235
1236namespace detail
1237{
1238
1241{
1242 typedef unsigned long long uint64;
1246 : m_state(state)
1247 {}
1248
1250 : m_state(0)
1251 {}
1252
1254 {
1255 uint64 z = (m_state += 0x9e3779b97f4a7c15);
1256 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
1257 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
1258 return z ^ (z >> 31);
1259 }
1260};
1261
1263template <class RandomIt>
1264void random_shuffle(RandomIt first, RandomIt last)
1265{
1267 typename std::iterator_traits<RandomIt>::difference_type i, n;
1268 n = last - first;
1269 for(i = n - 1; i > 0; --i)
1270 {
1271 std::swap(first[i], first[prng() % (i + 1)]);
1272 }
1273}
1274
1276template <class ForwardIt, class T>
1277void iota(ForwardIt first, ForwardIt last, T value)
1278{
1279 while(first != last)
1280 {
1281 *first++ = value;
1282 ++value;
1283 }
1284}
1285
1286} // namespace detail
1287
1288//-----------------------
1289// Triangulation methods
1290//-----------------------
1291template <typename T, typename TNearPointLocator>
1292template <
1293 typename TVertexIter,
1294 typename TGetVertexCoordX,
1295 typename TGetVertexCoordY>
1297 const TVertexIter first,
1298 const TVertexIter last,
1299 TGetVertexCoordX getX,
1300 TGetVertexCoordY getY)
1301{
1302 if(isFinalized())
1303 handleException(FinalizedError(CDT_SOURCE_LOCATION));
1304
1305 const bool isFirstTime = vertices.empty();
1306
1307 //
1308 // performance optimization: pre-allocate triangles and vertices
1309 //
1310 const std::size_t nNewVertices = std::distance(first, last);
1311 std::size_t exactCapacityTriangles = triangles.size() + 2 * nNewVertices;
1312 std::size_t exactCapacityVertices = vertices.size() + nNewVertices;
1313 if(isFirstTime) // account for adding super-triangle on the first run
1314 {
1315 exactCapacityTriangles += 1;
1316 exactCapacityVertices += nSuperTriVerts;
1317 }
1318 std::size_t capacityTriangles = exactCapacityTriangles;
1319 std::size_t capacityVertices = exactCapacityVertices;
1320 // to avoid re-allocation and unused memory
1321 // over-allocate by a fixed factor
1322 // when constraint edge intersections are resolved and vertices are many
1323 // because vertex is added for each intersection
1324 // and total number of intersections is unknown
1325 const VertInd overAllocationVerticesThreshold(1000);
1326 const std::size_t overAllocationFraction(10);
1327 const bool isOverPreAllocated =
1328 m_intersectingEdgesStrategy ==
1330 VertInd(nNewVertices) >= overAllocationVerticesThreshold;
1331 if(isOverPreAllocated)
1332 {
1333 capacityTriangles += capacityTriangles / overAllocationFraction;
1334 capacityVertices += capacityVertices / overAllocationFraction;
1335 }
1336 triangles.reserve(capacityTriangles);
1337 vertices.reserve(capacityVertices);
1338 m_vertTris.reserve(capacityVertices);
1339
1340 Box2d<T> box;
1341 if(isFirstTime)
1342 {
1343 box.envelopPoints(first, last, getX, getY);
1344 addSuperTriangle(box);
1345 }
1346 tryInitNearestPointLocator();
1347 const VertInd nExistingVerts = verticesCount();
1348
1349 for(TVertexIter it = first; it != last; ++it)
1350 addNewVertex(V2d<T>(getX(*it), getY(*it)), noNeighbor);
1351
1352 switch(m_vertexInsertionOrder)
1353 {
1355 insertVertices_AsProvided(nExistingVerts);
1356 break;
1358 isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box)
1359 : insertVertices_Randomized(nExistingVerts);
1360 break;
1361 }
1362
1363// make sure pre-allocation was correct
1364#ifdef CDT_ENABLE_CALLBACK_HANDLER
1365 assert(
1366 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1367 (vertices.size() == exactCapacityVertices));
1368 assert(
1369 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1370 (triangles.size() == exactCapacityTriangles));
1371#else
1372 assert(vertices.size() == exactCapacityVertices);
1373 assert(triangles.size() == exactCapacityTriangles);
1374#endif
1375}
1376
1377template <typename T, typename TNearPointLocator>
1378template <
1379 typename TEdgeIter,
1380 typename TGetEdgeVertexStart,
1381 typename TGetEdgeVertexEnd>
1383 TEdgeIter first,
1384 const TEdgeIter last,
1385 TGetEdgeVertexStart getStart,
1386 TGetEdgeVertexEnd getEnd)
1387{
1388 if(isFinalized())
1389 handleException(FinalizedError(CDT_SOURCE_LOCATION));
1390
1391 std::vector<TriangulatePseudoPolygonTask> tppIterations;
1392 EdgeVec remaining;
1393 for(; first != last; ++first)
1394 {
1395#ifdef CDT_ENABLE_CALLBACK_HANDLER
1396 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1397 {
1398 return;
1399 }
1400#endif
1401 // +3 to account for super-triangle vertices
1402 const Edge edge(
1403 VertInd(getStart(*first) + nSuperTriVerts),
1404 VertInd(getEnd(*first) + nSuperTriVerts));
1405 insertEdge(edge, edge, remaining, tppIterations);
1406 }
1407}
1408
1409template <typename T, typename TNearPointLocator>
1410template <
1411 typename TEdgeIter,
1412 typename TGetEdgeVertexStart,
1413 typename TGetEdgeVertexEnd>
1415 TEdgeIter first,
1416 const TEdgeIter last,
1417 TGetEdgeVertexStart getStart,
1418 TGetEdgeVertexEnd getEnd)
1419{
1420 if(isFinalized())
1421 handleException(FinalizedError(CDT_SOURCE_LOCATION));
1422
1423 tryInitNearestPointLocator();
1424 // state shared between different runs for performance gains
1425 std::vector<ConformToEdgeTask> remaining;
1426 for(; first != last; ++first)
1427 {
1428#ifdef CDT_ENABLE_CALLBACK_HANDLER
1429 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1430 {
1431 return;
1432 }
1433#endif
1434 // +3 to account for super-triangle vertices
1435 const Edge e(
1436 VertInd(getStart(*first) + nSuperTriVerts),
1437 VertInd(getEnd(*first) + nSuperTriVerts));
1438 conformToEdge(e, EdgeVec(1, e), 0, remaining);
1439 }
1440}
1441
1442} // namespace CDT
1443
1444#ifndef CDT_USE_AS_COMPILED_LIBRARY
1445#include "Triangulation.hpp"
1446#endif
1447
1448#endif // header-guard
Utilities and helpers.
Adapter between for KDTree and CDT.
void random_shuffle(RandomIt first, RandomIt last)
backport from c++11
void iota(ForwardIt first, ForwardIt last, T value)
backport from c++11
Triangulation class - implementation.
VertInd v2() const
second duplicate
VertInd v1() const
first duplicate
DuplicateVertexError(const VertInd v1, const VertInd v2, const SourceLocation &srcLoc)
Constructor.
virtual ~Error() CDT_NOEXCEPT
Destructor.
const SourceLocation & sourceLocation() const
Get source location from where the error was thrown.
Error(const std::string &description, const SourceLocation &srcLoc)
Constructor.
const std::string & description() const
Get error description.
Error thrown when triangulation modification is attempted after it was finalized.
FinalizedError(const SourceLocation &srcLoc)
Constructor.
Interface for the callback handler that user can derive from and inject into the triangulation to mon...
virtual void onAddSuperTriangle()
Called when super-triangle is added.
virtual void onInsertVertexOnEdge(const TriInd iRepurposedTri1, const TriInd iRepurposedTri2, const TriInd iNewTri1, const TriInd iNewTri2)
Called when inserted vertex is on an edge.
virtual bool isAbortCalculation() const
Tells whether the user wants to abort the triangulation at the earliest opportunity.
virtual ~ICallbackHandler()
Virtual destructor.
virtual void onReTriangulatePolygon(const std::vector< TriInd > &tris)
Called when inserting a constraint edge causes polygon containing triangles to be re-triangulated @tr...
virtual void onFlipEdge(const TriInd iT, const TriInd iTopo)
Called just before an edge between tro triangles is flipped.
virtual void onInsertVertexInsideTriangle(const TriInd iRepurposedTri, const TriInd iNewTri1, const TriInd iNewTri2)
Called when inserted vertex is inside a triangle.
virtual void onAddEdgeStart(const Edge &edge)
Called at the start of adding a constraint edge to the triangulation.
virtual void onAddVertexStart(const VertInd iV, const AddVertexType::Enum vertexType)
Called at the start of adding new vertex to the triangulation.
const Edge & e1() const
first intersecting constraint
const Edge & e2() const
second intersecting constraint
IntersectingConstraintsError(const Edge &e1, const Edge &e2, const SourceLocation &srcLoc)
Constructor.
const Edge & e2() const
second intersecting constraint
const Edge & e1() const
first intersecting constraint
InvalidEdgeSplitVertex(const Edge &e1, const Edge &e2, const SourceLocation &srcLoc)
Constructor.
Contains source location info: file, function, line.
SourceLocation(const std::string &file, const std::string &func, int line)
Constructor.
const std::string & func() const
source function
int line() const
source line
const std::string & file() const
source file
EdgeUSet fixedEdges
triangulation's constraints (fixed edges)
void eraseOuterTriangles()
Erase triangles outside of constrained boundary using growing.
void conformToEdges(TEdgeIter first, TEdgeIter last, TGetEdgeVertexStart getStart, TGetEdgeVertexEnd getEnd)
Insert constraint edges into triangulation for Conforming Delaunay Triangulation (for example see fig...
std::vector< V2d< T > > V2dVec
Vertices vector.
std::vector< LayerDepth > calculateTriangleDepths() const
Calculate depth of each triangle in constraint triangulation.
TriIndUSet collectSuperTriangle() const
Collect triangles adjacent to super-triangle: same triangles that eraseSuperTriangle would remove.
bool isFinalized() const
Check if the triangulation was finalized with erase... method and super-triangle was removed.
TriIndUSet collectOuterTrianglesAndHoles() const
Collect triangles outside of constrained boundary and auto-detected holes: same triangles that eraseO...
Triangulation(VertexInsertionOrder::Enum vertexInsertionOrder)
Constructor.
TriIndVec findUnrefinedTriangles(RefinementCriterion::Enum refinementCriterion=RefinementCriterion::SmallestAngle, T refinementThreshold=degToRad(T(20))) const
Find triangles that don't fulfill the refinement criterion.
void finalizeTriangulation(const TriIndUSet &removedTriangles)
Remove super-triangle and triangles with specified indices.
void eraseOuterTrianglesAndHoles()
Erase triangles outside of constrained boundary and auto-detected holes.
V2dVec vertices
triangulation's vertices
TriIndUSet collectOuterTriangles() const
Collect triangles outside of constrained boundary: same triangles that eraseOuterTriangles would remo...
Unrefined refineTriangles(VertInd maxVerticesToInsert, RefinementCriterion::Enum refinementCriterion=RefinementCriterion::SmallestAngle, T refinementThreshold=degToRad(T(20)), TriIndUSet *toEraseOrNull=NULL, T minEdgeLength=T(1e-6))
Triangles refinement by splitting bad triangles.
void insertEdges(TEdgeIter first, TEdgeIter last, TGetEdgeVertexStart getStart, TGetEdgeVertexEnd getEnd)
Insert constraint edges into triangulation for Constrained Delaunay Triangulation (for example see fi...
void insertVertices(TVertexIter first, TVertexIter last, TGetVertexCoordX getX, TGetVertexCoordY getY)
Insert custom point-types specified by iterator range and X/Y-getters.
Triangulation(VertexInsertionOrder::Enum vertexInsertionOrder, IntersectingConstraintEdges::Enum intersectingEdgesStrategy, T minDistToConstraintEdge)
Constructor.
void eraseSuperTriangle()
Erase triangles adjacent to super triangle.
unordered_map< Edge, EdgeVec > pieceToOriginals
Stores list of original edges represented by a given fixed edge.
Triangulation(VertexInsertionOrder::Enum vertexInsertionOrder, const TNearPointLocator &nearPtLocator, IntersectingConstraintEdges::Enum intersectingEdgesStrategy, T minDistToConstraintEdge)
Constructor.
unordered_map< Edge, BoundaryOverlapCount > overlapCount
Stores count of overlapping boundaries for a fixed edge.
TriangleVec triangles
triangulation's triangles
Triangulation()
Default constructor.
EdgeVec findEncroachedFixedEdges() const
Find all fixed edges encroached by their opposed vertices.
void setCallbackHandler(ICallbackHandler *callbackHandler)
Set user-provided callback handler.
unsigned short LayerDepth
Type used for storing layer depths for triangles.
Definition CDT.h:39
OptionalIndex< VertInd > OptionalVertInd
Optional vertex index.
OptionalIndex< TriInd > OptionalTriInd
Optional triangle index.
void flipEdge(TriInd iT, TriInd iTopo)
Flip an edge between two triangle.
TriIndVec & VertTrisInternal()
Access internal vertex adjacent triangles.
void removeTriangles(const TriIndUSet &removedTriangles)
Remove triangles with specified indices.
Namespace containing triangulation functionality.
std::vector< Edge > EdgeVec
Vector of edges.
Definition CDTUtils.h:400
unordered_set< Edge > EdgeUSet
Hash table of edges.
Definition CDTUtils.h:403
CDT_EXPORT T degToRad(T degrees)
Convert an angle from degrees to radians.
Definition CDTUtils.hpp:330
std::vector< TriInd > TriIndVec
Vector of triangle indices.
Definition CDTUtils.h:272
IndexSizeType VertInd
Vertex index.
Definition CDTUtils.h:254
unordered_set< TriInd > TriIndUSet
Hash table of triangles.
Definition CDTUtils.h:404
IndexSizeType TriInd
Triangle index.
Definition CDTUtils.h:256
std::vector< Triangle > TriangleVec
Vector of triangles.
Definition CDTUtils.h:467
std::queue< Edge > EdgeQueue
Queue of edges.
Definition CDTUtils.h:401
What type of vertex is added to the triangulation.
Enum
The Enum itself.
@ RefinementCircumcenter
Refinement: circumcenter of a poor-quality triangle.
@ UserInput
Original vertex from user input.
@ RefinementEdgeSplit
Refinement: split of an encroached fixed edge.
@ FixedEdgeMidpoint
During conforming triangulation edge mid-point is added.
@ FixedEdgesIntersection
Resolving fixed/constraint edges' intersection.
2D bounding box
Definition CDTUtils.h:279
Box2d< T > & envelopPoints(TVertexIter first, TVertexIter last, TGetVertexCoordX getX, TGetVertexCoordY getY)
Envelop box around a collection of custom points.
Definition CDTUtils.h:310
Edge connecting two vertices: vertex with smaller index is always first.
Definition CDTUtils.h:334
Enum of strategies for treating intersecting constraint edges.
@ TryResolve
attempt to resolve constraint edge intersections
@ NotAllowed
constraint edge intersections are not allowed
@ DontCheck
No checks: slightly faster but less safe.
Enum of strategies for triangles refinement.
@ LargestArea
constraint maximum triangles area
@ SmallestAngle
constraint minimum triangles angle
What type of triangle change happened.
@ AddedNew
new triangle added to the triangulation
@ ModifiedExisting
existing triangle was modified
Triangulation triangle (counter-clockwise winding)
Definition CDTUtils.h:416
Counts of the refinements that Triangulation::refineTriangles was not able to perform.
std::size_t circumcenterOnVertex
triangles whose circumcenter coincides with an existing vertex
std::size_t sharpFixedCorner
triangles whose smallest angle is enclosed by two fixed edges: such an angle comes from the input and...
std::size_t splitVertexInvalid
fixed edges whose split vertex can not be placed: inserting it would break the triangulation's topolo...
std::size_t circumcenterOutside
triangles whose circumcenter is outside the triangulated area
std::size_t shortEdges
fixed edges that are shorter than the threshold
std::size_t shortEdgeTriangles
triangles whose shortest edge is shorter than the threshold
Unrefined()
Constructor: all the counts start at zero.
2D vector
Definition CDTUtils.h:192
Enum of strategies specifying order in which a range of vertices is inserted.
@ AsProvided
insert vertices in same order they are provided
@ Auto
Automatic insertion order optimized for better performance.
SplitMix64 pseudo-random number generator.
SplitMix64RandGen()
default constructor
uint64 operator()()
functor's operator
unsigned long long uint64
uint64 type
SplitMix64RandGen(uint64 state)
constructor