/// <summary> /// Removes the edge eDel. There are several cases: /// if (eDel->Lface != eDel->Rface), we join two loops into one; the loop /// eDel->Lface is deleted. Otherwise, we are splitting one loop into two; /// the newly created loop will contain eDel->Dst. If the deletion of eDel /// would create isolated vertices, those are deleted as well. /// </summary> public void Delete(MeshUtils.Edge eDel) { var eDelSym = eDel._Sym; // First step: disconnect the origin vertex eDel->Org. We make all // changes to get a consistent mesh in this "intermediate" state. bool joiningLoops = false; if (eDel._Lface != eDel._Rface) { // We are joining two loops into one -- remove the left face joiningLoops = true; MeshUtils.KillFace(eDel._Lface, eDel._Rface); } if (eDel._Onext == eDel) { MeshUtils.KillVertex(eDel._Org, null); } else { // Make sure that eDel->Org and eDel->Rface point to valid half-edges eDel._Rface._anEdge = eDel._Oprev; eDel._Org._anEdge = eDel._Onext; MeshUtils.Splice(eDel, eDel._Oprev); if (!joiningLoops) { // We are splitting one loop into two -- create a new loop for eDel. MeshUtils.MakeFace(new MeshUtils.Face(), eDel, eDel._Lface); } } // Claim: the mesh is now in a consistent state, except that eDel->Org // may have been deleted. Now we disconnect eDel->Dst. if (eDelSym._Onext == eDelSym) { MeshUtils.KillVertex(eDelSym._Org, null); MeshUtils.KillFace(eDelSym._Lface, null); } else { // Make sure that eDel->Dst and eDel->Lface point to valid half-edges eDel._Lface._anEdge = eDelSym._Oprev; eDelSym._Org._anEdge = eDelSym._Onext; MeshUtils.Splice(eDelSym, eDelSym._Oprev); } // Any isolated vertices or faces have already been freed. MeshUtils.KillEdge(eDel); }
/// <summary> /// Destroys a face and removes it from the global face list. All edges of /// fZap will have a NULL pointer as their left face. Any edges which /// also have a NULL pointer as their right face are deleted entirely /// (along with any isolated vertices this produces). /// An entire mesh can be deleted by zapping its faces, one at a time, /// in any order. Zapped faces cannot be used in further mesh operations! /// </summary> public void ZapFace(MeshUtils.Face fZap) { var eStart = fZap._anEdge; // walk around face, deleting edges whose right face is also NULL var eNext = eStart._Lnext; MeshUtils.Edge e, eSym; do { e = eNext; eNext = e._Lnext; e._Lface = null; if (e._Rface == null) { // delete the edge -- see TESSmeshDelete above if (e._Onext == e) { MeshUtils.KillVertex(e._Org, null); } else { // Make sure that e._Org points to a valid half-edge e._Org._anEdge = e._Onext; MeshUtils.Splice(e, e._Oprev); } eSym = e._Sym; if (eSym._Onext == eSym) { MeshUtils.KillVertex(eSym._Org, null); } else { // Make sure that eSym._Org points to a valid half-edge eSym._Org._anEdge = eSym._Onext; MeshUtils.Splice(eSym, eSym._Oprev); } MeshUtils.KillEdge(e); } } while (e != eStart); /* delete from circular doubly-linked list */ var fPrev = fZap._prev; var fNext = fZap._next; fNext._prev = fPrev; fPrev._next = fNext; }