10#ifndef CDT_vW1vZ0lO8rS4gY4uI4fB
11#define CDT_vW1vZ0lO8rS4gY4uI4fB
147 const std::string&
file()
const
152 const std::string&
func()
const
169#define CDT_SOURCE_LOCATION \
170 SourceLocation(std::string(__FILE__), std::string(__func__), __LINE__)
176class CDT_EXPORT
Error :
public std::runtime_error
181 : std::runtime_error(
182 description +
"\nin '" + srcLoc.func() +
"' at " + srcLoc.file() +
183 ":" +
CDT::to_string(srcLoc.line()))
193 return m_description;
202 std::string m_description;
216 "Triangulation was finalized with 'erase...' method. Further "
217 "modification is not possible.",
234 "Duplicate vertex detected: #" +
CDT::to_string(
v1) +
235 " is a duplicate of #" +
CDT::to_string(
v2),
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()) +
")",
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",
328class CDT_EXPORT AccessingInvalidIndex :
public Error
332 :
Error(
"Accessing invalid index", srcLoc)
336template <
typename TIndex>
337class CDT_EXPORT OptionalIndex
340 OptionalIndex(
const TIndex index)
343 bool hasValue()
const
345 return m_index != TIndex(invalidIndexSizeType);
385#ifdef CDT_ENABLE_CALLBACK_HANDLER
405#pragma GCC diagnostic push
406#pragma GCC diagnostic ignored "-Wunused-parameter"
437 const TriInd iRepurposedTri,
454 const TriInd iRepurposedTri1,
455 const TriInd iRepurposedTri2,
505#pragma GCC diagnostic pop
523template <
typename T,
typename TNearPo
intLocator = LocatorKDTree<T> >
568 T minDistToConstraintEdge);
582 const TNearPointLocator& nearPtLocator,
584 T minDistToConstraintEdge);
600 typename TVertexIter,
601 typename TGetVertexCoordX,
602 typename TGetVertexCoordY>
606 TGetVertexCoordX getX,
607 TGetVertexCoordY getY);
651 typename TGetEdgeVertexStart,
652 typename TGetEdgeVertexEnd>
656 TGetEdgeVertexStart getStart,
657 TGetEdgeVertexEnd getEnd);
720 typename TGetEdgeVertexStart,
721 typename TGetEdgeVertexEnd>
725 TGetEdgeVertexStart getStart,
726 TGetEdgeVertexEnd getEnd);
774 T refinementThreshold =
degToRad(T(20)),
776 T minEdgeLength = T(1e-6));
801 T refinementThreshold =
degToRad(T(20)))
const;
871#ifdef CDT_ENABLE_CALLBACK_HANDLER
928 void addSuperTriangle(
const Box2d<T>& box);
930 void insertVertex(
VertInd iVert);
932 void ensureDelaunayByEdgeFlips(
VertInd iV1, std::stack<TriInd>& triStack);
934 std::vector<Edge> insertVertex_FlipFixedEdges(
VertInd iV1);
937 typedef tuple<IndexSizeType, IndexSizeType, TriInd, TriInd, Index>
938 TriangulatePseudoPolygonTask;
956 std::vector<TriangulatePseudoPolygonTask>& tppIterations);
970 void insertEdgeIteration(
974 std::vector<TriangulatePseudoPolygonTask>& tppIterations);
977 typedef tuple<Edge, EdgeVec, BoundaryOverlapCount> ConformToEdgeTask;
994 BoundaryOverlapCount overlaps,
995 std::vector<ConformToEdgeTask>& remaining);
1008 void conformToEdgeIteration(
1011 BoundaryOverlapCount overlaps,
1012 std::vector<ConformToEdgeTask>& remaining);
1014 tuple<TriInd, VertInd, VertInd> intersectedTriangle(
1018 T orientationTolerance = T(0))
const;
1020 std::stack<TriInd> insertVertexInsideTriangle(
VertInd v,
TriInd iT);
1022 std::stack<TriInd> insertVertexOnEdge(
1026 const bool doHandleFixedSplitEdge =
false);
1027 array<TriInd, 2> trianglesAt(
const V2d<T>& pos)
const;
1052 const bool doFlipFixedEdges =
false)
const;
1054 bool isSameOriginalEdge(
const Edge& e1,
const Edge& e2)
const;
1055 bool isRefinementNeeded(
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;
1074 VertInd steinerVerticesOffset,
1075 const V2d<T>* circumcenterOrNull,
1077 T badTriangleThreshold,
1083 VertInd steinerVerticesOffset,
1087 void changeNeighbor(
1092 void triangulatePseudoPolygon(
1093 const std::vector<VertInd>& poly,
1094 unordered_map<Edge, TriInd>& outerTris,
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,
1107 IndexSizeType iB)
const;
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);
1168 bool isEdgeSplitVertexValid(
1179 Edge originalInputEdge(
const Edge& e)
const;
1203 unordered_map<TriInd, LayerDepth> peelLayer(
1204 std::stack<TriInd> seeds,
1206 std::vector<LayerDepth>& triDepths)
const;
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;
1214 hasAnotherFixedEdgeAtSmallAngle(
VertInd v,
const Edge& excludeEdge)
const;
1216 void pivotVertexTriangleCW(
VertInd v);
1218 void tryAddVertexToLocator(
const VertInd v);
1221 void tryInitNearestPointLocator();
1223 TNearPointLocator m_nearPtLocator;
1226 T m_minDistToConstraintEdge;
1228#ifdef CDT_ENABLE_CALLBACK_HANDLER
1256 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
1257 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
1258 return z ^ (z >> 31);
1263template <
class RandomIt>
1267 typename std::iterator_traits<RandomIt>::difference_type i, n;
1269 for(i = n - 1; i > 0; --i)
1271 std::swap(first[i], first[prng() % (i + 1)]);
1276template <
class ForwardIt,
class T>
1277void iota(ForwardIt first, ForwardIt last, T value)
1279 while(first != last)
1291template <
typename T,
typename TNearPo
intLocator>
1293 typename TVertexIter,
1294 typename TGetVertexCoordX,
1295 typename TGetVertexCoordY>
1297 const TVertexIter first,
1298 const TVertexIter last,
1299 TGetVertexCoordX getX,
1300 TGetVertexCoordY getY)
1305 const bool isFirstTime =
vertices.empty();
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;
1315 exactCapacityTriangles += 1;
1316 exactCapacityVertices += nSuperTriVerts;
1318 std::size_t capacityTriangles = exactCapacityTriangles;
1319 std::size_t capacityVertices = exactCapacityVertices;
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)
1333 capacityTriangles += capacityTriangles / overAllocationFraction;
1334 capacityVertices += capacityVertices / overAllocationFraction;
1337 vertices.reserve(capacityVertices);
1338 m_vertTris.reserve(capacityVertices);
1344 addSuperTriangle(box);
1346 tryInitNearestPointLocator();
1347 const VertInd nExistingVerts = verticesCount();
1349 for(TVertexIter it = first; it != last; ++it)
1350 addNewVertex(
V2d<T>(getX(*it), getY(*it)), noNeighbor);
1352 switch(m_vertexInsertionOrder)
1355 insertVertices_AsProvided(nExistingVerts);
1358 isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box)
1359 : insertVertices_Randomized(nExistingVerts);
1364#ifdef CDT_ENABLE_CALLBACK_HANDLER
1366 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1367 (
vertices.size() == exactCapacityVertices));
1369 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1370 (
triangles.size() == exactCapacityTriangles));
1372 assert(
vertices.size() == exactCapacityVertices);
1373 assert(
triangles.size() == exactCapacityTriangles);
1377template <
typename T,
typename TNearPo
intLocator>
1380 typename TGetEdgeVertexStart,
1381 typename TGetEdgeVertexEnd>
1384 const TEdgeIter last,
1385 TGetEdgeVertexStart getStart,
1386 TGetEdgeVertexEnd getEnd)
1391 std::vector<TriangulatePseudoPolygonTask> tppIterations;
1393 for(; first != last; ++first)
1395#ifdef CDT_ENABLE_CALLBACK_HANDLER
1396 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1403 VertInd(getStart(*first) + nSuperTriVerts),
1404 VertInd(getEnd(*first) + nSuperTriVerts));
1405 insertEdge(edge, edge, remaining, tppIterations);
1409template <
typename T,
typename TNearPo
intLocator>
1412 typename TGetEdgeVertexStart,
1413 typename TGetEdgeVertexEnd>
1416 const TEdgeIter last,
1417 TGetEdgeVertexStart getStart,
1418 TGetEdgeVertexEnd getEnd)
1423 tryInitNearestPointLocator();
1425 std::vector<ConformToEdgeTask> remaining;
1426 for(; first != last; ++first)
1428#ifdef CDT_ENABLE_CALLBACK_HANDLER
1429 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1436 VertInd(getStart(*first) + nSuperTriVerts),
1437 VertInd(getEnd(*first) + nSuperTriVerts));
1438 conformToEdge(e,
EdgeVec(1, e), 0, remaining);
1444#ifndef CDT_USE_AS_COMPILED_LIBRARY
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.
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.
unordered_set< Edge > EdgeUSet
Hash table of edges.
CDT_EXPORT T degToRad(T degrees)
Convert an angle from degrees to radians.
std::vector< TriInd > TriIndVec
Vector of triangle indices.
IndexSizeType VertInd
Vertex index.
unordered_set< TriInd > TriIndUSet
Hash table of triangles.
IndexSizeType TriInd
Triangle index.
std::vector< Triangle > TriangleVec
Vector of triangles.
std::queue< Edge > EdgeQueue
Queue of edges.
What type of vertex is added to the triangulation.
@ 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.
Box2d< T > & envelopPoints(TVertexIter first, TVertexIter last, TGetVertexCoordX getX, TGetVertexCoordY getY)
Envelop box around a collection of custom points.
Edge connecting two vertices: vertex with smaller index is always first.
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)
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.
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.
uint64 m_state
PRNG's state.
SplitMix64RandGen()
default constructor
uint64 operator()()
functor's operator
unsigned long long uint64
uint64 type
SplitMix64RandGen(uint64 state)
constructor