diff --git a/src/manifold/src/edge_op.cpp b/src/manifold/src/edge_op.cpp index 05353deab..26fd983e8 100644 --- a/src/manifold/src/edge_op.cpp +++ b/src/manifold/src/edge_op.cpp @@ -223,9 +223,11 @@ void Manifold::Impl::SimplifyTopology() { for_each_n(policy, countAt(0), nbEdges, [=] __host__ __device__(int i) { bflagsPtr[i] = se(i); }); std::vector visited(halfedge_.size(), -1); + int tag = 0; for (int i = 0; i < nbEdges; ++i) { if (bflags[i]) { - RecursiveEdgeSwap(i, visited); + tag++; + RecursiveEdgeSwap(i, visited, tag); numFlagged++; } } @@ -485,14 +487,15 @@ void Manifold::Impl::CollapseEdge(const int edge) { } void Manifold::Impl::RecursiveEdgeSwap(const int edge, - std::vector& visited) { + std::vector& visited, int& tag) { VecDH& triRef = meshRelation_.triRef; if (edge < 0) return; const int pair = halfedge_[edge].pairedHalfedge; if (pair < 0) return; - if (visited[edge] == pair) return; - visited[edge] = pair; + + // avoid infinite recursion + if (visited[edge] == tag && visited[pair] == tag) return; const glm::ivec3 tri0edge = TriOf(edge); const glm::ivec3 tri1edge = TriOf(pair); @@ -572,12 +575,15 @@ void Manifold::Impl::RecursiveEdgeSwap(const int edge, SwapEdge(); const glm::vec2 e23 = v[3] - v[2]; if (glm::dot(e23, e23) < precision_ * precision_) { + tag++; CollapseEdge(tri0edge[2]); } else { - RecursiveEdgeSwap(tri0edge[0], visited); - RecursiveEdgeSwap(tri0edge[1], visited); - RecursiveEdgeSwap(tri1edge[0], visited); - RecursiveEdgeSwap(tri1edge[1], visited); + visited[edge] = tag; + visited[pair] = tag; + RecursiveEdgeSwap(tri0edge[0], visited, tag); + RecursiveEdgeSwap(tri0edge[1], visited, tag); + RecursiveEdgeSwap(tri1edge[0], visited, tag); + RecursiveEdgeSwap(tri1edge[1], visited, tag); } return; } else if (CCW(v[0], v[3], v[2], precision_) <= 0 || @@ -586,8 +592,10 @@ void Manifold::Impl::RecursiveEdgeSwap(const int edge, } // Normal path SwapEdge(); - RecursiveEdgeSwap(halfedge_[tri0edge[1]].pairedHalfedge, visited); - RecursiveEdgeSwap(halfedge_[tri1edge[0]].pairedHalfedge, visited); + visited[edge] = tag; + visited[pair] = tag; + RecursiveEdgeSwap(halfedge_[tri0edge[1]].pairedHalfedge, visited, tag); + RecursiveEdgeSwap(halfedge_[tri1edge[0]].pairedHalfedge, visited, tag); } void Manifold::Impl::SplitPinchedVerts() { diff --git a/src/manifold/src/impl.h b/src/manifold/src/impl.h index d9a2bbda0..dc4f57b5a 100644 --- a/src/manifold/src/impl.h +++ b/src/manifold/src/impl.h @@ -121,7 +121,7 @@ struct Manifold::Impl { void SimplifyTopology(); void DedupeEdge(int edge); void CollapseEdge(int edge); - void RecursiveEdgeSwap(int edge, std::vector& visited); + void RecursiveEdgeSwap(int edge, std::vector& visited, int& tag); void RemoveIfFolded(int edge); void PairUp(int edge0, int edge1); void UpdateVert(int vert, int startEdge, int endEdge); diff --git a/test/models/self_intersectA.glb b/test/models/self_intersectA.glb new file mode 100644 index 000000000..c05a3d6ab Binary files /dev/null and b/test/models/self_intersectA.glb differ diff --git a/test/models/self_intersectB.glb b/test/models/self_intersectB.glb new file mode 100644 index 000000000..4e724fe6f Binary files /dev/null and b/test/models/self_intersectB.glb differ diff --git a/test/samples_test.cpp b/test/samples_test.cpp index 05c8ce88a..21859efa4 100644 --- a/test/samples_test.cpp +++ b/test/samples_test.cpp @@ -255,3 +255,16 @@ TEST(Samples, Sponge4) { #endif } #endif + +#ifdef MANIFOLD_EXPORT +TEST(Samples, SelfIntersect) { + manifold::PolygonParams().processOverlaps = true; + std::string file = __FILE__; + std::string dir = file.substr(0, file.rfind('/')); + Manifold m1 = ImportMesh(dir + "/models/self_intersectA.glb"); + Manifold m2 = ImportMesh(dir + "/models/self_intersectB.glb"); + Manifold res = m1 + m2; + res.GetMeshGL(); // test crash + manifold::PolygonParams().processOverlaps = false; +} +#endif