meshmash / Plankton

A C# half-edge mesh data structure, and components for using this in Grasshopper/Rhino
http://meshmash.github.io/Plankton
GNU Lesser General Public License v3.0
216 stars 66 forks source link

InvalidOperationException in Halfedges.CollapseEdge #17

Closed indigo99 closed 10 years ago

indigo99 commented 10 years ago

Here is my test case:

PlanktonMesh mesh = new PlanktonMesh();

mesh.Vertices.Add(0, 0, 0);     // 0
mesh.Vertices.Add(100, 0, 0);   // 1
mesh.Vertices.Add(100, 100, 0); // 2
mesh.Vertices.Add(0, 100, 0);   // 3
mesh.Vertices.Add(50, 50, 0);   // 4

mesh.Faces.AddFace(1, 4, 0);
mesh.Faces.AddFace(new int[] {1, 2, 3, 0, 4});

mesh.Halfedges.CollapseEdge(0);

And the stack trace:

System.InvalidOperationException: Unset index, cannot continue.
   at Plankton.PlanktonHalfEdgeList.<GetFaceCirculator>d__5.MoveNext()
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
   at Plankton.PlanktonHalfEdgeList.CollapseEdge(Int32 index)
   at Script_Instance...

If I catch the exception and dump the state of the mesh, this is was I get:

Halfedges[0] startV:1 nextHE:2 face:0 
Halfedges[1] startV:1 nextHE:6 face:1 
Halfedges[2] *Unused* startV:-1 nextHE:-1 face:-1 
Halfedges[3] *Unused* startV:-1 nextHE:-1 face:-1 
Halfedges[4] startV:0 nextHE:6 face:1 
Halfedges[5] startV:1 nextHE:11 face:-1 
Halfedges[6] startV:1 nextHE:8 face:1 
Halfedges[7] startV:2 nextHE:5 face:-1 
Halfedges[8] startV:2 nextHE:10 face:1 
Halfedges[9] startV:3 nextHE:7 face:-1 
Halfedges[10] startV:3 nextHE:4 face:1 
Halfedges[11] startV:0 nextHE:9 face:-1 

Faces[0] *Unused* firstHE:-1
Faces[1] firstHE:6

I believe the Halfedges.CollapseEdge should just merge the two faces and leave me with a single face (0, 1, 2, 3). Is that right? Any idea what the issue is?

pearswj commented 10 years ago

Hi Gilles, thanks for raising this issue and for including so much useful information. There's definitely something funny going on...

I will add your test case to the project and will investigate what's causing the error.

indigo99 commented 10 years ago

Thanks looking at this issue! I played with it a little more and it seems the bug occurs when you try to collapse a edge that's part of a triangle, and that the edge and its NextHalfedge are both adjacent to the same face.

I was able to work around the issue by detecting when that situation occurs, and instead collapse the pair edge of the NextHalfedge. This accomplishes essentially the same thing and doesn't hit the bug since that edge will be part of a face with at least 4 sides.

Thanks, Gilles.

indigo99 commented 10 years ago

Will, I merged your fix #19 into the main branch and I'm not seeing any more issues. The other bugs you found are never triggered in my particular script. Thanks so much for your help!