Skip to content

Commit

Permalink
Fix producing zeros in overlaps map, adjust tests, refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
artem-ogre committed Sep 29, 2023
1 parent 8abda70 commit b6b5da2
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 160 deletions.
7 changes: 6 additions & 1 deletion CDT/include/Triangulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -558,9 +558,14 @@ class CDT_EXPORT Triangulation
*/
void finalizeTriangulation(const TriIndUSet& removedTriangles);
TriIndUSet growToBoundary(std::stack<TriInd> seeds) const;
void fixEdge(const Edge& edge, BoundaryOverlapCount overlaps);
void fixEdge(const Edge& edge);
void fixEdge(const Edge& edge, const Edge& originalEdge);
VertInd splitFixedEdgeAt(
const Edge& edge,
const V2d<T>& v,
const TriInd iT,
const TriInd iTopo);
VertInd splitFixedEdgeAt(const Edge& edge, const V2d<T>& v);
/**
* Flag triangle as dummy
* @note Advanced method for manually modifying the triangulation from
Expand Down
199 changes: 81 additions & 118 deletions CDT/include/Triangulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,22 +401,68 @@ void insert_unique(
} // namespace detail

template <typename T, typename TNearPointLocator>
void Triangulation<T, TNearPointLocator>::fixEdge(
VertInd Triangulation<T, TNearPointLocator>::splitFixedEdgeAt(
const Edge& edge,
const Edge& originalEdge)
const V2d<T>& v,
const TriInd iT,
const TriInd iTopo)
{
fixEdge(edge);
if(edge != originalEdge)
detail::insert_unique(pieceToOriginals[edge], originalEdge);
const VertInd iNewVert = static_cast<VertInd>(vertices.size());

// split constraint edge that already exists in triangulation
const Edge half1(edge.v1(), iNewVert);
const Edge half2(iNewVert, edge.v2());
// remove the edge that and add its halves
fixedEdges.erase(edge);
fixEdge(half1);
fixEdge(half2);
// maintain overlaps
typedef unordered_map<Edge, BoundaryOverlapCount>::const_iterator It;
const It overlapIt = overlapCount.find(edge);
if(overlapIt != overlapCount.end())
{
overlapCount[half1] += overlapIt->second;
overlapCount[half2] += overlapIt->second;
overlapCount.erase(overlapIt);
}
// maintain piece-to-original mapping
EdgeVec newOriginals(1, edge);
const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
pieceToOriginals.find(edge);
if(originalsIt != pieceToOriginals.end())
{ // edge being split was split before: pass-through originals
newOriginals = originalsIt->second;
pieceToOriginals.erase(originalsIt);
}
detail::insert_unique(pieceToOriginals[half1], newOriginals);
detail::insert_unique(pieceToOriginals[half2], newOriginals);
// add a new point at the intersection of two constraint edges
addNewVertex(v, noNeighbor);
std::stack<TriInd> triStack = insertVertexOnEdge(iNewVert, iT, iTopo);
tryAddVertexToLocator(iNewVert);
ensureDelaunayByEdgeFlips(v, iNewVert, triStack);

return iNewVert;
}

template <typename T, typename TNearPointLocator>
VertInd Triangulation<T, TNearPointLocator>::splitFixedEdgeAt(
const Edge& edge,
const V2d<T>& v)
{
TriInd iT, iTopo;
std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2());
return splitFixedEdgeAt(edge, v, iT, iTopo);
}

template <typename T, typename TNearPointLocator>
void Triangulation<T, TNearPointLocator>::fixEdge(
const Edge& edge,
const BoundaryOverlapCount overlaps)
const Edge& originalEdge)
{
fixedEdges.insert(edge);
overlapCount[edge] = overlaps; // override overlap counter
fixEdge(edge);
if(edge != originalEdge)
detail::insert_unique(pieceToOriginals[edge], originalEdge);
}

namespace detail
Expand Down Expand Up @@ -519,38 +565,10 @@ void Triangulation<T, TNearPointLocator>::insertEdgeIteration(
IntersectingConstraintEdges::Resolve &&
fixedEdges.count(Edge(iVL, iVR)))
{
const VertInd iNewVert = static_cast<VertInd>(vertices.size());

// split constraint edge that already exists in triangulation
const Edge splitEdge(iVL, iVR);
const Edge half1(iVL, iNewVert);
const Edge half2(iNewVert, iVR);
const BoundaryOverlapCount overlaps = overlapCount[splitEdge];
// remove the edge that will be split
fixedEdges.erase(splitEdge);
overlapCount.erase(splitEdge);
// add split edge's halves
fixEdge(half1, overlaps);
fixEdge(half2, overlaps);
// maintain piece-to-original mapping
EdgeVec newOriginals(1, splitEdge);
const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
pieceToOriginals.find(splitEdge);
if(originalsIt != pieceToOriginals.end())
{ // edge being split was split before: pass-through originals
newOriginals = originalsIt->second;
pieceToOriginals.erase(originalsIt);
}
detail::insert_unique(pieceToOriginals[half1], newOriginals);
detail::insert_unique(pieceToOriginals[half2], newOriginals);
// add a new point at the intersection of two constraint edges
// split edge at the intersection of two constraint edges
const V2d<T> newV = detail::intersectionPosition(
vertices[iA], vertices[iB], vertices[iVL], vertices[iVR]);
addNewVertex(newV, noNeighbor);
std::stack<TriInd> triStack =
insertVertexOnEdge(iNewVert, iT, iTopo);
tryAddVertexToLocator(iNewVert);
ensureDelaunayByEdgeFlips(newV, iNewVert, triStack);
const VertInd iNewVert = splitFixedEdgeAt(Edge(iVL, iVR), newV, iT, iTopo);
// TODO: is it's possible to re-use pseudo-polygons
// for inserting [iA, iNewVert] edge half?
remaining.push_back(Edge(iA, iNewVert));
Expand Down Expand Up @@ -673,7 +691,9 @@ void Triangulation<T, TNearPointLocator>::conformToEdgeIteration(

if(hasEdge(iA, iB))
{
overlaps > 0 ? fixEdge(edge, overlaps) : fixEdge(edge);
fixEdge(edge);
if(overlaps > 0)
overlapCount[edge] = overlaps;
// avoid marking edge as a part of itself
if(!originals.empty() && edge != originals.front())
{
Expand All @@ -695,7 +715,9 @@ void Triangulation<T, TNearPointLocator>::conformToEdgeIteration(
if(iT == noNeighbor)
{
const Edge edgePart(iA, iVleft);
overlaps > 0 ? fixEdge(edgePart, overlaps) : fixEdge(edgePart);
fixEdge(edgePart);
if(overlaps > 0)
overlapCount[edgePart] = overlaps;
detail::insert_unique(pieceToOriginals[edgePart], originals);
#ifdef CDT_CXX11_IS_SUPPORTED
remaining.emplace_back(Edge(iVleft, iB), originals, overlaps);
Expand All @@ -720,56 +742,14 @@ void Triangulation<T, TNearPointLocator>::conformToEdgeIteration(
IntersectingConstraintEdges::Resolve &&
fixedEdges.count(Edge(iVleft, iVright)))
{
const VertInd iNewVert = static_cast<VertInd>(vertices.size());

// split constraint edge that already exists in triangulation
const Edge splitEdge(iVleft, iVright);
const Edge half1(iVleft, iNewVert);
const Edge half2(iNewVert, iVright);

const unordered_map<Edge, BoundaryOverlapCount>::const_iterator
splitEdgeOverlapsIt = overlapCount.find(splitEdge);
const BoundaryOverlapCount splitEdgeOverlaps =
splitEdgeOverlapsIt != overlapCount.end()
? splitEdgeOverlapsIt->second
: 0;
// remove the edge that will be split and add split edge's
// halves
fixedEdges.erase(splitEdge);
if(splitEdgeOverlaps > 0)
{
overlapCount.erase(splitEdgeOverlapsIt);
fixEdge(half1, splitEdgeOverlaps);
fixEdge(half2, splitEdgeOverlaps);
}
else
{
fixEdge(half1);
fixEdge(half2);
}
// maintain piece-to-original mapping
EdgeVec newOriginals(1, splitEdge);
const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
pieceToOriginals.find(splitEdge);
if(originalsIt != pieceToOriginals.end())
{ // edge being split was split before: pass-through originals
newOriginals = originalsIt->second;
pieceToOriginals.erase(originalsIt);
}
detail::insert_unique(pieceToOriginals[half1], newOriginals);
detail::insert_unique(pieceToOriginals[half2], newOriginals);

// add a new point at the intersection of two constraint edges
// split edge at the intersection of two constraint edges
const V2d<T> newV = detail::intersectionPosition(
vertices[iA],
vertices[iB],
vertices[iVleft],
vertices[iVright]);
addNewVertex(newV, noNeighbor);
std::stack<TriInd> triStack =
insertVertexOnEdge(iNewVert, iT, iTopo);
tryAddVertexToLocator(iNewVert);
ensureDelaunayByEdgeFlips(newV, iNewVert, triStack);
const VertInd iNewVert =
splitFixedEdgeAt(Edge(iVleft, iVright), newV, iT, iTopo);
#ifdef CDT_CXX11_IS_SUPPORTED
remaining.emplace_back(Edge(iNewVert, iB), originals, overlaps);
remaining.emplace_back(Edge(iA, iNewVert), originals, overlaps);
Expand Down Expand Up @@ -1319,7 +1299,6 @@ TriIndVec Triangulation<T, TNearPointLocator>::resolveEncroachedEdges(
const RefinementCriterion::Enum refinementCriterion,
const T badTriangleThreshold)
{
IndexSizeType numOfSplits = 0;
std::vector<TriInd> badTriangles;

while(!encroachedEdges.empty() && remainingVertexBudget > 0)
Expand Down Expand Up @@ -1368,18 +1347,14 @@ VertInd Triangulation<T, TNearPointLocator>::splitEncroachedEdge(
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<VertInd>(vertices.size());
const V2d<T>& start = vertices[edge.v1()];
const V2d<T>& end = vertices[edge.v2()];
T split = T(0.5);
// check if any of the split edge vertices are Steiner vertices
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.
// that introduces FP rounding errors, so it's avoided.
const T len = distance(start, end);
const T d = len / T(2);
// Find the splitting distance
Expand All @@ -1397,39 +1372,27 @@ VertInd Triangulation<T, TNearPointLocator>::splitEncroachedEdge(
if(edge.v1() >= steinerVerticesOffset)
split = T(1) - split;
}

const V2d<T> mid = V2d<T>::make(
detail::lerp(start.x, end.x, split),
detail::lerp(start.y, end.y, split));
TriInd iT, iTopo;
std::tie(iT, iTopo) = edgeTriangles(edge.v1(), edge.v2());
assert(iT != invalidIndex && iTopo != invalidIndex);

// split constraint edge that already exists in triangulation
if(fixedEdges.find(edge) != fixedEdges.end())
{
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(edge);
overlapCount.erase(edge);
// add split edge's halves
fixEdge(half1, overlaps);
fixEdge(half2, overlaps);
// maintain piece-to-original mapping
EdgeVec newOriginals(1, edge);
const unordered_map<Edge, EdgeVec>::const_iterator originalsIt =
pieceToOriginals.find(edge);
if(originalsIt != pieceToOriginals.end())
{ // edge being split was split before: pass-through originals
newOriginals = originalsIt->second;
pieceToOriginals.erase(originalsIt);
}
detail::insert_unique(pieceToOriginals[half1], newOriginals);
detail::insert_unique(pieceToOriginals[half2], newOriginals);
}
addNewVertex(mid, noNeighbor);
std::stack<TriInd> triStack = insertVertexOnEdge(iMid, iT, iTopo);
tryAddVertexToLocator(iMid);
ensureDelaunayByEdgeFlips(mid, iMid, triStack);
return iMid;
return splitFixedEdgeAt(edge, mid, iT, iTopo);
}
else
{
const VertInd iMid = static_cast<VertInd>(vertices.size());
addNewVertex(mid, noNeighbor);
std::stack<TriInd> triStack = insertVertexOnEdge(iMid, iT, iTopo);
tryAddVertexToLocator(iMid);
ensureDelaunayByEdgeFlips(mid, iMid, triStack);
return iMid;
}
}

/* Flip edge between T and Topo:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
7 10
8 10

2
6 10 0
8 10 0
0

4
3 10
Expand Down
5 changes: 1 addition & 4 deletions CDT/tests/expected/corner cases__as-provided_resolve_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,11 @@
15 16
17 18

7
4
3 15 1
8 9 1
8 16 1
9 17 0
14 18 0
15 16 1
17 18 0

15
3 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
12 13
14 15

7
4
0 12 1
5 6 1
5 13 1
6 14 0
11 15 0
12 13 1
14 15 0

15
0 12
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
12 13
14 15

7
4
0 12 1
5 6 1
5 13 1
6 14 0
11 15 0
12 13 1
14 15 0

15
0 12
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,11 @@
12 13
14 15

7
4
0 12 1
5 6 1
5 13 1
6 14 0
11 15 0
12 13 1
14 15 0

15
0 12
Expand Down
5 changes: 1 addition & 4 deletions CDT/tests/expected/corner cases__auto_resolve_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,11 @@
15 16
17 18

7
4
3 15 1
8 9 1
8 16 1
9 17 0
14 18 0
15 16 1
17 18 0

15
3 15
Expand Down
Loading

0 comments on commit b6b5da2

Please sign in to comment.