From 1688fc30c50fd6cf2ccd535896534e799d50946f Mon Sep 17 00:00:00 2001 From: artem-ogre Date: Tue, 22 Aug 2023 10:44:26 +0200 Subject: [PATCH] #7 Code refactoring and cleanup --- CDT/include/CDTUtils.h | 2 + CDT/include/CDTUtils.hpp | 5 ++ CDT/include/Triangulation.h | 22 ++--- CDT/include/Triangulation.hpp | 152 ++++++++++++++++------------------ 4 files changed, 85 insertions(+), 96 deletions(-) diff --git a/CDT/include/CDTUtils.h b/CDT/include/CDTUtils.h index 8128013..968d16b 100644 --- a/CDT/include/CDTUtils.h +++ b/CDT/include/CDTUtils.h @@ -463,6 +463,8 @@ sineOfSmallestAngle(const V2d& a, const V2d& b, const V2d& c); template CDT_EXPORT T smallestAngle(const V2d& a, const V2d& b, const V2d& c); +CDT_EXPORT bool touchesSuperTriangle(const Triangle& t); + } // namespace CDT #ifndef CDT_USE_AS_COMPILED_LIBRARY diff --git a/CDT/include/CDTUtils.hpp b/CDT/include/CDTUtils.hpp index c6e3a0c..026c080 100644 --- a/CDT/include/CDTUtils.hpp +++ b/CDT/include/CDTUtils.hpp @@ -363,4 +363,9 @@ T smallestAngle(const V2d& a, const V2d& b, const V2d& c) return std::asin(angleSine); } +bool touchesSuperTriangle(const Triangle& t) +{ + return t.vertices[0] < 3 || t.vertices[1] < 3 || t.vertices[2] < 3; +} + } // namespace CDT diff --git a/CDT/include/Triangulation.h b/CDT/include/Triangulation.h index cf80d66..ed22ef4 100644 --- a/CDT/include/Triangulation.h +++ b/CDT/include/Triangulation.h @@ -520,16 +520,14 @@ class CDT_EXPORT Triangulation const Triangle& tri, RefinementCriterion::Enum refinementCriterion, T refinementThreshold) const; - /// Search in all fixed edges to find encroached edges, each fixed edge is - /// checked against its opposite vertices - /// Returns queue of encroached edges - EdgeQueue detectEncroachedEdges(); - /// Search in all fixed edges to find encroached edges, each fixed edge is - /// checked against its opposite vertices and vertex v - /// Returns queue of encroached edges - EdgeQueue detectEncroachedEdges(const V2d& v); + /// Check if edge is encroached by its opposed vertices + bool isEdgeEncroached(const Edge& edge) const; + bool isEdgeEncroachedBy(const Edge& edge, const V2d& v) const; + /// Find all fixed edges encroached by its opposed vertices + EdgeQueue allEncroachedEdges() const; + /// Find all fixed edges encroached by a given vertex + EdgeQueue edgesEncroachedBy(const V2d& v) const; /// Recursively split encroached edges - /// @return vector of badly shaped triangles TriIndVec resolveEncroachedEdges( EdgeQueue encroachedEdges, VertInd& newVertBudget, @@ -538,11 +536,7 @@ class CDT_EXPORT Triangulation RefinementCriterion::Enum refinementCriterion = RefinementCriterion::SmallestAngle, T badTriangleThreshold = T(0)); - VertInd splitEncroachedEdge( - Edge e, - TriInd iT, - TriInd iTopo, - VertInd steinerVerticesOffset); + VertInd splitEncroachedEdge(Edge edge, VertInd steinerVerticesOffset); void changeNeighbor(TriInd iT, TriInd oldNeighbor, TriInd newNeighbor); void changeNeighbor( TriInd iT, diff --git a/CDT/include/Triangulation.hpp b/CDT/include/Triangulation.hpp index 0357ed2..ffc3291 100644 --- a/CDT/include/Triangulation.hpp +++ b/CDT/include/Triangulation.hpp @@ -136,8 +136,7 @@ void Triangulation::eraseSuperTriangle() TriIndUSet toErase; for(TriInd iT(0); iT < TriInd(triangles.size()); ++iT) { - Triangle& t = triangles[iT]; - if(t.vertices[0] < 3 || t.vertices[1] < 3 || t.vertices[2] < 3) + if(touchesSuperTriangle(triangles[iT])) toErase.insert(iT); } finalizeTriangulation(toErase); @@ -1283,25 +1282,39 @@ bool Triangulation::isRefinementNeeded( } template -EdgeQueue Triangulation::detectEncroachedEdges() +bool Triangulation::isEdgeEncroached( + const Edge& edge) const +{ + TriInd iT, iTopo; + std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2()); + assert(iT != invalidIndex && iTopo != invalidIndex); + const VertInd v1 = opposedVertex(triangles[iT], iTopo); + const VertInd v2 = opposedVertex(triangles[iTopo], iT); + const V2d& edgeStart = vertices[edge.v1()]; + const V2d& edgeEnd = vertices[edge.v2()]; + return isEncroachingOnEdge(vertices[v1], edgeStart, edgeEnd) || + isEncroachingOnEdge(vertices[v2], edgeStart, edgeEnd); +} + +template +bool Triangulation::isEdgeEncroachedBy( + const Edge& edge, + const V2d& v) const { - // Search in all fixed edges to find encroached edges, each fixed edge is - // checked against its opposite vertices + return isEncroachingOnEdge(v, vertices[edge.v1()], vertices[edge.v2()]); +} + +template +EdgeQueue Triangulation::allEncroachedEdges() const +{ + // Search in all fixed edges to find encroached edges // Returns queue of encroached edges EdgeQueue encroachedEdges; typedef EdgeUSet::const_iterator Iter; for(Iter it = fixedEdges.begin(); it != fixedEdges.end(); ++it) { const Edge edge = *it; - TriInd iT, iTopo; - std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2()); - assert(iT != invalidIndex && iTopo != invalidIndex); - const VertInd v1 = opposedVertex(triangles[iT], iTopo); - const VertInd v2 = opposedVertex(triangles[iTopo], iT); - const V2d& edgeStart = vertices[edge.v1()]; - const V2d& edgeEnd = vertices[edge.v2()]; - if(isEncroachingOnEdge(vertices[v1], edgeStart, edgeEnd) || - isEncroachingOnEdge(vertices[v2], edgeStart, edgeEnd)) + if(isEdgeEncroached(edge)) { encroachedEdges.push(edge); } @@ -1311,19 +1324,17 @@ EdgeQueue Triangulation::detectEncroachedEdges() template EdgeQueue -Triangulation::detectEncroachedEdges(const V2d& v) +Triangulation::edgesEncroachedBy(const V2d& v) const { - // Search in all fixed edges to find encroached edges, each fixed edge is - // checked against its opposite vertices and vertex v - // Returns queue of encroached edges + // Search in all fixed edges to find edges encroached by v, each fixed edge + // is checked vertex v Returns queue of encroached edges EdgeQueue encroachedEdges; typedef EdgeUSet::const_iterator Iter; for(Iter it = fixedEdges.begin(); it != fixedEdges.end(); ++it) { - const Edge edge = *it; - if(isEncroachingOnEdge(v, vertices[edge.v1()], vertices[edge.v2()])) + if(isEdgeEncroachedBy(*it, v)) { - encroachedEdges.push(edge); + encroachedEdges.push(*it); } } return encroachedEdges; @@ -1345,74 +1356,62 @@ TriIndVec Triangulation::resolveEncroachedEdges( { const Edge edge = encroachedEdges.front(); encroachedEdges.pop(); - if(!hasEdge(edge.v1(), edge.v2())) + if(fixedEdges.find(edge) == fixedEdges.end()) { continue; } - TriInd iT, iTopo; - std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2()); - assert(iT != invalidIndex && iTopo != invalidIndex); - const VertInd i = - splitEncroachedEdge(edge, iT, iTopo, steinerVerticesOffset); + // split encroached edge + const VertInd iSplitVert = + splitEncroachedEdge(edge, steinerVerticesOffset); --remainingVertexBudget; - const TriInd start = m_vertTris[i]; - TriInd currTri = start; + const TriInd start = m_vertTris[iSplitVert]; + TriInd iT = start; do { - const Triangle& t = triangles[currTri]; + const Triangle& t = triangles[iT]; if(circumcenterOrNull && isRefinementNeeded(t, refinementCriterion, badTriangleThreshold)) { - badTriangles.push_back(currTri); + badTriangles.push_back(iT); } - for(int i = 0; i < 3; ++i) + for(Index i(0); i < Index(3); ++i) { - const Edge edge(t.vertices[i], t.vertices[cw(i)]); - if(fixedEdges.find(edge) == fixedEdges.end()) + const Edge triEdge(t.vertices[i], t.vertices[cw(i)]); + if(fixedEdges.find(triEdge) == fixedEdges.end()) continue; - const TriInd iT = currTri; - const TriInd iTopo = - edgeNeighbor(triangles[iT], edge.v1(), edge.v2()); - const Triangle& tOpo = triangles[iTopo]; - VertInd v1 = opposedVertex(t, iTopo); - VertInd v2 = opposedVertex(tOpo, iT); - const V2d& edgeStart = vertices[edge.v1()]; - const V2d& edgeEnd = vertices[edge.v2()]; - if(isEncroachingOnEdge(vertices[v1], edgeStart, edgeEnd) || - isEncroachingOnEdge(vertices[v2], edgeStart, edgeEnd) || + if(isEdgeEncroached(triEdge) || (circumcenterOrNull && - isEncroachingOnEdge( - *circumcenterOrNull, edgeStart, edgeEnd))) + isEdgeEncroachedBy(triEdge, *circumcenterOrNull))) { - encroachedEdges.push(edge); + encroachedEdges.push(triEdge); } } - currTri = t.next(i).first; - } while(currTri != start); + iT = t.next(iSplitVert).first; + } while(iT != start); } return badTriangles; } template VertInd Triangulation::splitEncroachedEdge( - const Edge splitEdge, - const TriInd iT, - const TriInd iTopo, + const Edge edge, const VertInd steinerVerticesOffset) { + TriInd iT, iTopo; + std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2()); + assert(iT != invalidIndex && iTopo != invalidIndex); const VertInd iMid = static_cast(vertices.size()); - const V2d& start = vertices[splitEdge.v1()]; - const V2d& end = vertices[splitEdge.v2()]; + const V2d& start = vertices[edge.v1()]; + const V2d& end = vertices[edge.v2()]; T split = T(0.5); // check if any of the split edge vertices are Steiner vertices - if(splitEdge.v1() >= steinerVerticesOffset || - splitEdge.v2() >= steinerVerticesOffset) + if(edge.v1() >= steinerVerticesOffset || edge.v2() >= steinerVerticesOffset) { // In Ruppert's paper, he used D(0.01) factor to divide edge length, but // that introduces FP rounding erros, so it's avoided. const T len = distance(start, end); - const T d = T(0.5) * len; + const T d = len / T(2); // Find the splitting distance T nearestPowerOfTwo = T(1); while(d > nearestPowerOfTwo) @@ -1425,7 +1424,7 @@ VertInd Triangulation::splitEncroachedEdge( } assert(abs(nearestPowerOfTwo - pow(2, round(log(d) / log(2.0)))) < 1e6); split = nearestPowerOfTwo / len; - if(splitEdge.v1() >= steinerVerticesOffset) + if(edge.v1() >= steinerVerticesOffset) split = T(1) - split; } const V2d mid = V2d::make( @@ -1433,21 +1432,21 @@ VertInd Triangulation::splitEncroachedEdge( detail::lerp(start.y, end.y, split)); // split constraint edge that already exists in triangulation - if(fixedEdges.find(splitEdge) != fixedEdges.end()) + if(fixedEdges.find(edge) != fixedEdges.end()) { - const Edge half1(splitEdge.v1(), iMid); - const Edge half2(iMid, splitEdge.v2()); - const BoundaryOverlapCount overlaps = overlapCount[splitEdge]; + const Edge half1(edge.v1(), iMid); + const Edge half2(iMid, edge.v2()); + const BoundaryOverlapCount overlaps = overlapCount[edge]; // remove the edge that will be split - fixedEdges.erase(splitEdge); - overlapCount.erase(splitEdge); + fixedEdges.erase(edge); + overlapCount.erase(edge); // add split edge's halves fixEdge(half1, overlaps); fixEdge(half2, overlaps); // maintain piece-to-original mapping - EdgeVec newOriginals(1, splitEdge); + EdgeVec newOriginals(1, edge); const unordered_map::const_iterator originalsIt = - pieceToOriginals.find(splitEdge); + pieceToOriginals.find(edge); if(originalsIt != pieceToOriginals.end()) { // edge being split was split before: pass-through originals newOriginals = originalsIt->second; @@ -2278,27 +2277,16 @@ void Triangulation::refineTriangles( VertInd remainingVertexBudget = maxVerticesToInsert; const VertInd steinerVerticesOffset = vertices.size(); resolveEncroachedEdges( - detectEncroachedEdges(), remainingVertexBudget, steinerVerticesOffset); + allEncroachedEdges(), remainingVertexBudget, steinerVerticesOffset); std::queue badTriangles; for(TriInd iT(0), n = triangles.size(); iT < n; ++iT) { const Triangle& t = triangles[iT]; - if(t.vertices[0] < 3 || t.vertices[1] < 3 || t.vertices[2] < 3) - continue; - - if(isRefinementNeeded(t, refinementCriterion, refinementThreshold)) + if(!touchesSuperTriangle(t) && + isRefinementNeeded(t, refinementCriterion, refinementThreshold)) { - const V2d vert = circumcenter( - vertices[t.vertices[0]], - vertices[t.vertices[1]], - vertices[t.vertices[2]]); - if(locatePointTriangle( - vert, vertices[0], vertices[1], vertices[2]) != - PtTriLocation::Outside) - { - badTriangles.push(iT); - } + badTriangles.push(iT); } } @@ -2323,7 +2311,7 @@ void Triangulation::refineTriangles( } const TriIndVec badTris = resolveEncroachedEdges( - detectEncroachedEdges(vert), + edgesEncroachedBy(vert), remainingVertexBudget, steinerVerticesOffset, &vert,