/* __gl_meshDelete( eDel ) 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. * * This function could be implemented as two calls to __gl_meshSplice * plus a few calls to memFree, but this would allocate and delete * unnecessary vertices and faces. */ int __gl_meshDelete(GLUhalfEdge* eDel) { GLUhalfEdge* eDelSym=eDel->Sym; int joiningLoops=FALSE; /* First step: disconnect the origin vertex eDel->Org. We make all * changes to get a consistent mesh in this "intermediate" state. */ if (eDel->Lface!=eDel->Rface) { /* We are joining two loops into one -- remove the left face */ joiningLoops=TRUE; KillFace(eDel->Lface, eDel->Rface); } if (eDel->Onext==eDel) { 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; Splice(eDel, eDel->Oprev); if (!joiningLoops) { GLUface* newFace=allocFace(); if (newFace==NULL) { return 0; } /* We are splitting one loop into two -- create a new loop for eDel. */ MakeFace(newFace, 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) { KillVertex(eDelSym->Org, NULL); 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; Splice(eDelSym, eDelSym->Oprev); } /* Any isolated vertices or faces have already been freed. */ KillEdge(eDel); return 1; }
/* tessMeshDelete (eDel) 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. * * This function could be implemented as two calls to tessMeshSplice * plus a few calls to memFree, but this would allocate and delete * unnecessary vertices and faces. */ int tessMeshDelete (TMesh *mesh, THalfEdge *eDel) { THalfEdge *eDelSym = eDel->Sym; int joiningLoops = false; /* First step: disconnect the origin vertex eDel->Org. We make all * changes to get a consistent mesh in this "intermediate" state. */ if (eDel->Lface != eDel->Rface) { /* We are joining two loops into one -- remove the left face */ joiningLoops = true; KillFace (mesh, eDel->Lface, eDel->Rface) ; } if (eDel->Onext == eDel) { KillVertex (mesh, eDel->pOrigin, NULL) ; } else { /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ eDel->Rface->pHalfEdge = eDel->Oprev; eDel->pOrigin->pHalfEdge = eDel->Onext; Splice (eDel, eDel->Oprev) ; if (! joiningLoops) { TFace *newFace= (TFace*)BucketAlloc (mesh->pFaceBucket) ; if (newFace == NULL) return 0; /* We are splitting one loop into two -- create a new loop for eDel. */ MakeFace (newFace, 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) { KillVertex (mesh, eDelSym->pOrigin, NULL) ; KillFace (mesh, eDelSym->Lface, NULL) ; } else { /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ eDel->Lface->pHalfEdge = eDelSym->Oprev; eDelSym->pOrigin->pHalfEdge = eDelSym->Onext; Splice (eDelSym, eDelSym->Oprev) ; } /* Any isolated vertices or faces have already been freed. */ KillEdge (mesh, eDel) ; return 1; }
/* __gl_meshZapFace(fZap) 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! */ void __gl_meshZapFace(GLUface* fZap) { GLUhalfEdge* eStart=fZap->anEdge; GLUhalfEdge* e, *eNext, *eSym; GLUface* fPrev, *fNext; /* walk around face, deleting edges whose right face is also NULL */ eNext=eStart->Lnext; do { e=eNext; eNext=e->Lnext; e->Lface=NULL; if (e->Rface==NULL) { /* delete the edge -- see __gl_MeshDelete above */ if (e->Onext==e) { KillVertex(e->Org, NULL); } else { /* Make sure that e->Org points to a valid half-edge */ e->Org->anEdge=e->Onext; Splice(e, e->Oprev); } eSym=e->Sym; if (eSym->Onext==eSym) { KillVertex(eSym->Org, NULL); } else { /* Make sure that eSym->Org points to a valid half-edge */ eSym->Org->anEdge=eSym->Onext; Splice(eSym, eSym->Oprev); } KillEdge(e); } } while(e!=eStart); /* delete from circular doubly-linked list */ fPrev=fZap->prev; fNext=fZap->next; fNext->prev=fPrev; fPrev->next=fNext; memFree(fZap); }
/* tessMeshZapFace (fZap) 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! */ void tessMeshZapFace (TMesh *mesh, TFace *fZap) { THalfEdge *eStart = fZap->pHalfEdge; THalfEdge *e, *eNext, *eSym; TFace *fPrev, *fNext; /* walk around face, deleting edges whose right face is also NULL */ eNext = eStart->Lnext; do { e = eNext; eNext = e->Lnext; e->Lface = NULL; if (e->Rface == NULL) { /* delete the edge -- see TESSmeshDelete above */ if (e->Onext == e) { KillVertex (mesh, e->pOrigin, NULL) ; } else { /* Make sure that e->Org points to a valid half-edge */ e->pOrigin->pHalfEdge = e->Onext; Splice (e, e->Oprev) ; } eSym = e->Sym; if (eSym->Onext == eSym) { KillVertex (mesh, eSym->pOrigin, NULL) ; } else { /* Make sure that eSym->Org points to a valid half-edge */ eSym->pOrigin->pHalfEdge = eSym->Onext; Splice (eSym, eSym->Oprev) ; } KillEdge (mesh, e) ; } } while (e != eStart) ; /* delete from circular doubly-linked list */ fPrev = fZap->pPrev; fNext = fZap->pNext; fNext->pPrev = fPrev; fPrev->pNext = fNext; BucketFree (mesh->pFaceBucket, fZap) ; }