/* __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; }
/* glu_fastuidraw_gl_meshMakeEdge creates one edge, two vertices, and a loop (face). * The loop consists of the two new half-edges. */ GLUhalfEdge *glu_fastuidraw_gl_meshMakeEdge( GLUmesh *mesh ) { GLUvertex *newVertex1= allocVertex(); GLUvertex *newVertex2= allocVertex(); GLUface *newFace= allocFace(); GLUhalfEdge *e; /* if any one is null then all get freed */ if (newVertex1 == nullptr || newVertex2 == nullptr || newFace == nullptr) { if (newVertex1 != nullptr) memFree(newVertex1); if (newVertex2 != nullptr) memFree(newVertex2); if (newFace != nullptr) memFree(newFace); return nullptr; } e = MakeEdge( &mesh->eHead ); if (e == nullptr) { memFree(newVertex1); memFree(newVertex2); memFree(newFace); return nullptr; } MakeVertex( newVertex1, e, &mesh->vHead ); MakeVertex( newVertex2, e->Sym, &mesh->vHead ); MakeFace( newFace, e, &mesh->fHead ); return e; }
/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the * mesh connectivity and topology. It changes the mesh so that * eOrg->Onext <- OLD(eDst->Onext) * eDst->Onext <- OLD(eOrg->Onext) * where OLD(...) means the value before the meshSplice operation. * * This can have two effects on the vertex structure: * - if eOrg->Org != eDst->Org, the two vertices are merged together * - if eOrg->Org == eDst->Org, the origin is split into two vertices * In both cases, eDst->Org is changed and eOrg->Org is untouched. * * Similarly (and independently) for the face structure, * - if eOrg->Lface == eDst->Lface, one loop is split into two * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. * * Some special cases: * If eDst == eOrg, the operation has no effect. * If eDst == eOrg->Lnext, the new face will have a single edge. * If eDst == eOrg->Lprev, the old face will have a single edge. * If eDst == eOrg->Onext, the new vertex will have a single edge. * If eDst == eOrg->Oprev, the old vertex will have a single edge. */ int __gl_meshSplice(GLUhalfEdge* eOrg, GLUhalfEdge* eDst) { int joiningLoops=FALSE; int joiningVertices=FALSE; if (eOrg==eDst) { return 1; } if (eDst->Org!=eOrg->Org) { /* We are merging two disjoint vertices -- destroy eDst->Org */ joiningVertices=TRUE; KillVertex(eDst->Org, eOrg->Org); } if (eDst->Lface!=eOrg->Lface) { /* We are connecting two disjoint loops -- destroy eDst->Lface */ joiningLoops=TRUE; KillFace(eDst->Lface, eOrg->Lface); } /* Change the edge structure */ Splice(eDst, eOrg); if (!joiningVertices) { GLUvertex* newVertex=allocVertex(); if (newVertex==NULL) { return 0; } /* We split one vertex into two -- the new vertex is eDst->Org. * Make sure the old vertex points to a valid half-edge. */ MakeVertex(newVertex, eDst, eOrg->Org); eOrg->Org->anEdge=eOrg; } if (!joiningLoops) { GLUface* newFace=allocFace(); if (newFace==NULL) { return 0; } /* We split one loop into two -- the new loop is eDst->Lface. * Make sure the old face points to a valid half-edge. */ MakeFace(newFace, eDst, eOrg->Lface); eOrg->Lface->anEdge=eOrg; } return 1; }
Triangle& Subdivision::makeFace(Edge *e) { Triangle *t = allocFace(e); first_face = t->linkTo(first_face); return *t; }
/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst * to eDst->Org, and returns the corresponding half-edge eNew. * If eOrg->Lface == eDst->Lface, this splits one loop into two, * and the newly created loop is eNew->Lface. Otherwise, two disjoint * loops are merged into one, and the loop eDst->Lface is destroyed. * * If (eOrg == eDst), the new face will have only two edges. * If (eOrg->Lnext == eDst), the old face is reduced to a single edge. * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. */ GLUhalfEdge* __gl_meshConnect(GLUhalfEdge* eOrg, GLUhalfEdge* eDst) { GLUhalfEdge* eNewSym; int joiningLoops=FALSE; GLUhalfEdge* eNew=MakeEdge(eOrg); if (eNew==NULL) { return NULL; } eNewSym=eNew->Sym; if (eDst->Lface!=eOrg->Lface) { /* We are connecting two disjoint loops -- destroy eDst->Lface */ joiningLoops=TRUE; KillFace(eDst->Lface, eOrg->Lface); } /* Connect the new edge appropriately */ Splice(eNew, eOrg->Lnext); Splice(eNewSym, eDst); /* Set the vertex and face information */ eNew->Org=eOrg->Dst; eNewSym->Org=eDst->Org; eNew->Lface=eNewSym->Lface=eOrg->Lface; /* Make sure the old face points to a valid half-edge */ eOrg->Lface->anEdge=eNewSym; if (!joiningLoops) { GLUface* newFace=allocFace(); if (newFace==NULL) { return NULL; } /* We split one loop into two -- the new loop is eNew->Lface */ MakeFace(newFace, eNew, eOrg->Lface); } return eNew; }
/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). * The loop consists of the two new half-edges. */ GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh ) { GLUvertex *newVertex1= allocVertex(); GLUvertex *newVertex2= allocVertex(); GLUface *newFace= allocFace(); GLUhalfEdge *e; /* if any one is null then all get freed */ if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { if (newVertex1 != NULL) memFree(newVertex1); if (newVertex2 != NULL) memFree(newVertex2); if (newFace != NULL) memFree(newFace); return NULL; } e = MakeEdge( &mesh->eHead ); if (e == NULL) return NULL; MakeVertex( newVertex1, e, &mesh->vHead ); MakeVertex( newVertex2, e->Sym, &mesh->vHead ); MakeFace( newFace, e, &mesh->fHead ); return e; }