Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/glutess/mesh is written in an unsupported language. File is not indexed.

0001 // see license file for original license.
0002 
0003 #ifndef tools_glutess_mesh
0004 #define tools_glutess_mesh
0005 
0006 #include "_glu"
0007 
0008 typedef struct GLUmesh GLUmesh; 
0009 
0010 typedef struct GLUvertex GLUvertex;
0011 typedef struct GLUface GLUface;
0012 typedef struct GLUhalfEdge GLUhalfEdge;
0013 
0014 typedef struct ActiveRegion ActiveRegion;       /* Internal data */
0015 
0016 /* The mesh structure is similar in spirit, notation, and operations
0017  * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
0018  * for the manipulation of general subdivisions and the computation of
0019  * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
0020  * For a simplified description, see the course notes for CS348a,
0021  * "Mathematical Foundations of Computer Graphics", available at the
0022  * Stanford bookstore (and taught during the fall quarter).
0023  * The implementation also borrows a tiny subset of the graph-based approach
0024  * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
0025  * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
0026  *
0027  * The fundamental data structure is the "half-edge".  Two half-edges
0028  * go together to make an edge, but they point in opposite directions.
0029  * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
0030  * its origin vertex (Org), the face on its left side (Lface), and the
0031  * adjacent half-edges in the CCW direction around the origin vertex
0032  * (Onext) and around the left face (Lnext).  There is also a "next"
0033  * pointer for the global edge list (see below).
0034  *
0035  * The notation used for mesh navigation:
0036  *      Sym   = the mate of a half-edge (same edge, but opposite direction)
0037  *      Onext = edge CCW around origin vertex (keep same origin)
0038  *      Dnext = edge CCW around destination vertex (keep same dest)
0039  *      Lnext = edge CCW around left face (dest becomes new origin)
0040  *      Rnext = edge CCW around right face (origin becomes new dest)
0041  *
0042  * "prev" means to substitute CW for CCW in the definitions above.
0043  *
0044  * The mesh keeps global lists of all vertices, faces, and edges,
0045  * stored as doubly-linked circular lists with a dummy header node.
0046  * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
0047  *
0048  * The circular edge list is special; since half-edges always occur
0049  * in pairs (e and e->Sym), each half-edge stores a pointer in only
0050  * one direction.  Starting at eHead and following the e->next pointers
0051  * will visit each *edge* once (ie. e or e->Sym, but not both).
0052  * e->Sym stores a pointer in the opposite direction, thus it is
0053  * always true that e->Sym->next->Sym->next == e.
0054  *
0055  * Each vertex has a pointer to next and previous vertices in the
0056  * circular list, and a pointer to a half-edge with this vertex as
0057  * the origin (NULL if this is the dummy header).  There is also a
0058  * field "data" for client data.
0059  *
0060  * Each face has a pointer to the next and previous faces in the
0061  * circular list, and a pointer to a half-edge with this face as
0062  * the left face (NULL if this is the dummy header).  There is also
0063  * a field "data" for client data.
0064  *
0065  * Note that what we call a "face" is really a loop; faces may consist
0066  * of more than one loop (ie. not simply connected), but there is no
0067  * record of this in the data structure.  The mesh may consist of
0068  * several disconnected regions, so it may not be possible to visit
0069  * the entire mesh by starting at a half-edge and traversing the edge
0070  * structure.
0071  *
0072  * The mesh does NOT support isolated vertices; a vertex is deleted along
0073  * with its last edge.  Similarly when two faces are merged, one of the
0074  * faces is deleted (see __gl_meshDelete below).  For mesh operations,
0075  * all face (loop) and vertex pointers must not be NULL.  However, once
0076  * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
0077  * faces of the mesh, one at a time.  All external faces can be "zapped"
0078  * before the mesh is returned to the client; then a NULL face indicates
0079  * a region which is not part of the output polygon.
0080  */
0081 
0082 struct GLUvertex {
0083   GLUvertex     *next;          /* next vertex (never NULL) */
0084   GLUvertex     *prev;          /* previous vertex (never NULL) */
0085   GLUhalfEdge   *anEdge;        /* a half-edge with this origin */
0086   void          *data;          /* client's data */
0087 
0088   /* Internal data (keep hidden) */
0089   GLUdouble     coords[3];      /* vertex location in 3D */
0090   GLUdouble     s, t;           /* projection onto the sweep plane */
0091   long          pqHandle;       /* to allow deletion from priority queue */
0092 };
0093 
0094 struct GLUface {
0095   GLUface       *next;          /* next face (never NULL) */
0096   GLUface       *prev;          /* previous face (never NULL) */
0097   GLUhalfEdge   *anEdge;        /* a half edge with this left face */
0098   void          *data;          /* room for client's data */
0099 
0100   /* Internal data (keep hidden) */
0101   GLUface       *trail;         /* "stack" for conversion to strips */
0102   GLUboolean    marked;         /* flag for conversion to strips */
0103   GLUboolean    inside;         /* this face is in the polygon interior */
0104 };
0105 
0106 struct GLUhalfEdge {
0107   GLUhalfEdge   *next;          /* doubly-linked list (prev==Sym->next) */
0108   GLUhalfEdge   *Sym;           /* same edge, opposite direction */
0109   GLUhalfEdge   *Onext;         /* next edge CCW around origin */
0110   GLUhalfEdge   *Lnext;         /* next edge CCW around left face */
0111   GLUvertex     *Org;           /* origin vertex (Overtex too long) */
0112   GLUface       *Lface;         /* left face */
0113 
0114   /* Internal data (keep hidden) */
0115   ActiveRegion  *activeRegion;  /* a region with this upper edge (sweep.c) */
0116   int           winding;        /* change in winding number when crossing
0117                                    from the right face to the left face */
0118 };
0119 
0120 #define Rface   Sym->Lface
0121 #define Dst     Sym->Org
0122 
0123 #define Oprev   Sym->Lnext
0124 #define Lprev   Onext->Sym
0125 #define Dprev   Lnext->Sym
0126 #define Rprev   Sym->Onext
0127 #define Dnext   Rprev->Sym      /* 3 pointers */
0128 #define Rnext   Oprev->Sym      /* 3 pointers */
0129 
0130 
0131 struct GLUmesh {
0132   GLUvertex     vHead;          /* dummy header for vertex list */
0133   GLUface       fHead;          /* dummy header for face list */
0134   GLUhalfEdge   eHead;          /* dummy header for edge list */
0135   GLUhalfEdge   eHeadSym;       /* and its symmetric counterpart */
0136 };
0137 
0138 /* The mesh operations below have three motivations: completeness,
0139  * convenience, and efficiency.  The basic mesh operations are MakeEdge,
0140  * Splice, and Delete.  All the other edge operations can be implemented
0141  * in terms of these.  The other operations are provided for convenience
0142  * and/or efficiency.
0143  *
0144  * When a face is split or a vertex is added, they are inserted into the
0145  * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
0146  * This makes it easier to process all vertices or faces in the global lists
0147  * without worrying about processing the same data twice.  As a convenience,
0148  * when a face is split, the "inside" flag is copied from the old face.
0149  * Other internal data (v->data, v->activeRegion, f->data, f->marked,
0150  * f->trail, e->winding) is set to zero.
0151  *
0152  * ********************** Basic Edge Operations **************************
0153  *
0154  * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
0155  * The loop (face) consists of the two new half-edges.
0156  *
0157  * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
0158  * mesh connectivity and topology.  It changes the mesh so that
0159  *      eOrg->Onext <- OLD( eDst->Onext )
0160  *      eDst->Onext <- OLD( eOrg->Onext )
0161  * where OLD(...) means the value before the meshSplice operation.
0162  *
0163  * This can have two effects on the vertex structure:
0164  *  - if eOrg->Org != eDst->Org, the two vertices are merged together
0165  *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
0166  * In both cases, eDst->Org is changed and eOrg->Org is untouched.
0167  *
0168  * Similarly (and independently) for the face structure,
0169  *  - if eOrg->Lface == eDst->Lface, one loop is split into two
0170  *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
0171  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
0172  *
0173  * __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
0174  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
0175  * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
0176  * the newly created loop will contain eDel->Dst.  If the deletion of eDel
0177  * would create isolated vertices, those are deleted as well.
0178  *
0179  * ********************** Other Edge Operations **************************
0180  *
0181  * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
0182  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
0183  * eOrg and eNew will have the same left face.
0184  *
0185  * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
0186  * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org.
0187  * eOrg and eNew will have the same left face.
0188  *
0189  * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
0190  * to eDst->Org, and returns the corresponding half-edge eNew.
0191  * If eOrg->Lface == eDst->Lface, this splits one loop into two,
0192  * and the newly created loop is eNew->Lface.  Otherwise, two disjoint
0193  * loops are merged into one, and the loop eDst->Lface is destroyed.
0194  *
0195  * ************************ Other Operations *****************************
0196  *
0197  * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
0198  * and no loops (what we usually call a "face").
0199  *
0200  * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
0201  * both meshes, and returns the new mesh (the old meshes are destroyed).
0202  *
0203  * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
0204  *
0205  * __gl_meshZapFace( fZap ) destroys a face and removes it from the
0206  * global face list.  All edges of fZap will have a NULL pointer as their
0207  * left face.  Any edges which also have a NULL pointer as their right face
0208  * are deleted entirely (along with any isolated vertices this produces).
0209  * An entire mesh can be deleted by zapping its faces, one at a time,
0210  * in any order.  Zapped faces cannot be used in further mesh operations!
0211  *
0212  * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
0213  */
0214 
0215 ////////////////////////////////////////////////////////
0216 /// inlined C code : ///////////////////////////////////
0217 ////////////////////////////////////////////////////////
0218 
0219 //#include "gluos"
0220 #include <cstddef>
0221 #include <cassert>
0222 #include "memalloc"
0223 
0224 inline/*static*/ GLUvertex *static_allocVertex()
0225 {
0226    return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
0227 }
0228 
0229 inline/*static*/ GLUface *static_allocFace()
0230 {
0231    return (GLUface *)memAlloc( sizeof( GLUface ));
0232 }
0233 
0234 /************************ Utility Routines ************************/
0235 
0236 /* Allocate and free half-edges in pairs for efficiency.
0237  * The *only* place that should use this fact is allocation/free.
0238  */
0239 typedef struct { GLUhalfEdge e, eSym; } EdgePair;
0240 
0241 /* MakeEdge creates a new pair of half-edges which form their own loop.
0242  * No vertex or face structures are allocated, but these must be assigned
0243  * before the current edge operation is completed.
0244  */
0245 inline/*static*/ GLUhalfEdge *static_MakeEdge( GLUhalfEdge *eNext )
0246 {
0247   GLUhalfEdge *e;
0248   GLUhalfEdge *eSym;
0249   GLUhalfEdge *ePrev;
0250   EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
0251   if (pair == NULL) return NULL;
0252 
0253   e = &pair->e;
0254   eSym = &pair->eSym;
0255 
0256   /* Make sure eNext points to the first edge of the edge pair */
0257   if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
0258 
0259   /* Insert in circular doubly-linked list before eNext.
0260    * Note that the prev pointer is stored in Sym->next.
0261    */
0262   ePrev = eNext->Sym->next;
0263   eSym->next = ePrev;
0264   ePrev->Sym->next = e;
0265   e->next = eNext;
0266   eNext->Sym->next = eSym;
0267 
0268   e->Sym = eSym;
0269   e->Onext = e;
0270   e->Lnext = eSym;
0271   e->Org = NULL;
0272   e->Lface = NULL;
0273   e->winding = 0;
0274   e->activeRegion = NULL;
0275 
0276   eSym->Sym = e;
0277   eSym->Onext = eSym;
0278   eSym->Lnext = e;
0279   eSym->Org = NULL;
0280   eSym->Lface = NULL;
0281   eSym->winding = 0;
0282   eSym->activeRegion = NULL;
0283 
0284   return e;
0285 }
0286 
0287 /* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
0288  * CS348a notes (see mesh.h).  Basically it modifies the mesh so that
0289  * a->Onext and b->Onext are exchanged.  This can have various effects
0290  * depending on whether a and b belong to different face or vertex rings.
0291  * For more explanation see __gl_meshSplice() below.
0292  */
0293 inline/*static*/ void static_Splice( GLUhalfEdge *a, GLUhalfEdge *b )
0294 {
0295   GLUhalfEdge *aOnext = a->Onext;
0296   GLUhalfEdge *bOnext = b->Onext;
0297 
0298   aOnext->Sym->Lnext = b;
0299   bOnext->Sym->Lnext = a;
0300   a->Onext = bOnext;
0301   b->Onext = aOnext;
0302 }
0303 
0304 /* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
0305  * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
0306  * a place to insert the new vertex in the global vertex list.  We insert
0307  * the new vertex *before* vNext so that algorithms which walk the vertex
0308  * list will not see the newly created vertices.
0309  */
0310 inline/*static*/ void static_MakeVertex( GLUvertex *newVertex, 
0311                         GLUhalfEdge *eOrig, GLUvertex *vNext )
0312 {
0313   GLUhalfEdge *e;
0314   GLUvertex *vPrev;
0315   GLUvertex *vNew = newVertex;
0316 
0317   assert(vNew != NULL);
0318 
0319   /* insert in circular doubly-linked list before vNext */
0320   vPrev = vNext->prev;
0321   vNew->prev = vPrev;
0322   vPrev->next = vNew;
0323   vNew->next = vNext;
0324   vNext->prev = vNew;
0325 
0326   vNew->anEdge = eOrig;
0327   vNew->data = NULL;
0328   /* leave coords, s, t undefined */
0329 
0330   /* fix other edges on this vertex loop */
0331   e = eOrig;
0332   do {
0333     e->Org = vNew;
0334     e = e->Onext;
0335   } while( e != eOrig );
0336 }
0337 
0338 /* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
0339  * face of all edges in the face loop to which eOrig belongs.  "fNext" gives
0340  * a place to insert the new face in the global face list.  We insert
0341  * the new face *before* fNext so that algorithms which walk the face
0342  * list will not see the newly created faces.
0343  */
0344 inline/*static*/ void static_MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
0345 {
0346   GLUhalfEdge *e;
0347   GLUface *fPrev;
0348   GLUface *fNew = newFace;
0349 
0350   assert(fNew != NULL); 
0351 
0352   /* insert in circular doubly-linked list before fNext */
0353   fPrev = fNext->prev;
0354   fNew->prev = fPrev;
0355   fPrev->next = fNew;
0356   fNew->next = fNext;
0357   fNext->prev = fNew;
0358 
0359   fNew->anEdge = eOrig;
0360   fNew->data = NULL;
0361   fNew->trail = NULL;
0362   fNew->marked = TOOLS_GLU_FALSE;
0363 
0364   /* The new face is marked "inside" if the old one was.  This is a
0365    * convenience for the common case where a face has been split in two.
0366    */
0367   fNew->inside = fNext->inside;
0368 
0369   /* fix other edges on this face loop */
0370   e = eOrig;
0371   do {
0372     e->Lface = fNew;
0373     e = e->Lnext;
0374   } while( e != eOrig );
0375 }
0376 
0377 /* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
0378  * and removes from the global edge list.
0379  */
0380 inline/*static*/ void static_KillEdge( GLUhalfEdge *eDel )
0381 {
0382   GLUhalfEdge *ePrev, *eNext;
0383 
0384   /* Half-edges are allocated in pairs, see EdgePair above */
0385   if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
0386 
0387   /* delete from circular doubly-linked list */
0388   eNext = eDel->next;
0389   ePrev = eDel->Sym->next;
0390   eNext->Sym->next = ePrev;
0391   ePrev->Sym->next = eNext;
0392 
0393   memFree( eDel );
0394 }
0395 
0396 
0397 /* KillVertex( vDel ) destroys a vertex and removes it from the global
0398  * vertex list.  It updates the vertex loop to point to a given new vertex.
0399  */
0400 inline/*static*/ void static_KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
0401 {
0402   GLUhalfEdge *e, *eStart = vDel->anEdge;
0403   GLUvertex *vPrev, *vNext;
0404 
0405   /* change the origin of all affected edges */
0406   e = eStart;
0407   do {
0408     e->Org = newOrg;
0409     e = e->Onext;
0410   } while( e != eStart );
0411 
0412   /* delete from circular doubly-linked list */
0413   vPrev = vDel->prev;
0414   vNext = vDel->next;
0415   vNext->prev = vPrev;
0416   vPrev->next = vNext;
0417 
0418   memFree( vDel );
0419 }
0420 
0421 /* KillFace( fDel ) destroys a face and removes it from the global face
0422  * list.  It updates the face loop to point to a given new face.
0423  */
0424 inline/*static*/ void static_KillFace( GLUface *fDel, GLUface *newLface )
0425 {
0426   GLUhalfEdge *e, *eStart = fDel->anEdge;
0427   GLUface *fPrev, *fNext;
0428 
0429   /* change the left face of all affected edges */
0430   e = eStart;
0431   do {
0432     e->Lface = newLface;
0433     e = e->Lnext;
0434   } while( e != eStart );
0435 
0436   /* delete from circular doubly-linked list */
0437   fPrev = fDel->prev;
0438   fNext = fDel->next;
0439   fNext->prev = fPrev;
0440   fPrev->next = fNext;
0441 
0442   memFree( fDel );
0443 }
0444 
0445 
0446 /****************** Basic Edge Operations **********************/
0447 
0448 /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
0449  * The loop consists of the two new half-edges.
0450  */
0451 inline GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
0452 {
0453   GLUvertex *newVertex1= static_allocVertex();
0454   GLUvertex *newVertex2= static_allocVertex();
0455   GLUface *newFace= static_allocFace();
0456   GLUhalfEdge *e;
0457 
0458   /* if any one is null then all get freed */
0459   if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
0460      if (newVertex1 != NULL) memFree(newVertex1);
0461      if (newVertex2 != NULL) memFree(newVertex2);
0462      if (newFace != NULL) memFree(newFace);     
0463      return NULL;
0464   } 
0465 
0466   e = static_MakeEdge( &mesh->eHead );
0467   if (e == NULL) {
0468      memFree(newVertex1);
0469      memFree(newVertex2);
0470      memFree(newFace);
0471      return NULL;
0472   }
0473 
0474   static_MakeVertex( newVertex1, e, &mesh->vHead );
0475   static_MakeVertex( newVertex2, e->Sym, &mesh->vHead );
0476   static_MakeFace( newFace, e, &mesh->fHead );
0477   return e;
0478 }
0479   
0480 
0481 /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
0482  * mesh connectivity and topology.  It changes the mesh so that
0483  *      eOrg->Onext <- OLD( eDst->Onext )
0484  *      eDst->Onext <- OLD( eOrg->Onext )
0485  * where OLD(...) means the value before the meshSplice operation.
0486  *
0487  * This can have two effects on the vertex structure:
0488  *  - if eOrg->Org != eDst->Org, the two vertices are merged together
0489  *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
0490  * In both cases, eDst->Org is changed and eOrg->Org is untouched.
0491  *
0492  * Similarly (and independently) for the face structure,
0493  *  - if eOrg->Lface == eDst->Lface, one loop is split into two
0494  *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
0495  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
0496  *
0497  * Some special cases:
0498  * If eDst == eOrg, the operation has no effect.
0499  * If eDst == eOrg->Lnext, the new face will have a single edge.
0500  * If eDst == eOrg->Lprev, the old face will have a single edge.
0501  * If eDst == eOrg->Onext, the new vertex will have a single edge.
0502  * If eDst == eOrg->Oprev, the old vertex will have a single edge.
0503  */
0504 inline int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
0505 {
0506   int joiningLoops = TOOLS_GLU_FALSE;
0507   int joiningVertices = TOOLS_GLU_FALSE;
0508 
0509   if( eOrg == eDst ) return 1;
0510 
0511   if( eDst->Org != eOrg->Org ) {
0512     /* We are merging two disjoint vertices -- destroy eDst->Org */
0513     joiningVertices = TOOLS_GLU_TRUE;
0514     static_KillVertex( eDst->Org, eOrg->Org );
0515   }
0516   if( eDst->Lface != eOrg->Lface ) {
0517     /* We are connecting two disjoint loops -- destroy eDst->Lface */
0518     joiningLoops = TOOLS_GLU_TRUE;
0519     static_KillFace( eDst->Lface, eOrg->Lface );
0520   }
0521 
0522   /* Change the edge structure */
0523   static_Splice( eDst, eOrg );
0524 
0525   if( ! joiningVertices ) {
0526     GLUvertex *newVertex= static_allocVertex();
0527     if (newVertex == NULL) return 0;
0528 
0529     /* We split one vertex into two -- the new vertex is eDst->Org.
0530      * Make sure the old vertex points to a valid half-edge.
0531      */
0532     static_MakeVertex( newVertex, eDst, eOrg->Org );
0533     eOrg->Org->anEdge = eOrg;
0534   }
0535   if( ! joiningLoops ) {
0536     GLUface *newFace= static_allocFace();  
0537     if (newFace == NULL) return 0;
0538 
0539     /* We split one loop into two -- the new loop is eDst->Lface.
0540      * Make sure the old face points to a valid half-edge.
0541      */
0542     static_MakeFace( newFace, eDst, eOrg->Lface );
0543     eOrg->Lface->anEdge = eOrg;
0544   }
0545 
0546   return 1;
0547 }
0548 
0549 
0550 /* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
0551  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
0552  * eDel->Lface is deleted.  Otherwise, we are splitting one loop into two;
0553  * the newly created loop will contain eDel->Dst.  If the deletion of eDel
0554  * would create isolated vertices, those are deleted as well.
0555  *
0556  * This function could be implemented as two calls to __gl_meshSplice
0557  * plus a few calls to memFree, but this would allocate and delete
0558  * unnecessary vertices and faces.
0559  */
0560 inline int __gl_meshDelete( GLUhalfEdge *eDel )
0561 {
0562   GLUhalfEdge *eDelSym = eDel->Sym;
0563   int joiningLoops = TOOLS_GLU_FALSE;
0564 
0565   /* First step: disconnect the origin vertex eDel->Org.  We make all
0566    * changes to get a consistent mesh in this "intermediate" state.
0567    */
0568   if( eDel->Lface != eDel->Rface ) {
0569     /* We are joining two loops into one -- remove the left face */
0570     joiningLoops = TOOLS_GLU_TRUE;
0571     static_KillFace( eDel->Lface, eDel->Rface );
0572     /* G.Barrand : note : Coverity says that there is a problem using eDel->Lface->anEdge in the below,
0573        but it appears that at the out of the upper static_KillFace() call (then here), eDel->Lface before
0574        (the pointer freeed) is not the same than after (then here). */
0575   }
0576 
0577   if( eDel->Onext == eDel ) {
0578     static_KillVertex( eDel->Org, NULL );
0579   } else {
0580     /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
0581     eDel->Rface->anEdge = eDel->Oprev;
0582     eDel->Org->anEdge = eDel->Onext;
0583 
0584     static_Splice( eDel, eDel->Oprev );
0585     if( ! joiningLoops ) {
0586       GLUface *newFace= static_allocFace();
0587       if (newFace == NULL) return 0; 
0588 
0589       /* We are splitting one loop into two -- create a new loop for eDel. */
0590       static_MakeFace( newFace, eDel, eDel->Lface );
0591     }
0592   }
0593 
0594   /* Claim: the mesh is now in a consistent state, except that eDel->Org
0595    * may have been deleted.  Now we disconnect eDel->Dst.
0596    */
0597   if( eDelSym->Onext == eDelSym ) {
0598     static_KillVertex( eDelSym->Org, NULL );
0599     static_KillFace( eDelSym->Lface, NULL );
0600   } else {
0601     /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
0602     eDel->Lface->anEdge = eDelSym->Oprev;
0603     eDelSym->Org->anEdge = eDelSym->Onext;
0604     static_Splice( eDelSym, eDelSym->Oprev );
0605   }
0606 
0607   /* Any isolated vertices or faces have already been freed. */
0608   static_KillEdge( eDel );
0609 
0610   return 1;
0611 }
0612 
0613 
0614 /******************** Other Edge Operations **********************/
0615 
0616 /* All these routines can be implemented with the basic edge
0617  * operations above.  They are provided for convenience and efficiency.
0618  */
0619 
0620 
0621 /* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
0622  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
0623  * eOrg and eNew will have the same left face.
0624  */
0625 inline GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
0626 {
0627   GLUhalfEdge *eNewSym;
0628   GLUhalfEdge *eNew = static_MakeEdge( eOrg );
0629   if (eNew == NULL) return NULL;
0630 
0631   eNewSym = eNew->Sym;
0632 
0633   /* Connect the new edge appropriately */
0634   static_Splice( eNew, eOrg->Lnext );
0635 
0636   /* Set the vertex and face information */
0637   eNew->Org = eOrg->Dst;
0638   {
0639     GLUvertex *newVertex= static_allocVertex();
0640     if (newVertex == NULL) return NULL;
0641 
0642     static_MakeVertex( newVertex, eNewSym, eNew->Org );
0643   }
0644   eNew->Lface = eNewSym->Lface = eOrg->Lface;
0645 
0646   return eNew;
0647 }
0648 
0649 
0650 /* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
0651  * such that eNew == eOrg->Lnext.  The new vertex is eOrg->Dst == eNew->Org.
0652  * eOrg and eNew will have the same left face.
0653  */
0654 inline GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
0655 {
0656   GLUhalfEdge *eNew;
0657   GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
0658   if (tempHalfEdge == NULL) return NULL;
0659 
0660   eNew = tempHalfEdge->Sym;
0661 
0662   /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
0663   static_Splice( eOrg->Sym, eOrg->Sym->Oprev );
0664   static_Splice( eOrg->Sym, eNew );
0665 
0666   /* Set the vertex and face information */
0667   eOrg->Dst = eNew->Org;
0668   eNew->Dst->anEdge = eNew->Sym;        /* may have pointed to eOrg->Sym */
0669   eNew->Rface = eOrg->Rface;
0670   eNew->winding = eOrg->winding;        /* copy old winding information */
0671   eNew->Sym->winding = eOrg->Sym->winding;
0672 
0673   return eNew;
0674 }
0675 
0676 
0677 /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
0678  * to eDst->Org, and returns the corresponding half-edge eNew.
0679  * If eOrg->Lface == eDst->Lface, this splits one loop into two,
0680  * and the newly created loop is eNew->Lface.  Otherwise, two disjoint
0681  * loops are merged into one, and the loop eDst->Lface is destroyed.
0682  *
0683  * If (eOrg == eDst), the new face will have only two edges.
0684  * If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
0685  * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
0686  */
0687 inline GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
0688 {
0689   GLUhalfEdge *eNewSym;
0690   int joiningLoops = TOOLS_GLU_FALSE;  
0691   GLUhalfEdge *eNew = static_MakeEdge( eOrg );
0692   if (eNew == NULL) return NULL;
0693 
0694   eNewSym = eNew->Sym;
0695 
0696   if( eDst->Lface != eOrg->Lface ) {
0697     /* We are connecting two disjoint loops -- destroy eDst->Lface */
0698     joiningLoops = TOOLS_GLU_TRUE;
0699     static_KillFace( eDst->Lface, eOrg->Lface );
0700   }
0701 
0702   /* Connect the new edge appropriately */
0703   static_Splice( eNew, eOrg->Lnext );
0704   static_Splice( eNewSym, eDst );
0705 
0706   /* Set the vertex and face information */
0707   eNew->Org = eOrg->Dst;
0708   eNewSym->Org = eDst->Org;
0709   eNew->Lface = eNewSym->Lface = eOrg->Lface;
0710 
0711   /* Make sure the old face points to a valid half-edge */
0712   eOrg->Lface->anEdge = eNewSym;
0713 
0714   if( ! joiningLoops ) {
0715     GLUface *newFace= static_allocFace();
0716     if (newFace == NULL) return NULL;
0717 
0718     /* We split one loop into two -- the new loop is eNew->Lface */
0719     static_MakeFace( newFace, eNew, eOrg->Lface );
0720   }
0721   return eNew;
0722 }
0723 
0724 
0725 /******************** Other Operations **********************/
0726 
0727 /* __gl_meshZapFace( fZap ) destroys a face and removes it from the
0728  * global face list.  All edges of fZap will have a NULL pointer as their
0729  * left face.  Any edges which also have a NULL pointer as their right face
0730  * are deleted entirely (along with any isolated vertices this produces).
0731  * An entire mesh can be deleted by zapping its faces, one at a time,
0732  * in any order.  Zapped faces cannot be used in further mesh operations!
0733  */
0734 inline void __gl_meshZapFace( GLUface *fZap )
0735 {
0736   GLUhalfEdge *eStart = fZap->anEdge;
0737   GLUhalfEdge *e, *eNext, *eSym;
0738   GLUface *fPrev, *fNext;
0739 
0740   /* walk around face, deleting edges whose right face is also NULL */
0741   eNext = eStart->Lnext;
0742   do {
0743     e = eNext;
0744     eNext = e->Lnext;
0745 
0746     e->Lface = NULL;
0747     if( e->Rface == NULL ) {
0748       /* delete the edge -- see __gl_MeshDelete above */
0749 
0750       if( e->Onext == e ) {
0751         static_KillVertex( e->Org, NULL );
0752       } else {
0753         /* Make sure that e->Org points to a valid half-edge */
0754         e->Org->anEdge = e->Onext;
0755         static_Splice( e, e->Oprev );
0756       }
0757       eSym = e->Sym;
0758       if( eSym->Onext == eSym ) {
0759         static_KillVertex( eSym->Org, NULL );
0760       } else {
0761         /* Make sure that eSym->Org points to a valid half-edge */
0762         eSym->Org->anEdge = eSym->Onext;
0763         static_Splice( eSym, eSym->Oprev );
0764       }
0765       static_KillEdge( e );
0766     }
0767   } while( e != eStart );
0768 
0769   /* delete from circular doubly-linked list */
0770   fPrev = fZap->prev;
0771   fNext = fZap->next;
0772   fNext->prev = fPrev;
0773   fPrev->next = fNext;
0774 
0775   memFree( fZap );
0776 }
0777 
0778 
0779 /* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
0780  * and no loops (what we usually call a "face").
0781  */
0782 inline GLUmesh *__gl_meshNewMesh( void )
0783 {
0784   GLUvertex *v;
0785   GLUface *f;
0786   GLUhalfEdge *e;
0787   GLUhalfEdge *eSym;
0788   GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
0789   if (mesh == NULL) {
0790      return NULL;
0791   }
0792   
0793   v = &mesh->vHead;
0794   f = &mesh->fHead;
0795   e = &mesh->eHead;
0796   eSym = &mesh->eHeadSym;
0797 
0798   v->next = v->prev = v;
0799   v->anEdge = NULL;
0800   v->data = NULL;
0801 
0802   f->next = f->prev = f;
0803   f->anEdge = NULL;
0804   f->data = NULL;
0805   f->trail = NULL;
0806   f->marked = TOOLS_GLU_FALSE;
0807   f->inside = TOOLS_GLU_FALSE;
0808 
0809   e->next = e;
0810   e->Sym = eSym;
0811   e->Onext = NULL;
0812   e->Lnext = NULL;
0813   e->Org = NULL;
0814   e->Lface = NULL;
0815   e->winding = 0;
0816   e->activeRegion = NULL;
0817 
0818   eSym->next = eSym;
0819   eSym->Sym = e;
0820   eSym->Onext = NULL;
0821   eSym->Lnext = NULL;
0822   eSym->Org = NULL;
0823   eSym->Lface = NULL;
0824   eSym->winding = 0;
0825   eSym->activeRegion = NULL;
0826 
0827   return mesh;
0828 }
0829 
0830 
0831 /* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
0832  * both meshes, and returns the new mesh (the old meshes are destroyed).
0833  */
0834 inline GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
0835 {
0836   GLUface *f1 = &mesh1->fHead;
0837   GLUvertex *v1 = &mesh1->vHead;
0838   GLUhalfEdge *e1 = &mesh1->eHead;
0839   GLUface *f2 = &mesh2->fHead;
0840   GLUvertex *v2 = &mesh2->vHead;
0841   GLUhalfEdge *e2 = &mesh2->eHead;
0842 
0843   /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
0844   if( f2->next != f2 ) {
0845     f1->prev->next = f2->next;
0846     f2->next->prev = f1->prev;
0847     f2->prev->next = f1;
0848     f1->prev = f2->prev;
0849   }
0850 
0851   if( v2->next != v2 ) {
0852     v1->prev->next = v2->next;
0853     v2->next->prev = v1->prev;
0854     v2->prev->next = v1;
0855     v1->prev = v2->prev;
0856   }
0857 
0858   if( e2->next != e2 ) {
0859     e1->Sym->next->Sym->next = e2->next;
0860     e2->next->Sym->next = e1->Sym->next;
0861     e2->Sym->next->Sym->next = e1;
0862     e1->Sym->next = e2->Sym->next;
0863   }
0864 
0865   memFree( mesh2 );
0866   return mesh1;
0867 }
0868 
0869 
0870 #ifdef DELETE_BY_ZAPPING
0871 
0872 /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
0873  */
0874 inline void __gl_meshDeleteMesh( GLUmesh *mesh )
0875 {
0876   GLUface *fHead = &mesh->fHead;
0877 
0878   while( fHead->next != fHead ) {
0879     __gl_meshZapFace( fHead->next );
0880   }
0881   assert( mesh->vHead.next == &mesh->vHead );
0882 
0883   memFree( mesh );
0884 }
0885 
0886 #else
0887 
0888 /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
0889  */
0890 inline void __gl_meshDeleteMesh( GLUmesh *mesh )
0891 {
0892   GLUface *f, *fNext;
0893   GLUvertex *v, *vNext;
0894   GLUhalfEdge *e, *eNext;
0895 
0896   for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
0897     fNext = f->next;
0898     memFree( f );
0899   }
0900 
0901   for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
0902     vNext = v->next;
0903     memFree( v );
0904   }
0905 
0906   for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
0907     /* One call frees both e and e->Sym (see EdgePair above) */
0908     eNext = e->next;
0909     memFree( e );
0910   }
0911 
0912   memFree( mesh );
0913 }
0914 
0915 #endif
0916 
0917 inline void __gl_meshCheckMesh( GLUmesh *mesh )
0918 {
0919   GLUface *fHead = &mesh->fHead;
0920   GLUvertex *vHead = &mesh->vHead;
0921   GLUhalfEdge *eHead = &mesh->eHead;
0922   GLUface *f, *fPrev;
0923   GLUvertex *v, *vPrev;
0924   GLUhalfEdge *e, *ePrev;
0925 
0926   fPrev = fHead;
0927   for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
0928     assert( f->prev == fPrev );
0929     e = f->anEdge;
0930     do {
0931       assert( e->Sym != e );
0932       assert( e->Sym->Sym == e );
0933       assert( e->Lnext->Onext->Sym == e );
0934       assert( e->Onext->Sym->Lnext == e );
0935       assert( e->Lface == f );
0936       e = e->Lnext;
0937     } while( e != f->anEdge );
0938   }
0939   assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
0940 
0941   vPrev = vHead;
0942   for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
0943     assert( v->prev == vPrev );
0944     e = v->anEdge;
0945     do {
0946       assert( e->Sym != e );
0947       assert( e->Sym->Sym == e );
0948       assert( e->Lnext->Onext->Sym == e );
0949       assert( e->Onext->Sym->Lnext == e );
0950       assert( e->Org == v );
0951       e = e->Onext;
0952     } while( e != v->anEdge );
0953   }
0954   assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
0955 
0956   ePrev = eHead;
0957   for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
0958     assert( e->Sym->next == ePrev->Sym );
0959     assert( e->Sym != e );
0960     assert( e->Sym->Sym == e );
0961     assert( e->Org != NULL );
0962     assert( e->Dst != NULL );
0963     assert( e->Lnext->Onext->Sym == e );
0964     assert( e->Onext->Sym->Lnext == e );
0965   }
0966   assert( e->Sym->next == ePrev->Sym
0967        && e->Sym == &mesh->eHeadSym
0968        && e->Sym->Sym == e
0969        && e->Org == NULL && e->Dst == NULL
0970        && e->Lface == NULL && e->Rface == NULL );
0971 }
0972 
0973 #endif