void splitSurface(Plane P) { List <HE_Vertex> newVertices = new List <HE_Vertex> (); List <HE_Face> newFaces = new List <HE_Face> (); List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> (); List <HE_Edge> newEdges = new List <HE_Edge> (); // get all split edges List <SplitEdge> splitEdges = retrieveSplitEdges(P); //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane. //compared to the first point float[] sides = new float[vertices.Count]; //bool cut=false; for (int i = 0; i < vertices.Count; i++) { HE_Vertex v = vertices [i]; sides [i] = P.side(v); //if(sides[0]*sides[i]<=0f) cut=true; } //loop through all faces. for (int i = 0; i < faces.Count; i++) { HE_Face face = faces [i]; HE_HalfEdge halfEdge = face.halfEdge; List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> (); List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> (); List <HE_Vertex> currentFace = newFaceVertices1; //for each face, loop through all vertices and retain the vertices on the correct side. If the edge //is cut, insert the new point in the appropriate place. do { currentFace.Add(halfEdge.vert); for (int j = 0; j < splitEdges.Count; j++) // loop through all split edges to check for the current edge. { SplitEdge se = (SplitEdge)splitEdges [j]; if (halfEdge.edge == se.edge) { newFaceVertices1.Add(se.splitVertex); newFaceVertices2.Add(se.splitVertex); if (currentFace == newFaceVertices1) { currentFace = newFaceVertices2; } else { currentFace = newFaceVertices1; } break; } } halfEdge = halfEdge.next; } while(halfEdge != face.halfEdge); //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices. //Add all face-related information to the data-structure. HE_Face newFace = new HE_Face(); newFaces.Add(newFace); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices1.Count; j++) { HE_Vertex v = newFaceVertices1 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); if (newFaceVertices2.Count > 0) { newFace = new HE_Face(); newFaces.Add(newFace); faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices2.Count; j++) { HE_Vertex v = newFaceVertices2 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); //}//test } //Add missing information to the datastructure pairHalfEdges(newHalfEdges); createEdges(newHalfEdges, newEdges); } // update the mesh vertices = newVertices; faces = newFaces; halfEdges = newHalfEdges; edges = newEdges; reindex(); }
// Split the mesh in half, retain the part on the same side as the point "center". // Works only on a convex mesh !!! public void cutMesh(Plane P, PVector center) { float centerside = P.side(center); if (centerside != 0) // if center is on the plane, we can't decide which part to keep, ignore. { List <HE_Vertex> newVertices = new List <HE_Vertex> (); List <HE_Face> newFaces = new List <HE_Face> (); List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> (); List <HE_Edge> newEdges = new List <HE_Edge> (); // get all split edges List <SplitEdge> splitEdges = retrieveSplitEdges(P); //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane. //compared to the first point float[] sides = new float[vertices.Count]; //bool cut = false;// add inok for (int i = 0; i < vertices.Count; i++) { HE_Vertex v = vertices [i]; sides [i] = P.side(v); //if(sides[0]*sides[i]<=0f) cut=true;// add inok } //loop through all faces. for (int i = 0; i < faces.Count; i++) { HE_Face face = faces [i]; HE_HalfEdge halfEdge = face.halfEdge; List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> (); // vertices on the correct side. List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> (); // vertices on the wrong side, not used right now. //for each face, loop through all vertices and retain the vertices on the correct side. If the edge //is cut, insert the new point in the appropriate place. do { if (sides [halfEdge.vert.id] * centerside >= 0f) { newFaceVertices1.Add(halfEdge.vert); } if (sides [halfEdge.vert.id] * centerside <= 0f) { newFaceVertices2.Add(halfEdge.vert); } for (int j = 0; j < splitEdges.Count; j++) // loop through all split edges to check for the current edge. { SplitEdge se = splitEdges [j]; if (halfEdge.edge == se.edge) { newFaceVertices1.Add(se.splitVertex); newFaceVertices2.Add(se.splitVertex); break; } } halfEdge = halfEdge.next; } while(halfEdge != face.halfEdge); //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices. //Add all face-related information to the data-structure. if (newFaceVertices1.Count > 2) { HE_Face newFace = new HE_Face(); newFaces.Add(newFace); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices1.Count; j++) { HE_Vertex v = newFaceVertices1 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); } } //Add missing information to the datastructure int n = newHalfEdges.Count; pairHalfEdges(newHalfEdges); createEdges(newHalfEdges, newEdges); //Cutting the mesh not only cuts the faces, it also creates one new planar face looping through all new cutpoints(in a convex mesh). //This hole in the mesh is identified by unpaired halfedges remaining after the pairibg operation. //This part needs to rethought to extend to concave meshes!!! List <HE_HalfEdge> unpairedEdges = new List <HE_HalfEdge> (); for (int i = 0; i < n; i++) { HE_HalfEdge he = newHalfEdges [i]; if (he.pair == null) { unpairedEdges.Add(he); } } if (unpairedEdges.Count > 0) { //Create a closed loop out of the collection of unpaired halfedges and associate a new face with this. //Easy to explain with a drawing, beyond my skill with words. HE_Face cutFace = new HE_Face(); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); HE_HalfEdge he = unpairedEdges [0]; HE_HalfEdge hen = he; do { HE_HalfEdge _hen = he.next; HE_HalfEdge _hep = he.next.pair; if (_hep != null) //add inok { hen = he.next.pair.next; while (!unpairedEdges.Contains(hen)) { hen = hen.pair.next; } } else { hen = hen.next; Debug.LogWarning("LogWarning: null"); } HE_HalfEdge newhe = new HE_HalfEdge(); faceEdges.Add(newhe); if (cutFace.halfEdge == null) { cutFace.halfEdge = newhe; } newhe.vert = hen.vert; newhe.pair = he; he.pair = newhe; HE_Edge e = new HE_Edge(); e.halfEdge = newhe; he.edge = e; newhe.edge = e; newEdges.Add(e); newhe.face = cutFace; he = hen; } while(hen != unpairedEdges[0]); cycleHalfEdges(faceEdges, true); newHalfEdges.AddRange(faceEdges); newFaces.Add(cutFace); } // update the mesh vertices = newVertices; faces = newFaces; halfEdges = newHalfEdges; edges = newEdges; reindex(); } }