Stellarium  0.90.0
mesh.h
1 /*
2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice including the dates of first publication and
13  * either this permission notice or a reference to
14  * http://oss.sgi.com/projects/FreeB/
15  * shall be included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26  * shall not be used in advertising or otherwise to promote the sale, use or
27  * other dealings in this Software without prior written authorization from
28  * Silicon Graphics, Inc.
29  */
30 /*
31 ** Author: Eric Veach, July 1994.
32 **
33 */
34 
35 #ifndef __mesh_h_
36 #define __mesh_h_
37 
38 #include "glues.h"
39 
40 typedef struct GLUESmesh GLUESmesh;
41 
42 typedef struct GLUESvertex GLUESvertex;
43 typedef struct GLUESface GLUESface;
44 typedef struct GLUEShalfEdge GLUEShalfEdge;
45 
46 typedef struct ActiveRegion ActiveRegion; /* Internal data */
47 
48 /* The mesh structure is similar in spirit, notation, and operations
49  * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
50  * for the manipulation of general subdivisions and the computation of
51  * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
52  * For a simplified description, see the course notes for CS348a,
53  * "Mathematical Foundations of Computer Graphics", available at the
54  * Stanford bookstore (and taught during the fall quarter).
55  * The implementation also borrows a tiny subset of the graph-based approach
56  * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
57  * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
58  *
59  * The fundamental data structure is the "half-edge". Two half-edges
60  * go together to make an edge, but they point in opposite directions.
61  * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
62  * its origin vertex (Org), the face on its left side (Lface), and the
63  * adjacent half-edges in the CCW direction around the origin vertex
64  * (Onext) and around the left face (Lnext). There is also a "next"
65  * pointer for the global edge list (see below).
66  *
67  * The notation used for mesh navigation:
68  * Sym = the mate of a half-edge (same edge, but opposite direction)
69  * Onext = edge CCW around origin vertex (keep same origin)
70  * Dnext = edge CCW around destination vertex (keep same dest)
71  * Lnext = edge CCW around left face (dest becomes new origin)
72  * Rnext = edge CCW around right face (origin becomes new dest)
73  *
74  * "prev" means to substitute CW for CCW in the definitions above.
75  *
76  * The mesh keeps global lists of all vertices, faces, and edges,
77  * stored as doubly-linked circular lists with a dummy header node.
78  * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
79  *
80  * The circular edge list is special; since half-edges always occur
81  * in pairs (e and e->Sym), each half-edge stores a pointer in only
82  * one direction. Starting at eHead and following the e->next pointers
83  * will visit each *edge* once (ie. e or e->Sym, but not both).
84  * e->Sym stores a pointer in the opposite direction, thus it is
85  * always true that e->Sym->next->Sym->next == e.
86  *
87  * Each vertex has a pointer to next and previous vertices in the
88  * circular list, and a pointer to a half-edge with this vertex as
89  * the origin (NULL if this is the dummy header). There is also a
90  * field "data" for client data.
91  *
92  * Each face has a pointer to the next and previous faces in the
93  * circular list, and a pointer to a half-edge with this face as
94  * the left face (NULL if this is the dummy header). There is also
95  * a field "data" for client data.
96  *
97  * Note that what we call a "face" is really a loop; faces may consist
98  * of more than one loop (ie. not simply connected), but there is no
99  * record of this in the data structure. The mesh may consist of
100  * several disconnected regions, so it may not be possible to visit
101  * the entire mesh by starting at a half-edge and traversing the edge
102  * structure.
103  *
104  * The mesh does NOT support isolated vertices; a vertex is deleted along
105  * with its last edge. Similarly when two faces are merged, one of the
106  * faces is deleted (see __gl_meshDelete below). For mesh operations,
107  * all face (loop) and vertex pointers must not be NULL. However, once
108  * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
109  * faces of the mesh, one at a time. All external faces can be "zapped"
110  * before the mesh is returned to the client; then a NULL face indicates
111  * a region which is not part of the output polygon.
112  */
113 
115 {
116  GLUESvertex* next; /* next vertex (never NULL) */
117  GLUESvertex* prev; /* previous vertex (never NULL) */
118  GLUEShalfEdge* anEdge; /* a half-edge with this origin */
119  void* data; /* client's data */
120 
121  /* Internal data (keep hidden) */
122  double coords[3]; /* vertex location in 3D */
123  GLfloat s, t; /* projection onto the sweep plane */
124  long pqHandle; /* to allow deletion from priority queue */
125 };
126 
127 struct GLUESface
128 {
129  GLUESface* next; /* next face (never NULL) */
130  GLUESface* prev; /* previous face (never NULL) */
131  GLUEShalfEdge* anEdge; /* a half edge with this left face */
132  void* data; /* room for client's data */
133 
134  /* Internal data (keep hidden) */
135  GLUESface* trail; /* "stack" for conversion to strips */
136  GLboolean marked; /* flag for conversion to strips */
137  GLboolean inside; /* this face is in the polygon interior */
138 };
139 
141 {
142  GLUEShalfEdge* next; /* doubly-linked list (prev==Sym->next) */
143  GLUEShalfEdge* Sym; /* same edge, opposite direction */
144  GLUEShalfEdge* Onext; /* next edge CCW around origin */
145  GLUEShalfEdge* Lnext; /* next edge CCW around left face */
146  GLUESvertex* Org; /* origin vertex (Overtex too long) */
147  GLUESface* Lface; /* left face */
148 
149  /* Internal data (keep hidden) */
150  ActiveRegion* activeRegion; /* a region with this upper edge (sweep.c) */
151  int winding; /* change in winding number when crossing
152  from the right face to the left face */
153 };
154 
155 #define Rface Sym->Lface
156 #define Dst Sym->Org
157 
158 #define Oprev Sym->Lnext
159 #define Lprev Onext->Sym
160 #define Dprev Lnext->Sym
161 #define Rprev Sym->Onext
162 #define Dnext Rprev->Sym /* 3 pointers */
163 #define Rnext Oprev->Sym /* 3 pointers */
164 
165 struct GLUESmesh
166 {
167  GLUESvertex vHead; /* dummy header for vertex list */
168  GLUESface fHead; /* dummy header for face list */
169  GLUEShalfEdge eHead; /* dummy header for edge list */
170  GLUEShalfEdge eHeadSym; /* and its symmetric counterpart */
171 };
172 
173 /* The mesh operations below have three motivations: completeness,
174  * convenience, and efficiency. The basic mesh operations are MakeEdge,
175  * Splice, and Delete. All the other edge operations can be implemented
176  * in terms of these. The other operations are provided for convenience
177  * and/or efficiency.
178  *
179  * When a face is split or a vertex is added, they are inserted into the
180  * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
181  * This makes it easier to process all vertices or faces in the global lists
182  * without worrying about processing the same data twice. As a convenience,
183  * when a face is split, the "inside" flag is copied from the old face.
184  * Other internal data (v->data, v->activeRegion, f->data, f->marked,
185  * f->trail, e->winding) is set to zero.
186  *
187  * ********************** Basic Edge Operations **************************
188  *
189  * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
190  * The loop (face) consists of the two new half-edges.
191  *
192  * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
193  * mesh connectivity and topology. It changes the mesh so that
194  * eOrg->Onext <- OLD(eDst->Onext)
195  * eDst->Onext <- OLD(eOrg->Onext)
196  * where OLD(...) means the value before the meshSplice operation.
197  *
198  * This can have two effects on the vertex structure:
199  * - if eOrg->Org != eDst->Org, the two vertices are merged together
200  * - if eOrg->Org == eDst->Org, the origin is split into two vertices
201  * In both cases, eDst->Org is changed and eOrg->Org is untouched.
202  *
203  * Similarly (and independently) for the face structure,
204  * - if eOrg->Lface == eDst->Lface, one loop is split into two
205  * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
206  * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
207  *
208  * __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
209  * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
210  * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
211  * the newly created loop will contain eDel->Dst. If the deletion of eDel
212  * would create isolated vertices, those are deleted as well.
213  *
214  * ********************** Other Edge Operations **************************
215  *
216  * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
217  * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
218  * eOrg and eNew will have the same left face.
219  *
220  * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
221  * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
222  * eOrg and eNew will have the same left face.
223  *
224  * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
225  * to eDst->Org, and returns the corresponding half-edge eNew.
226  * If eOrg->Lface == eDst->Lface, this splits one loop into two,
227  * and the newly created loop is eNew->Lface. Otherwise, two disjoint
228  * loops are merged into one, and the loop eDst->Lface is destroyed.
229  *
230  * ************************ Other Operations *****************************
231  *
232  * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
233  * and no loops (what we usually call a "face").
234  *
235  * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
236  * both meshes, and returns the new mesh (the old meshes are destroyed).
237  *
238  * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
239  *
240  * __gl_meshZapFace( fZap ) destroys a face and removes it from the
241  * global face list. All edges of fZap will have a NULL pointer as their
242  * left face. Any edges which also have a NULL pointer as their right face
243  * are deleted entirely (along with any isolated vertices this produces).
244  * An entire mesh can be deleted by zapping its faces, one at a time,
245  * in any order. Zapped faces cannot be used in further mesh operations!
246  *
247  * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
248  */
249 
250 GLUEShalfEdge* __gl_meshMakeEdge(GLUESmesh* mesh);
251 int __gl_meshSplice(GLUEShalfEdge* eOrg, GLUEShalfEdge* eDst);
252 int __gl_meshDelete(GLUEShalfEdge* eDel);
253 
254 GLUEShalfEdge* __gl_meshAddEdgeVertex(GLUEShalfEdge* eOrg);
255 GLUEShalfEdge* __gl_meshSplitEdge(GLUEShalfEdge* eOrg);
256 GLUEShalfEdge* __gl_meshConnect(GLUEShalfEdge* eOrg, GLUEShalfEdge* eDst);
257 
258 GLUESmesh* __gl_meshNewMesh(void);
259 GLUESmesh* __gl_meshUnion(GLUESmesh* mesh1, GLUESmesh* mesh2);
260 void __gl_meshDeleteMesh(GLUESmesh* mesh);
261 void __gl_meshZapFace(GLUESface* fZap);
262 
263 #ifdef NDEBUG
264  #define __gl_meshCheckMesh(mesh)
265 #else
266  void __gl_meshCheckMesh(GLUESmesh* mesh);
267 #endif
268 
269 #endif /* __mesh_h_ */