9#ifndef CDT_pDqrlveWIOrIWeUCkPqX
10#define CDT_pDqrlveWIOrIWeUCkPqX
13#include "portable_nth_element.hpp"
24typedef std::deque<TriInd> TriDeque;
32const std::size_t nTargetVerts = 0;
38const float minDistToConstraintEdge(0);
44template <
typename T,
typename TNearPo
intLocator>
46 : m_nTargetVerts(detail::defaults::nTargetVerts)
47 , m_superGeomType(detail::defaults::superGeomType)
48 , m_vertexInsertionOrder(detail::defaults::vertexInsertionOrder)
49 , m_intersectingEdgesStrategy(detail::defaults::intersectingEdgesStrategy)
50 , m_minDistToConstraintEdge(detail::defaults::minDistToConstraintEdge)
51#ifdef CDT_ENABLE_CALLBACK_HANDLER
52 , m_callbackHandler(NULL)
56template <
typename T,
typename TNearPo
intLocator>
59 : m_nTargetVerts(detail::defaults::nTargetVerts)
60 , m_superGeomType(detail::defaults::superGeomType)
61 , m_vertexInsertionOrder(vertexInsertionOrder)
62 , m_intersectingEdgesStrategy(detail::defaults::intersectingEdgesStrategy)
63 , m_minDistToConstraintEdge(detail::defaults::minDistToConstraintEdge)
64#ifdef CDT_ENABLE_CALLBACK_HANDLER
65 , m_callbackHandler(NULL)
69template <
typename T,
typename TNearPo
intLocator>
73 const T minDistToConstraintEdge)
74 : m_nTargetVerts(detail::defaults::nTargetVerts)
75 , m_superGeomType(detail::defaults::superGeomType)
76 , m_vertexInsertionOrder(vertexInsertionOrder)
77 , m_intersectingEdgesStrategy(intersectingEdgesStrategy)
78 , m_minDistToConstraintEdge(minDistToConstraintEdge)
79#ifdef CDT_ENABLE_CALLBACK_HANDLER
80 , m_callbackHandler(NULL)
84template <
typename T,
typename TNearPo
intLocator>
87 const TNearPointLocator& nearPtLocator,
89 const T minDistToConstraintEdge)
90 : m_nearPtLocator(nearPtLocator)
91 , m_nTargetVerts(detail::defaults::nTargetVerts)
92 , m_superGeomType(detail::defaults::superGeomType)
93 , m_vertexInsertionOrder(vertexInsertionOrder)
94 , m_intersectingEdgesStrategy(intersectingEdgesStrategy)
95 , m_minDistToConstraintEdge(minDistToConstraintEdge)
96#ifdef CDT_ENABLE_CALLBACK_HANDLER
97 , m_callbackHandler(NULL)
101template <
typename T,
typename TNearPo
intLocator>
113 finalizeTriangulation(toErase);
116template <
typename T,
typename TNearPo
intLocator>
119 assert(m_vertTris[0] != noNeighbor);
120 const std::stack<TriInd> seed(std::deque<TriInd>(1, m_vertTris[0]));
121 const TriIndUSet toErase = growToBoundary(seed);
122 finalizeTriangulation(toErase);
125template <
typename T,
typename TNearPo
intLocator>
131 for(std::size_t iT = 0; iT !=
triangles.size(); ++iT)
133 if(triDepths[iT] % 2 == 0)
134 toErase.insert(
static_cast<TriInd>(iT));
136 finalizeTriangulation(toErase);
145template <
typename T,
typename TNearPo
intLocator>
149 if(removedTriangles.empty())
155 if(removedTriangles.count(iT))
157 triIndMap[iT] = iTnew;
168 for(NeighborsArr3::iterator n = nn.begin(); n != nn.end(); ++n)
170 if(removedTriangles.count(*n))
174 else if(*n != noNeighbor)
182template <
typename T,
typename TNearPo
intLocator>
188template <
typename T,
typename TNearPo
intLocator>
194template <
typename T,
typename TNearPo
intLocator>
195void Triangulation<T, TNearPointLocator>::finalizeTriangulation(
203 vertices.begin(), vertices.begin() + nSuperTriangleVertices);
207 typedef CDT::EdgeUSet::const_iterator It;
208 for(It e = fixedEdges.begin(); e != fixedEdges.end(); ++e)
212 fixedEdges = updatedFixedEdges;
215 unordered_map<Edge, BoundaryOverlapCount> updatedOverlapCount;
216 typedef unordered_map<Edge, BoundaryOverlapCount>::const_iterator
218 for(It it = overlapCount.begin(); it != overlapCount.end(); ++it)
220 updatedOverlapCount.insert(
224 overlapCount = updatedOverlapCount;
227 unordered_map<Edge, EdgeVec> updatedPieceToOriginals;
228 typedef unordered_map<Edge, EdgeVec>::const_iterator It;
229 for(It it = pieceToOriginals.begin(); it != pieceToOriginals.end();
233 for(EdgeVec::iterator eeIt = ee.begin(); eeIt != ee.end();
238 updatedPieceToOriginals.insert(
241 pieceToOriginals = updatedPieceToOriginals;
245 removeTriangles(removedTriangles);
249 for(TriangleVec::iterator t = triangles.begin(); t != triangles.end();
253 for(VerticesArr3::iterator v = vv.begin(); v != vv.end(); ++v)
255 *v -= nSuperTriangleVertices;
261template <
typename T,
typename TNearPo
intLocator>
264 m_nearPtLocator.initialize(
vertices);
265 m_nTargetVerts =
static_cast<IndexSizeType
>(
vertices.size());
269template <
typename T,
typename TNearPo
intLocator>
270TriIndUSet Triangulation<T, TNearPointLocator>::growToBoundary(
271 std::stack<TriInd> seeds)
const
274 while(!seeds.empty())
276 const TriInd iT = seeds.top();
278 traversed.insert(iT);
283 if(fixedEdges.count(opEdge))
286 if(iN != noNeighbor && traversed.count(iN) == 0)
293template <
typename T,
typename TNearPo
intLocator>
294TriInd Triangulation<T, TNearPointLocator>::addTriangle(
const Triangle& t)
296 const TriInd iT(triangles.size());
297 triangles.push_back(t);
301template <
typename T,
typename TNearPo
intLocator>
302TriInd Triangulation<T, TNearPointLocator>::addTriangle()
307template <
typename T,
typename TNearPo
intLocator>
309 const std::vector<Edge>& edges)
314template <
typename T,
typename TNearPo
intLocator>
316 const std::vector<Edge>& edges)
321template <
typename T,
typename TNearPo
intLocator>
322void Triangulation<T, TNearPointLocator>::fixEdge(
const Edge& edge)
324 if(!fixedEdges.insert(edge).second)
326 ++overlapCount[edge];
334template <
typename T,
typename Allocator1>
335void insert_unique(std::vector<T, Allocator1>& to,
const T& elem)
337 if(std::find(to.begin(), to.end(), elem) == to.end())
344template <
typename T,
typename Allocator1,
typename Allocator2>
346 std::vector<T, Allocator1>& to,
347 const std::vector<T, Allocator2>& from)
349 typedef typename std::vector<T, Allocator2>::const_iterator Cit;
350 to.reserve(to.size() + from.size());
351 for(Cit cit = from.begin(); cit != from.end(); ++cit)
353 insert_unique(to, *cit);
359template <
typename T,
typename TNearPo
intLocator>
360void Triangulation<T, TNearPointLocator>::splitFixedEdge(
365 const Edge half1(edge.v1(), iSplitVert);
366 const Edge half2(iSplitVert, edge.v2());
368 fixedEdges.erase(edge);
372 typedef unordered_map<Edge, BoundaryOverlapCount>::const_iterator It;
373 const It overlapIt = overlapCount.find(edge);
374 if(overlapIt != overlapCount.end())
376 overlapCount[half1] += overlapIt->second;
377 overlapCount[half2] += overlapIt->second;
378 overlapCount.erase(overlapIt);
382 const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
383 pieceToOriginals.find(edge);
384 if(originalsIt != pieceToOriginals.end())
386 newOriginals = originalsIt->second;
387 pieceToOriginals.erase(originalsIt);
389 detail::insert_unique(pieceToOriginals[half1], newOriginals);
390 detail::insert_unique(pieceToOriginals[half2], newOriginals);
393template <
typename T,
typename TNearPo
intLocator>
394VertInd Triangulation<T, TNearPointLocator>::addSplitEdgeVertex(
401 addNewVertex(splitVert, noNeighbor);
403#ifdef CDT_ENABLE_CALLBACK_HANDLER
404 if(m_callbackHandler)
406 m_callbackHandler->onAddVertexStart(
411 std::stack<TriInd> triStack = insertVertexOnEdge(iSplitVert, iT, iTopo);
412 tryAddVertexToLocator(iSplitVert);
413 ensureDelaunayByEdgeFlips(iSplitVert, triStack);
417template <
typename T,
typename TNearPo
intLocator>
418VertInd Triangulation<T, TNearPointLocator>::splitFixedEdgeAt(
424 const VertInd iSplitVert = addSplitEdgeVertex(splitVert, iT, iTopo);
425 splitFixedEdge(edge, iSplitVert);
429template <
typename T,
typename TNearPo
intLocator>
430bool Triangulation<T, TNearPointLocator>::isEdgeSplitVertexValid(
444 splitVert, vertices[tL.vertices[sL]], vertices[tL.vertices[
ccw(sL)]]);
445 if(side == PtLineLocation::OnLine)
447 return splitVert != vertices[iVL] && splitVert != vertices[iVR];
449 const Triangle& t = side == PtLineLocation::Left ? tL : triangles[iTopo];
456 const V2d<T>& from = vertices[t.vertices[s]];
457 const V2d<T>& to = vertices[t.vertices[
ccw(s)]];
458 const V2d<T>& apex = vertices[t.vertices[
cw(s)]];
459 return locatePointLine(splitVert, to, apex) != PtLineLocation::Right &&
463template <
typename T,
typename TNearPo
intLocator>
464Edge Triangulation<T, TNearPointLocator>::originalInputEdge(
const Edge& e)
const
467 pieceToOriginals.count(e) ? pieceToOriginals.at(e).front() : e;
469 VertInd(orig.v1() - m_nTargetVerts),
470 VertInd(orig.v2() - m_nTargetVerts));
473template <
typename T,
typename TNearPo
intLocator>
475Triangulation<T, TNearPointLocator>::triangleAt(
const TriInd iT)
const
477 if(iT >= triangles.size())
478 handleException(
Error(
480 ?
"Attempted reading no-neighbor sentinel value triangle"
481 :
"Triangle index " + CDT::to_string(iT) +
" out of range " +
482 CDT::to_string(triangles.size()),
483 CDT_SOURCE_LOCATION));
484 return triangles[iT];
487template <
typename T,
typename TNearPo
intLocator>
488void Triangulation<T, TNearPointLocator>::fixEdge(
490 const Edge& originalEdge)
493 if(edge != originalEdge)
494 detail::insert_unique(pieceToOriginals[edge], originalEdge);
501T lerp(
const T& a,
const T& b,
const T t)
503 return (T(1) - t) * a + t * b;
508V2d<T> intersectionPosition(
514 using namespace predicates::adaptive;
518 const T a_cd = orient2d(c.x, c.y, d.x, d.y, a.x, a.y);
519 const T b_cd = orient2d(c.x, c.y, d.x, d.y, b.x, b.y);
520 const T t_ab = a_cd / (a_cd - b_cd);
522 const T c_ab = orient2d(a.x, a.y, b.x, b.y, c.x, c.y);
523 const T d_ab = orient2d(a.x, a.y, b.x, b.y, d.x, d.y);
524 const T t_cd = c_ab / (c_ab - d_ab);
527 std::fabs(a.x - b.x) < std::fabs(c.x - d.x) ? lerp(a.x, b.x, t_ab)
528 : lerp(c.x, d.x, t_cd),
529 std::fabs(a.y - b.y) < std::fabs(c.y - d.y) ? lerp(a.y, b.y, t_ab)
530 : lerp(c.y, d.y, t_cd));
535template <
typename T,
typename TNearPo
intLocator>
536void Triangulation<T, TNearPointLocator>::insertEdgeIteration(
538 const Edge originalEdge,
540 std::vector<TriangulatePseudoPolygonTask>& tppIterations)
549 fixEdge(edge, originalEdge);
553 const V2d<T>& a = vertices[iA];
554 const V2d<T>& b = vertices[iB];
555 const T distanceTolerance =
556 m_minDistToConstraintEdge == T(0)
558 : m_minDistToConstraintEdge *
distance(a, b);
563 tie(iT, iVL, iVR) = intersectedTriangle(iA, a, b, distanceTolerance);
567 const Edge edgePart(iA, iVL);
568 fixEdge(edgePart, originalEdge);
569 remaining.push_back(
Edge(iVL, iB));
573 std::vector<TriInd> intersected(1, iT);
574 std::vector<VertInd> polyL, polyR;
577 polyL.push_back(iVL);
580 polyR.push_back(iVR);
581 unordered_map<Edge, TriInd> outerTris;
586 while(!t.containsVertex(iB))
589 const Triangle& tOpo = triangleAt(iTopo);
592 switch(m_intersectingEdgesStrategy)
595 if(fixedEdges.count(
Edge(iVL, iVR)))
597 originalInputEdge(originalEdge),
598 originalInputEdge(
Edge(iVL, iVR)),
599 CDT_SOURCE_LOCATION));
603 if(!fixedEdges.count(
Edge(iVL, iVR)))
606 const V2d<T> newV = detail::intersectionPosition(
607 vertices[iA], vertices[iB], vertices[iVL], vertices[iVR]);
608 if(!isEdgeSplitVertexValid(newV, iT, iTopo, iVL, iVR))
610 originalInputEdge(originalEdge),
611 originalInputEdge(
Edge(iVL, iVR)),
612 CDT_SOURCE_LOCATION));
614 splitFixedEdgeAt(
Edge(iVL, iVR), newV, iT, iTopo);
617 remaining.push_back(
Edge(iA, iNewVert));
618 remaining.push_back(
Edge(iNewVert, iB));
622 assert(!fixedEdges.count(
Edge(iVL, iVR)));
628 if(loc == PtLineLocation::Left)
630 const Edge e(polyL.back(), iVopo);
632 if(!outerTris.insert(std::make_pair(e, outer)).second)
633 outerTris.at(e) = noNeighbor;
634 polyL.push_back(iVopo);
638 else if(loc == PtLineLocation::Right)
640 const Edge e(polyR.back(), iVopo);
642 if(!outerTris.insert(std::make_pair(e, outer)).second)
643 outerTris.at(e) = noNeighbor;
644 polyR.push_back(iVopo);
651 intersected.push_back(iTopo);
660 assert(!intersected.empty());
663 if(m_vertTris[iA] == intersected.front())
664 pivotVertexTriangleCW(iA);
665 if(m_vertTris[iB] == intersected.back())
666 pivotVertexTriangleCW(iB);
669#ifdef CDT_ENABLE_CALLBACK_HANDLER
670 if(m_callbackHandler)
672 m_callbackHandler->onReTriangulatePolygon(intersected);
677 std::reverse(polyR.begin(), polyR.end());
682 assert(intersected.size() >= 2);
683 const TriInd iTL = intersected.back();
684 intersected.pop_back();
685 const TriInd iTR = intersected.back();
686 intersected.pop_back();
688 triangulatePseudoPolygon(
689 polyL, outerTris, iTL, iTR, intersected, tppIterations);
690 triangulatePseudoPolygon(
691 polyR, outerTris, iTR, iTL, intersected, tppIterations);
692 assert(intersected.empty());
698 const Edge edgePart(iA, iB);
699 fixEdge(edgePart, originalEdge);
700 remaining.push_back(
Edge(iB, edge.v2()));
705 fixEdge(edge, originalEdge);
709template <
typename T,
typename TNearPo
intLocator>
710void Triangulation<T, TNearPointLocator>::insertEdge(
712 const Edge originalEdge,
714 std::vector<TriangulatePseudoPolygonTask>& tppIterations)
716#ifdef CDT_ENABLE_CALLBACK_HANDLER
717 if(m_callbackHandler)
719 m_callbackHandler->onAddEdgeStart(edge);
725 remaining.push_back(edge);
726 while(!remaining.empty())
728 edge = remaining.back();
729 remaining.pop_back();
730 insertEdgeIteration(edge, originalEdge, remaining, tppIterations);
734template <
typename T,
typename TNearPo
intLocator>
735void Triangulation<T, TNearPointLocator>::conformToEdgeIteration(
738 BoundaryOverlapCount overlaps,
739 std::vector<ConformToEdgeTask>& remaining)
750 overlapCount[edge] = overlaps;
752 if(!originals.empty() && edge != originals.front())
754 detail::insert_unique(pieceToOriginals[edge], originals);
759 const V2d<T>& a = vertices[iA];
760 const V2d<T>& b = vertices[iB];
761 const T distanceTolerance =
762 m_minDistToConstraintEdge == T(0)
764 : m_minDistToConstraintEdge *
distance(a, b);
767 tie(iT, iVleft, iVright) = intersectedTriangle(iA, a, b, distanceTolerance);
771 const Edge edgePart(iA, iVleft);
774 overlapCount[edgePart] = overlaps;
775 detail::insert_unique(pieceToOriginals[edgePart], originals);
776#ifdef CDT_CXX11_IS_SUPPORTED
777 remaining.emplace_back(
Edge(iVleft, iB), originals, overlaps);
779 remaining.push_back(make_tuple(
Edge(iVleft, iB), originals, overlaps));
786 while(std::find(t.vertices.begin(), t.vertices.end(), iB) ==
790 const Triangle& tOpo = triangleAt(iTopo);
792 const V2d<T> vOpo = vertices[iVopo];
794 switch(m_intersectingEdgesStrategy)
797 if(fixedEdges.count(
Edge(iVleft, iVright)))
799 originalInputEdge(edge),
800 originalInputEdge(
Edge(iVleft, iVright)),
801 CDT_SOURCE_LOCATION));
805 if(!fixedEdges.count(
Edge(iVleft, iVright)))
808 const V2d<T> newV = detail::intersectionPosition(
813 if(!isEdgeSplitVertexValid(newV, iT, iTopo, iVleft, iVright))
815 originalInputEdge(edge),
816 originalInputEdge(
Edge(iVleft, iVright)),
817 CDT_SOURCE_LOCATION));
819 splitFixedEdgeAt(
Edge(iVleft, iVright), newV, iT, iTopo);
820#ifdef CDT_CXX11_IS_SUPPORTED
821 remaining.emplace_back(
Edge(iNewVert, iB), originals, overlaps);
822 remaining.emplace_back(
Edge(iA, iNewVert), originals, overlaps);
825 make_tuple(
Edge(iNewVert, iB), originals, overlaps));
827 make_tuple(
Edge(iA, iNewVert), originals, overlaps));
832 assert(!fixedEdges.count(
Edge(iVleft, iVright)));
841 if(loc == PtLineLocation::Left)
846 else if(loc == PtLineLocation::Right)
858#ifdef CDT_CXX11_IS_SUPPORTED
859 remaining.emplace_back(
Edge(iB, edge.v2()), originals, overlaps);
862 make_tuple(
Edge(iB, edge.v2()), originals, overlaps));
868 const V2d<T>& start = vertices[iA];
869 const V2d<T>& end = vertices[iB];
871 V2d<T>((start.x + end.x) / T(2), (start.y + end.y) / T(2)), noNeighbor);
873#ifdef CDT_ENABLE_CALLBACK_HANDLER
874 if(m_callbackHandler)
876 m_callbackHandler->onAddVertexStart(
881 const std::vector<Edge> flippedFixedEdges =
882 insertVertex_FlipFixedEdges(iMid);
884#ifdef CDT_CXX11_IS_SUPPORTED
885 remaining.emplace_back(
Edge(iMid, iB), originals, overlaps);
886 remaining.emplace_back(
Edge(iA, iMid), originals, overlaps);
888 remaining.push_back(make_tuple(
Edge(iMid, iB), originals, overlaps));
889 remaining.push_back(make_tuple(
Edge(iA, iMid), originals, overlaps));
894 for(std::vector<Edge>::const_iterator it = flippedFixedEdges.begin();
895 it != flippedFixedEdges.end();
898 const Edge& flippedFixedEdge = *it;
899 fixedEdges.erase(flippedFixedEdge);
901 BoundaryOverlapCount prevOverlaps = 0;
902 const unordered_map<Edge, BoundaryOverlapCount>::const_iterator
903 overlapsIt = overlapCount.find(flippedFixedEdge);
904 if(overlapsIt != overlapCount.end())
906 prevOverlaps = overlapsIt->second;
907 overlapCount.erase(overlapsIt);
910 EdgeVec prevOriginals(1, flippedFixedEdge);
911 const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
912 pieceToOriginals.find(flippedFixedEdge);
913 if(originalsIt != pieceToOriginals.end())
915 prevOriginals = originalsIt->second;
917#ifdef CDT_CXX11_IS_SUPPORTED
918 remaining.emplace_back(flippedFixedEdge, prevOriginals, prevOverlaps);
921 make_tuple(flippedFixedEdge, prevOriginals, prevOverlaps));
926template <
typename T,
typename TNearPo
intLocator>
927void Triangulation<T, TNearPointLocator>::conformToEdge(
930 BoundaryOverlapCount overlaps,
931 std::vector<ConformToEdgeTask>& remaining)
933#ifdef CDT_ENABLE_CALLBACK_HANDLER
934 if(m_callbackHandler)
936 m_callbackHandler->onAddEdgeStart(edge);
942#ifdef CDT_CXX11_IS_SUPPORTED
943 remaining.emplace_back(edge, originals, overlaps);
945 remaining.push_back(make_tuple(edge, originals, overlaps));
947 while(!remaining.empty())
949 tie(edge, originals, overlaps) = remaining.back();
950 remaining.pop_back();
951 conformToEdgeIteration(edge, originals, overlaps, remaining);
965template <
typename T,
typename TNearPo
intLocator>
966tuple<TriInd, VertInd, VertInd>
967Triangulation<T, TNearPointLocator>::intersectedTriangle(
971 const T orientationTolerance)
const
973 const TriInd startTri = m_vertTris[iA];
980 const T orientP2 =
orient2D(vertices[iP2], a, b);
982 if(locP2 == PtLineLocation::Right)
985 const T orientP1 =
orient2D(vertices[iP1], a, b);
987 if(locP1 == PtLineLocation::OnLine)
989 return make_tuple(noNeighbor, iP1, iP1);
991 if(locP1 == PtLineLocation::Left)
993 if(orientationTolerance)
997 if(std::abs(orientP1) <= std::abs(orientP2))
999 closestOrient = orientP1;
1004 closestOrient = orientP2;
1008 closestOrient, orientationTolerance) ==
1009 PtLineLocation::OnLine)
1011 return make_tuple(noNeighbor, iClosestP, iClosestP);
1014 return make_tuple(iT, iP1, iP2);
1017 iT = t.next(iA).first;
1018 }
while(iT != startTri);
1020 handleException(
Error(
1021 "Could not find vertex triangle intersected by an edge.",
1022 CDT_SOURCE_LOCATION));
1023 return make_tuple(noNeighbor, noVertex, noVertex);
1026template <
typename T,
typename TNearPo
intLocator>
1027void Triangulation<T, TNearPointLocator>::addSuperTriangle(
const Box2d<T>& box)
1029 m_nTargetVerts = nSuperTriangleVertices;
1033 (box.min.x + box.max.x) / T(2), (box.min.y + box.max.y) / T(2));
1034 const T w = box.max.x - box.min.x;
1035 const T h = box.max.y - box.min.y;
1036 T r = std::max(w, h);
1041 r = std::max(T(2) * r, T(1));
1047 while(center.y <= center.y - r)
1051 const T R = T(2) * r;
1052 const T cos_30_deg = T(0.8660254037844386);
1053 const T shiftX = R * cos_30_deg;
1054 const V2d<T> posV1(center.x - shiftX, center.y - r);
1055 const V2d<T> posV2(center.x + shiftX, center.y - r);
1056 const V2d<T> posV3(center.x, center.y + R);
1057 addNewVertex(posV1,
TriInd(0));
1058 addNewVertex(posV2,
TriInd(0));
1059 addNewVertex(posV3,
TriInd(0));
1061#ifdef CDT_ENABLE_CALLBACK_HANDLER
1062 if(m_callbackHandler)
1064 m_callbackHandler->onAddSuperTriangle();
1073 m_nearPtLocator.initialize(vertices);
1077template <
typename T,
typename TNearPo
intLocator>
1078void Triangulation<T, TNearPointLocator>::addNewVertex(
1082 vertices.push_back(pos);
1083 m_vertTris.push_back(iT);
1086template <
typename T,
typename TNearPo
intLocator>
1088Triangulation<T, TNearPointLocator>::insertVertex_FlipFixedEdges(
1091 std::vector<Edge> flippedFixedEdges;
1093 const V2d<T>& v1 = vertices[iV1];
1094 const VertInd startVertex = m_nearPtLocator.nearPoint(v1, vertices);
1095 array<TriInd, 2> trisAt = walkingSearchTrianglesAt(iV1, startVertex);
1096 std::stack<TriInd> triStack =
1097 trisAt[1] == noNeighbor ? insertVertexInsideTriangle(iV1, trisAt[0])
1098 : insertVertexOnEdge(iV1, trisAt[0], trisAt[1]);
1100 TriInd iTopo, n1, n2, n3, n4;
1102 while(!triStack.empty())
1104 const TriInd iT = triStack.top();
1107 edgeFlipInfo(iT, iV1, iTopo, iV2, iV3, iV4, n1, n2, n3, n4);
1108 if(iTopo != noNeighbor && isFlipNeeded(iV1, iV2, iV3, iV4))
1111 const Edge flippedEdge(iV2, iV4);
1112 if(!fixedEdges.empty() &&
1113 fixedEdges.find(flippedEdge) != fixedEdges.end())
1115 flippedFixedEdges.push_back(flippedEdge);
1118 flipEdge(iT, iTopo, iV1, iV2, iV3, iV4, n1, n2, n3, n4);
1120 triStack.push(iTopo);
1124 tryAddVertexToLocator(iV1);
1125 return flippedFixedEdges;
1128template <
typename T,
typename TNearPo
intLocator>
1129void Triangulation<T, TNearPointLocator>::insertVertex(
1130 const VertInd iVert,
1131 const VertInd walkStart)
1133#ifdef CDT_ENABLE_CALLBACK_HANDLER
1134 if(m_callbackHandler)
1136 m_callbackHandler->onAddVertexStart(iVert, AddVertexType::UserInput);
1140 const array<TriInd, 2> trisAt = walkingSearchTrianglesAt(iVert, walkStart);
1141 std::stack<TriInd> triStack =
1142 trisAt[1] == noNeighbor
1143 ? insertVertexInsideTriangle(iVert, trisAt[0])
1144 : insertVertexOnEdge(iVert, trisAt[0], trisAt[1], true);
1145 ensureDelaunayByEdgeFlips(iVert, triStack);
1148template <
typename T,
typename TNearPo
intLocator>
1149void Triangulation<T, TNearPointLocator>::insertVertex(
const VertInd iVert)
1151 const V2d<T>& v = vertices[iVert];
1152 const VertInd walkStart = m_nearPtLocator.nearPoint(v, vertices);
1153 insertVertex(iVert, walkStart);
1154 tryAddVertexToLocator(iVert);
1157template <
typename T,
typename TNearPo
intLocator>
1158void Triangulation<T, TNearPointLocator>::ensureDelaunayByEdgeFlips(
1160 std::stack<TriInd>& triStack)
1162 TriInd iTopo, n1, n2, n3, n4;
1164 while(!triStack.empty())
1166 const TriInd iT = triStack.top();
1169 edgeFlipInfo(iT, iV1, iTopo, iV2, iV3, iV4, n1, n2, n3, n4);
1170 if(iTopo != noNeighbor && isFlipNeeded(iV1, iV2, iV3, iV4))
1172 flipEdge(iT, iTopo, iV1, iV2, iV3, iV4, n1, n2, n3, n4);
1174 triStack.push(iTopo);
1192template <
typename T,
typename TNearPo
intLocator>
1193void Triangulation<T, TNearPointLocator>::edgeFlipInfo(
1210 const Triangle& t = triangles[iT];
1211 if(t.vertices[0] == iV1)
1213 iV2 = t.vertices[1];
1214 iV4 = t.vertices[2];
1215 n1 = t.neighbors[0];
1216 n3 = t.neighbors[2];
1217 iTopo = t.neighbors[1];
1219 else if(t.vertices[1] == iV1)
1221 iV2 = t.vertices[2];
1222 iV4 = t.vertices[0];
1223 n1 = t.neighbors[1];
1224 n3 = t.neighbors[0];
1225 iTopo = t.neighbors[2];
1229 iV2 = t.vertices[0];
1230 iV4 = t.vertices[1];
1231 n1 = t.neighbors[2];
1232 n3 = t.neighbors[1];
1233 iTopo = t.neighbors[0];
1235 if(iTopo == noNeighbor)
1237 const Triangle& tOpo = triangles[iTopo];
1238 if(tOpo.neighbors[0] == iT)
1240 iV3 = tOpo.vertices[2];
1241 n2 = tOpo.neighbors[1];
1242 n4 = tOpo.neighbors[2];
1244 else if(tOpo.neighbors[1] == iT)
1246 iV3 = tOpo.vertices[0];
1247 n2 = tOpo.neighbors[2];
1248 n4 = tOpo.neighbors[0];
1252 iV3 = tOpo.vertices[1];
1253 n2 = tOpo.neighbors[0];
1254 n4 = tOpo.neighbors[1];
1281template <
typename T,
typename TNearPo
intLocator>
1282bool Triangulation<T, TNearPointLocator>::isFlipNeeded(
1286 const VertInd iV4)
const
1288 if(fixedEdges.count(Edge(iV2, iV4)))
1290 const V2d<T>& v1 = vertices[iV1];
1291 const V2d<T>& v2 = vertices[iV2];
1292 const V2d<T>& v3 = vertices[iV3];
1293 const V2d<T>& v4 = vertices[iV4];
1294 if(m_superGeomType == SuperGeometryType::SuperTriangle)
1351template <
typename T,
typename TNearPo
intLocator>
1356#ifdef CDT_ENABLE_CALLBACK_HANDLER
1357 if(m_callbackHandler)
1359 m_callbackHandler->onFlipEdge(iT, iTopo);
1365 const array<TriInd, 3>& triNs = t.
neighbors;
1366 const array<TriInd, 3>& triOpoNs = tOpo.
neighbors;
1367 const array<VertInd, 3>& triVs = t.
vertices;
1368 const array<VertInd, 3>& triOpoVs = tOpo.
vertices;
1373 const TriInd n1 = triNs[i];
1376 const VertInd v3 = triOpoVs[i];
1378 const TriInd n4 = triOpoNs[i];
1384 changeNeighbor(n1, iT, iTopo);
1385 changeNeighbor(n4, iTopo, iT);
1391 setAdjacentTriangle(v4, iT);
1392 setAdjacentTriangle(v2, iTopo);
1412template <
typename T,
typename TNearPo
intLocator>
1425#ifdef CDT_ENABLE_CALLBACK_HANDLER
1426 if(m_callbackHandler)
1428 m_callbackHandler->onFlipEdge(iT, iTopo);
1436 changeNeighbor(n1, iT, iTopo);
1437 changeNeighbor(n4, iTopo, iT);
1443 setAdjacentTriangle(v4, iT);
1444 setAdjacentTriangle(v2, iTopo);
1464template <
typename T,
typename TNearPo
intLocator>
1466Triangulation<T, TNearPointLocator>::insertVertexInsideTriangle(
1470 const TriInd iNewT1 = addTriangle();
1471 const TriInd iNewT2 = addTriangle();
1473#ifdef CDT_ENABLE_CALLBACK_HANDLER
1474 if(m_callbackHandler)
1476 m_callbackHandler->onInsertVertexInsideTriangle(iT, iNewT1, iNewT2);
1480 Triangle& t = triangles[iT];
1481 const array<VertInd, 3> vv = t.vertices;
1482 const array<TriInd, 3> nn = t.neighbors;
1483 const VertInd v1 = vv[0], v2 = vv[1], v3 = vv[2];
1484 const TriInd n1 = nn[0], n2 = nn[1], n3 = nn[2];
1487 triangles[iNewT1] = Triangle(arr3(v2, v3, v), arr3(n2, iNewT2, iT));
1488 triangles[iNewT2] = Triangle(arr3(v3, v1, v), arr3(n3, iT, iNewT1));
1489 t = Triangle(arr3(v1, v2, v), arr3(n1, iNewT1, iNewT2));
1491 setAdjacentTriangle(v, iT);
1492 setAdjacentTriangle(v3, iNewT1);
1494 changeNeighbor(n2, iT, iNewT1);
1495 changeNeighbor(n3, iT, iNewT2);
1497 std::stack<TriInd> newTriangles;
1498 newTriangles.push(iT);
1499 newTriangles.push(iNewT1);
1500 newTriangles.push(iNewT2);
1501 return newTriangles;
1517template <
typename T,
typename TNearPo
intLocator>
1518std::stack<TriInd> Triangulation<T, TNearPointLocator>::insertVertexOnEdge(
1522 const bool doHandleFixedSplitEdge)
1524 const TriInd iTnew1 = addTriangle();
1525 const TriInd iTnew2 = addTriangle();
1527#ifdef CDT_ENABLE_CALLBACK_HANDLER
1528 if(m_callbackHandler)
1530 m_callbackHandler->onInsertVertexOnEdge(iT1, iT2, iTnew1, iTnew2);
1534 Triangle& t1 = triangles[iT1];
1535 Triangle& t2 = triangles[iT2];
1537 const VertInd v1 = t1.vertices[i];
1539 const TriInd n1 = t1.neighbors[i];
1540 const TriInd n4 = t1.neighbors[
cw(i)];
1542 const VertInd v3 = t2.vertices[i];
1544 const TriInd n3 = t2.neighbors[i];
1545 const TriInd n2 = t2.neighbors[
cw(i)];
1547 t1 = Triangle(
arr3(v, v1, v2),
arr3(iTnew1, n1, iT2));
1548 t2 = Triangle(
arr3(v, v2, v3),
arr3(iT1, n2, iTnew2));
1549 triangles[iTnew1] = Triangle(
arr3(v, v4, v1),
arr3(iTnew2, n4, iT1));
1550 triangles[iTnew2] = Triangle(
arr3(v, v3, v4),
arr3(iT2, n3, iTnew1));
1552 setAdjacentTriangle(v, iT1);
1553 setAdjacentTriangle(v4, iTnew1);
1555 changeNeighbor(n4, iT1, iTnew1);
1556 changeNeighbor(n3, iT2, iTnew2);
1558 if(doHandleFixedSplitEdge)
1560 const Edge sharedEdge(v2, v4);
1561 if(fixedEdges.count(sharedEdge))
1562 splitFixedEdge(sharedEdge, v);
1565 std::stack<TriInd> newTriangles;
1566 newTriangles.push(iT1);
1567 newTriangles.push(iTnew2);
1568 newTriangles.push(iT2);
1569 newTriangles.push(iTnew1);
1570 return newTriangles;
1573template <
typename T,
typename TNearPo
intLocator>
1575Triangulation<T, TNearPointLocator>::trianglesAt(
const V2d<T>& pos)
const
1577 array<TriInd, 2> out = {noNeighbor, noNeighbor};
1578 for(TriInd i =
TriInd(0); i <
TriInd(triangles.size()); ++i)
1580 const Triangle& t = triangles[i];
1581 const V2d<T>& v1 = vertices[t.vertices[0]];
1582 const V2d<T>& v2 = vertices[t.vertices[1]];
1583 const V2d<T>& v3 = vertices[t.vertices[2]];
1585 if(loc == PtTriLocation::Outside)
1593 Error(
"No triangle was found at position", CDT_SOURCE_LOCATION));
1597template <
typename T,
typename TNearPo
intLocator>
1598TriInd Triangulation<T, TNearPointLocator>::walkTriangles(
1599 const VertInd startVertex,
1600 const V2d<T>& pos)
const
1603 TriInd currTri = m_vertTris[startVertex];
1605 detail::SplitMix64RandGen prng;
1608 const Triangle& t = triangles[currTri];
1611 const Index offset(prng() % 3);
1612 for(Index i_(0); i_ <
Index(3); ++i_)
1614 const Index i((i_ + offset) % 3);
1615 const V2d<T>& vStart = vertices[t.vertices[i]];
1616 const V2d<T>& vEnd = vertices[t.vertices[
ccw(i)]];
1617 const PtLineLocation::Enum edgeCheck =
1619 const TriInd iN = t.neighbors[i];
1620 if(edgeCheck == PtLineLocation::Right && iN != noNeighbor)
1631template <
typename T,
typename TNearPo
intLocator>
1632array<TriInd, 2> Triangulation<T, TNearPointLocator>::walkingSearchTrianglesAt(
1634 const VertInd startVertex)
const
1636 const V2d<T> v = vertices[iV];
1637 array<TriInd, 2> out = {noNeighbor, noNeighbor};
1638 const TriInd iT = walkTriangles(startVertex, v);
1640 const Triangle& t = triangles[iT];
1641 const V2d<T>& v1 = vertices[t.vertices[0]];
1642 const V2d<T>& v2 = vertices[t.vertices[1]];
1643 const V2d<T>& v3 = vertices[t.vertices[2]];
1646 if(loc == PtTriLocation::Outside)
1649 Error(
"No triangle was found at position", CDT_SOURCE_LOCATION));
1651 if(loc == PtTriLocation::OnVertex)
1653 const VertInd iDupe = v1 == v ? t.vertices[0]
1654 : v2 == v ? t.vertices[1]
1656 handleException(DuplicateVertexError(
1658 VertInd(iDupe - m_nTargetVerts),
1659 CDT_SOURCE_LOCATION));
1668template <
typename T,
typename TNearPo
intLocator>
1669void Triangulation<T, TNearPointLocator>::changeNeighbor(
1671 const TriInd oldNeighbor,
1672 const TriInd newNeighbor)
1674 if(iT == noNeighbor)
1678 nn[0] == oldNeighbor || nn[1] == oldNeighbor || nn[2] == oldNeighbor);
1679 if(nn[0] == oldNeighbor)
1680 nn[0] = newNeighbor;
1681 else if(nn[1] == oldNeighbor)
1682 nn[1] = newNeighbor;
1684 nn[2] = newNeighbor;
1687template <
typename T,
typename TNearPo
intLocator>
1688void Triangulation<T, TNearPointLocator>::changeNeighbor(
1690 const VertInd iVedge1,
1691 const VertInd iVedge2,
1692 const TriInd newNeighbor)
1694 assert(iT != noNeighbor);
1695 Triangle& t = triangles[iT];
1696 t.neighbors[
edgeNeighborInd(t.vertices, iVedge1, iVedge2)] = newNeighbor;
1699template <
typename T,
typename TNearPo
intLocator>
1700void Triangulation<T, TNearPointLocator>::triangulatePseudoPolygon(
1701 const std::vector<VertInd>& poly,
1702 unordered_map<Edge, TriInd>& outerTris,
1705 std::vector<TriInd>& trianglesToReuse,
1706 std::vector<TriangulatePseudoPolygonTask>& iterations)
1708 assert(poly.size() > 2);
1711 iterations.push_back(make_tuple(
1713 static_cast<IndexSizeType
>(poly.size() - 1),
1717 while(!iterations.empty())
1719 triangulatePseudoPolygonIteration(
1720 poly, outerTris, trianglesToReuse, iterations);
1724template <
typename T,
typename TNearPo
intLocator>
1725void Triangulation<T, TNearPointLocator>::triangulatePseudoPolygonIteration(
1726 const std::vector<VertInd>& poly,
1727 unordered_map<Edge, TriInd>& outerTris,
1728 std::vector<TriInd>& trianglesToReuse,
1729 std::vector<TriangulatePseudoPolygonTask>& iterations)
1731 IndexSizeType iA, iB;
1734 assert(!iterations.empty());
1735 tie(iA, iB, iT, iParent, iInParent) = iterations.back();
1736 iterations.pop_back();
1737 assert(iB - iA > 1 && iT != noNeighbor && iParent != noNeighbor);
1738 Triangle& t = triangles[iT];
1740 const IndexSizeType iC = findDelaunayPoint(poly, iA, iB);
1752 assert(!trianglesToReuse.empty());
1753 const TriInd iNext = trianglesToReuse.back();
1754 trianglesToReuse.pop_back();
1755 iterations.push_back(make_tuple(iC, iB, iNext, iT,
Index(1)));
1759 const Edge outerEdge(b, c);
1760 const TriInd outerTri = outerTris.at(outerEdge);
1761 if(outerTri != noNeighbor)
1763 assert(outerTri != iT);
1764 t.neighbors[1] = outerTri;
1765 changeNeighbor(outerTri, c, b, iT);
1768 outerTris.at(outerEdge) = iT;
1773 assert(!trianglesToReuse.empty());
1774 const TriInd iNext = trianglesToReuse.back();
1775 trianglesToReuse.pop_back();
1776 iterations.push_back(make_tuple(iA, iC, iNext, iT,
Index(2)));
1780 const Edge outerEdge(c, a);
1781 const TriInd outerTri = outerTris.at(outerEdge);
1782 if(outerTri != noNeighbor)
1784 assert(outerTri != iT);
1785 t.neighbors[2] = outerTri;
1786 changeNeighbor(outerTri, c, a, iT);
1789 outerTris.at(outerEdge) = iT;
1794 triangles[iParent].neighbors[iInParent] = iT;
1795 t.neighbors[0] = iParent;
1796 t.vertices =
arr3(a, b, c);
1797 setAdjacentTriangle(c, iT);
1800template <
typename T,
typename TNearPo
intLocator>
1801IndexSizeType Triangulation<T, TNearPointLocator>::findDelaunayPoint(
1802 const std::vector<VertInd>& poly,
1803 const IndexSizeType iA,
1804 const IndexSizeType iB)
const
1806 assert(iB - iA > 1);
1807 const V2d<T>& a = vertices[poly[iA]];
1808 const V2d<T>& b = vertices[poly[iB]];
1809 IndexSizeType out = iA + 1;
1810 const V2d<T>* c = &vertices[poly[out]];
1811 for(IndexSizeType i = iA + 1; i < iB; ++i)
1813 const V2d<T>& v = vertices[poly[i]];
1820 assert(out > iA && out < iB);
1824template <
typename T,
typename TNearPo
intLocator>
1826 const std::vector<
V2d<T> >& newVertices)
1832template <
typename T,
typename TNearPo
intLocator>
1835 return m_vertTris.empty() && !
vertices.empty();
1838template <
typename T,
typename TNearPo
intLocator>
1839unordered_map<TriInd, LayerDepth>
1840Triangulation<T, TNearPointLocator>::peelLayer(
1841 std::stack<TriInd> seeds,
1843 std::vector<LayerDepth>& triDepths)
const
1845 unordered_map<TriInd, LayerDepth> behindBoundary;
1846 while(!seeds.empty())
1848 const TriInd iT = seeds.top();
1850 triDepths[iT] = std::min(triDepths[iT], layerDepth);
1851 behindBoundary.erase(iT);
1857 if(iN == noNeighbor || triDepths[iN] <= layerDepth)
1859 if(fixedEdges.count(opEdge))
1861 const unordered_map<Edge, LayerDepth>::const_iterator cit =
1862 overlapCount.find(opEdge);
1863 const LayerDepth triDepth = cit == overlapCount.end()
1865 : layerDepth + cit->second + 1;
1866 behindBoundary[iN] = triDepth;
1872 return behindBoundary;
1875template <
typename T,
typename TNearPo
intLocator>
1876std::vector<LayerDepth>
1879 std::vector<LayerDepth> triDepths(
1880 triangles.size(), std::numeric_limits<LayerDepth>::max());
1881 std::stack<TriInd> seeds(TriDeque(1, m_vertTris[0]));
1885 unordered_map<LayerDepth, TriIndUSet> seedsByDepth;
1888 const unordered_map<TriInd, LayerDepth>& newSeeds =
1889 peelLayer(seeds, layerDepth, triDepths);
1891 seedsByDepth.erase(layerDepth);
1892 typedef unordered_map<TriInd, LayerDepth>::const_iterator Iter;
1893 for(Iter it = newSeeds.begin(); it != newSeeds.end(); ++it)
1895 deepestSeedDepth = std::max(deepestSeedDepth, it->second);
1896 seedsByDepth[it->second].insert(it->first);
1898 const TriIndUSet& nextLayerSeeds = seedsByDepth[layerDepth + 1];
1899 seeds = std::stack<TriInd>(
1900 TriDeque(nextLayerSeeds.begin(), nextLayerSeeds.end()));
1902 }
while(!seeds.empty() || deepestSeedDepth > layerDepth);
1907#ifdef CDT_ENABLE_CALLBACK_HANDLER
1908template <
typename T,
typename TNearPo
intLocator>
1912 m_callbackHandler = callbackHandler;
1916template <
typename T,
typename TNearPo
intLocator>
1917void Triangulation<T, TNearPointLocator>::insertVertices_AsProvided(
1920 for(
VertInd iV = superGeomVertCount; iV < vertices.size(); ++iV)
1922#ifdef CDT_ENABLE_CALLBACK_HANDLER
1923 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1932template <
typename T,
typename TNearPo
intLocator>
1933void Triangulation<T, TNearPointLocator>::insertVertices_Randomized(
1934 VertInd superGeomVertCount)
1936 std::size_t vertexCount = vertices.size() - superGeomVertCount;
1937 std::vector<VertInd> ii(vertexCount);
1938 detail::iota(ii.begin(), ii.end(), superGeomVertCount);
1939 detail::random_shuffle(ii.begin(), ii.end());
1940 for(std::vector<VertInd>::iterator it = ii.begin(); it != ii.end(); ++it)
1942#ifdef CDT_ENABLE_CALLBACK_HANDLER
1943 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
1956template <
typename T>
1957inline double log2_bc(T x)
1959#ifdef CDT_CXX11_IS_SUPPORTED
1960 return std::log2(x);
1962 static double log2_constant = std::log(2.0);
1963 return std::log(
static_cast<double>(x)) / log2_constant;
1973 const int filledLayerPow2 =
1974 static_cast<int>(std::floor(log2_bc(vertexCount)) - 1);
1975 const std::size_t nodesInFilledTree =
1976 static_cast<std::size_t
>(std::pow(2., filledLayerPow2 + 1) - 1);
1977 const std::size_t nodesInLastFilledLayer =
1978 static_cast<std::size_t
>(std::pow(2., filledLayerPow2));
1979 const std::size_t nodesInLastLayer = vertexCount - nodesInFilledTree;
1980 return nodesInLastLayer >= nodesInLastFilledLayer
1981 ? nodesInLastFilledLayer + nodesInLastLayer -
1982 nodesInLastFilledLayer
1983 : nodesInLastFilledLayer;
1986template <
typename T>
1987class FixedCapacityQueue
1990 FixedCapacityQueue(
const std::size_t capacity)
1992 , m_front(m_vec.begin())
1993 , m_back(m_vec.begin())
2000 const T& front()
const
2008 if(m_front == m_vec.end())
2009 m_front = m_vec.begin();
2012 void push(
const T& t)
2014 assert(m_size < m_vec.size());
2017 if(m_back == m_vec.end())
2018 m_back = m_vec.begin();
2021#ifdef CDT_CXX11_IS_SUPPORTED
2022 void push(
const T&& t)
2024 assert(m_size < m_vec.size());
2027 if(m_back == m_vec.end())
2028 m_back = m_vec.begin();
2033 std::vector<T> m_vec;
2034 typename std::vector<T>::iterator m_front;
2035 typename std::vector<T>::iterator m_back;
2039template <
typename T>
2042 const std::vector<V2d<T> >& m_vertices;
2045 less_than_x(
const std::vector<
V2d<T> >& vertices)
2046 : m_vertices(vertices)
2050 return m_vertices[a].x < m_vertices[b].x;
2054template <
typename T>
2057 const std::vector<V2d<T> >& m_vertices;
2060 less_than_y(
const std::vector<
V2d<T> >& vertices)
2061 : m_vertices(vertices)
2065 return m_vertices[a].y < m_vertices[b].y;
2071template <
typename T,
typename TNearPo
intLocator>
2072void Triangulation<T, TNearPointLocator>::insertVertices_KDTreeBFS(
2077 const VertInd vertexCount(vertices.size() - superGeomVertCount);
2080 std::vector<VertInd> ii(vertexCount);
2081 detail::iota(ii.begin(), ii.end(), superGeomVertCount);
2083 typedef std::vector<VertInd>::iterator It;
2086 queue.push(make_tuple(ii.begin(), ii.end(), box.
min, box.
max,
VertInd(0)));
2089 V2d<T> newBoxMin, newBoxMax;
2095 while(!queue.empty())
2097#ifdef CDT_ENABLE_CALLBACK_HANDLER
2098 if(m_callbackHandler && m_callbackHandler->isAbortCalculation())
2103 tie(first, last, box.
min, box.
max, parent) = queue.front();
2105 assert(first != last);
2107 const std::ptrdiff_t len = std::distance(first, last);
2110 insertVertex(*first, parent);
2113 const It midIt = first + len / 2;
2116 detail::portable_nth_element(first, midIt, last, cmpX);
2118 const T split = vertices[mid].x;
2119 newBoxMin.
x = split;
2120 newBoxMin.
y = box.
min.y;
2121 newBoxMax.
x = split;
2122 newBoxMax.
y = box.
max.y;
2126 detail::portable_nth_element(first, midIt, last, cmpY);
2128 const T split = vertices[mid].y;
2129 newBoxMin.
x = box.
min.x;
2130 newBoxMin.
y = split;
2131 newBoxMax.
x = box.
max.x;
2132 newBoxMax.
y = split;
2134 insertVertex(mid, parent);
2137 queue.push(make_tuple(first, midIt, box.
min, newBoxMax, mid));
2139 if(midIt + 1 != last)
2141 queue.push(make_tuple(midIt + 1, last, newBoxMin, box.
max, mid));
2146template <
typename T,
typename TNearPo
intLocator>
2147std::pair<TriInd, TriInd> Triangulation<T, TNearPointLocator>::edgeTriangles(
2149 const VertInd b)
const
2151 const TriInd triStart = m_vertTris[a];
2152 assert(triStart != noNeighbor);
2153 TriInd iT = triStart, iTNext = triStart;
2157 const Triangle& t = triangles[iT];
2158 tie(iTNext, iV) = t.
next(a);
2159 assert(iTNext != noNeighbor);
2162 return std::make_pair(iT, iTNext);
2165 }
while(iT != triStart);
2166 return std::make_pair(noNeighbor, noNeighbor);
2169template <
typename T,
typename TNearPo
intLocator>
2170bool Triangulation<T, TNearPointLocator>::hasEdge(
2172 const VertInd b)
const
2174 return edgeTriangles(a, b).first != invalidIndexSizeType;
2177template <
typename T,
typename TNearPo
intLocator>
2178void Triangulation<T, TNearPointLocator>::setAdjacentTriangle(
2182 assert(t != noNeighbor);
2185 triangles[t].vertices[0] == v || triangles[t].vertices[1] == v ||
2186 triangles[t].vertices[2] == v);
2189template <
typename T,
typename TNearPo
intLocator>
2190void Triangulation<T, TNearPointLocator>::pivotVertexTriangleCW(
const VertInd v)
2192 assert(m_vertTris[v] != noNeighbor);
2193 m_vertTris[v] = triangles[m_vertTris[v]].next(v).first;
2194 assert(m_vertTris[v] != noNeighbor);
2196 triangles[m_vertTris[v]].vertices[0] == v ||
2197 triangles[m_vertTris[v]].vertices[1] == v ||
2198 triangles[m_vertTris[v]].vertices[2] == v);
2201template <
typename T,
typename TNearPo
intLocator>
2202void Triangulation<T, TNearPointLocator>::tryAddVertexToLocator(
const VertInd v)
2204 if(!m_nearPtLocator.empty())
2205 m_nearPtLocator.addPoint(v, vertices);
2208template <
typename T,
typename TNearPo
intLocator>
2209void Triangulation<T, TNearPointLocator>::tryInitNearestPointLocator()
2211 if(!vertices.empty() && m_nearPtLocator.empty())
2213 m_nearPtLocator.initialize(vertices);
void iota(ForwardIt first, ForwardIt last, T value)
backport from c++11
std::size_t maxQueueLengthBFSKDTree(const std::size_t vertexCount)
Since KD-tree bulk load builds a balanced tree the maximum length of a queue can be pre-calculated: i...
Interface for the callback handler that user can derive from and inject into the triangulation to mon...
Error thrown when intersecting constraint edges are detected, but triangulation is not configured to ...
Error thrown when resolving intersecting constraints fails: floating-point rounding places the comput...
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< LayerDepth > calculateTriangleDepths() const
Calculate depth of each triangle in constraint triangulation.
bool isFinalized() const
Check if the triangulation was finalized with erase... method and super-triangle was removed.
void eraseOuterTrianglesAndHoles()
Erase triangles outside of constrained boundary and auto-detected holes.
V2dVec vertices
triangulation's vertices
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.
void eraseSuperTriangle()
Erase triangles adjacent to super triangle.
TriangleVec triangles
triangulation's triangles
Triangulation()
Default constructor.
void setCallbackHandler(ICallbackHandler *callbackHandler)
Set user-provided callback handler.
void initializedWithCustomSuperGeometry()
Call this method after directly setting custom super-geometry via vertices and triangles members.
unsigned short LayerDepth
Type used for storing layer depths for triangles.
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.
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY VertInd opposedVertex(const Triangle &tri, TriInd iTopo)
Given two triangles, return vertex of first triangle opposed to the second.
unordered_set< Edge > EdgeUSet
Hash table of edges.
VertInd edge_get_v2(const Edge &e)
Get edge second vertex.
std::vector< TriInd > TriIndVec
Vector of triangle indices.
CDT_INLINE_IF_HEADER_ONLY Index edgeNeighborInd(const VerticesArr3 &vv, VertInd iVedge1, VertInd iVedge2)
Index of triangle's neighbor opposed to an edge.
VertInd edge_get_v1(const Edge &e)
Get edge first vertex.
CDT_EXPORT PtLineLocation::Enum classifyOrientation(T orientation, T orientationTolerance=T(0))
Classify value of orient2d predicate.
array< TriInd, 3 > NeighborsArr3
array of three neighbors
CDT_EXPORT T distance(const V2d< T > &a, const V2d< T > &b)
Distance between two 2D points.
IndexSizeType VertInd
Vertex index.
CDT_EXPORT Index cw(Index i)
Advance vertex or neighbor index clockwise.
array< VertInd, 3 > VerticesArr3
array of three vertex indices
CDT_INLINE_IF_HEADER_ONLY bool touchesSuperTriangle(const Triangle &t)
Check if any of triangle's vertices belongs to a super-triangle.
array< T, 3 > arr3(const T &v0, const T &v1, const T &v2)
Needed for c++03 compatibility (no uniform initialization available)
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opoNbr(Index vertIndex)
Opposed neighbor index from vertex index.
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index vertexInd(const VerticesArr3 &vv, VertInd iV)
If triangle has a given vertex return vertex-index.
CDT_EXPORT T orient2D(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2)
Orient p against line v1-v2 2D: robust geometric predicate.
CDT_EXPORT PtLineLocation::Enum locatePointLine(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, T orientationTolerance=T(0))
Check if point lies to the left of, to the right of, or on a line.
unordered_set< TriInd > TriIndUSet
Hash table of triangles.
CDT_EXPORT Index ccw(Index i)
Advance vertex or neighbor index counter-clockwise.
CDT_EXPORT Index edgeNeighbor(PtTriLocation::Enum location)
Neighbor index from a on-edge location.
unordered_map< TriInd, TriInd > TriIndUMap
Triangle hash map.
const T & getX_V2d(const V2d< T > &v)
X- coordinate getter for V2d.
unsigned char Index
Index in triangle.
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY TriInd opposedTriangle(const Triangle &tri, VertInd iVert)
Given triangle and a vertex find opposed triangle.
CDT_EXPORT bool isInCircumcircle(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, const V2d< T > &v3)
Test if point lies in a circumscribed circle of a triangle.
Edge RemapNoSuperTriangle(const Edge &e)
Remap removing super-triangle: subtract 3 from vertices.
CDT_EXPORT bool isOnEdge(PtTriLocation::Enum location)
Check if location is classified as on any of three edges.
IndexSizeType TriInd
Triangle index.
CDT_EXPORT PtTriLocation::Enum locatePointTriangle(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, const V2d< T > &v3)
Check if point a lies inside of, outside of, or on an edge of a triangle.
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opposedVertexInd(const NeighborsArr3 &nn, TriInd iTopo)
Index of triangle's vertex opposed to a triangle.
const T & getY_V2d(const V2d< T > &v)
Y-coordinate getter for V2d.
@ FixedEdgeMidpoint
During conforming triangulation edge mid-point is added.
@ FixedEdgesIntersection
Resolving fixed/constraint edges' intersection.
V2d< T > max
max box corner
V2d< T > min
min box corner
Edge connecting two vertices: vertex with smaller index is always first.
VertInd v1() const
V1 getter.
VertInd v2() const
V2 getter.
@ TryResolve
attempt to resolve constraint edge intersections
@ NotAllowed
constraint edge intersections are not allowed
@ DontCheck
No checks: slightly faster but less safe.
@ SuperTriangle
conventional super-triangle
@ Custom
user-specified custom geometry (e.g., grid)
Triangulation triangle (counter-clockwise winding)
VerticesArr3 vertices
triangle's three vertices
NeighborsArr3 neighbors
triangle's three neighbors
std::pair< TriInd, VertInd > next(const VertInd i) const
Next triangle adjacent to a vertex (clockwise)
@ Auto
Automatic insertion order optimized for better performance.