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 VertInd opposedVertexOnEdge(
const Edge& edge, T tolerance)
const;
1216 hasAnotherFixedEdgeAtSmallAngle(
VertInd v,
const Edge& excludeEdge)
const;
1218 void pivotVertexTriangleCW(
VertInd v);
1220 void tryAddVertexToLocator(
const VertInd v);
1223 void tryInitNearestPointLocator();
1225 TNearPointLocator m_nearPtLocator;
1228 T m_minDistToConstraintEdge;
1230#ifdef CDT_ENABLE_CALLBACK_HANDLER
1258 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
1259 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
1260 return z ^ (z >> 31);
1265template <
class RandomIt>
1269 typename std::iterator_traits<RandomIt>::difference_type i, n;
1271 for(i = n - 1; i > 0; --i)
1273 std::swap(first[i], first[prng() % (i + 1)]);
1278template <
class ForwardIt,
class T>
1279void iota(ForwardIt first, ForwardIt last, T value)
1281 while(first != last)
1293template <
typename T,
typename TNearPo
intLocator>
1295 typename TVertexIter,
1296 typename TGetVertexCoordX,
1297 typename TGetVertexCoordY>
1299 const TVertexIter first,
1300 const TVertexIter last,
1301 TGetVertexCoordX getX,
1302 TGetVertexCoordY getY)
1307 const bool isFirstTime =
vertices.empty();
1312 const std::size_t nNewVertices = std::distance(first, last);
1313 std::size_t exactCapacityTriangles =
triangles.size() + 2 * nNewVertices;
1314 std::size_t exactCapacityVertices =
vertices.size() + nNewVertices;
1317 exactCapacityTriangles += 1;
1318 exactCapacityVertices += nSuperTriVerts;
1320 std::size_t capacityTriangles = exactCapacityTriangles;
1321 std::size_t capacityVertices = exactCapacityVertices;
1327 const VertInd overAllocationVerticesThreshold(1000);
1328 const std::size_t overAllocationFraction(10);
1329 const bool isOverPreAllocated =
1330 m_intersectingEdgesStrategy ==
1332 VertInd(nNewVertices) >= overAllocationVerticesThreshold;
1333 if(isOverPreAllocated)
1335 capacityTriangles += capacityTriangles / overAllocationFraction;
1336 capacityVertices += capacityVertices / overAllocationFraction;
1339 vertices.reserve(capacityVertices);
1340 m_vertTris.reserve(capacityVertices);
1346 addSuperTriangle(box);
1348 tryInitNearestPointLocator();
1349 const VertInd nExistingVerts = verticesCount();
1351 for(TVertexIter it = first; it != last; ++it)
1352 addNewVertex(
V2d<T>(getX(*it), getY(*it)), noNeighbor);
1354 switch(m_vertexInsertionOrder)
1357 insertVertices_AsProvided(nExistingVerts);
1360 isFirstTime ? insertVertices_KDTreeBFS(nExistingVerts, box)
1361 : insertVertices_Randomized(nExistingVerts);
1366#ifdef CDT_ENABLE_CALLBACK_HANDLER
1368 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1369 (
vertices.size() == exactCapacityVertices));
1371 !m_callbackHandler || m_callbackHandler->isAbortCalculation() ||
1372 (
triangles.size() == exactCapacityTriangles));
1374 assert(
vertices.size() == exactCapacityVertices);
1375 assert(
triangles.size() == exactCapacityTriangles);
1379template <
typename T,
typename TNearPo
intLocator>
1382 typename TGetEdgeVertexStart,
1383 typename TGetEdgeVertexEnd>
1386 const TEdgeIter last,
1387 TGetEdgeVertexStart getStart,
1388 TGetEdgeVertexEnd getEnd)
1393 std::vector<TriangulatePseudoPolygonTask> tppIterations;
1395 for(; first != last; ++first)
1397#ifdef CDT_ENABLE_CALLBACK_HANDLER
1398 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1405 VertInd(getStart(*first) + nSuperTriVerts),
1406 VertInd(getEnd(*first) + nSuperTriVerts));
1407 insertEdge(edge, edge, remaining, tppIterations);
1411template <
typename T,
typename TNearPo
intLocator>
1414 typename TGetEdgeVertexStart,
1415 typename TGetEdgeVertexEnd>
1418 const TEdgeIter last,
1419 TGetEdgeVertexStart getStart,
1420 TGetEdgeVertexEnd getEnd)
1425 tryInitNearestPointLocator();
1427 std::vector<ConformToEdgeTask> remaining;
1428 for(; first != last; ++first)
1430#ifdef CDT_ENABLE_CALLBACK_HANDLER
1431 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1438 VertInd(getStart(*first) + nSuperTriVerts),
1439 VertInd(getEnd(*first) + nSuperTriVerts));
1440 conformToEdge(e,
EdgeVec(1, e), 0, remaining);
1446#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