1 | /************************************************************************
|
---|
2 |
|
---|
3 | Primitive entities for adjacency models (AdjModel).
|
---|
4 | $Id: AdjPrims.cxx,v 1.1 1997/06/25 15:24:55 garland Exp $
|
---|
5 |
|
---|
6 | Adapted from:
|
---|
7 | mlab: (Id: primitives.cc,v 1.7 1997/02/06 16:32:45 garland Exp)
|
---|
8 | via
|
---|
9 | QSlim: (Id: primitives.cc,v 1.2 1997/02/18 21:11:27 garland Exp)
|
---|
10 |
|
---|
11 | ************************************************************************/
|
---|
12 |
|
---|
13 | #include "AdjPrims.h"
|
---|
14 |
|
---|
15 | using namespace qslim;
|
---|
16 |
|
---|
17 | void Vertex::kill()
|
---|
18 | {
|
---|
19 | #ifdef SAFETY
|
---|
20 | assert( edge_uses.length() == 0 );
|
---|
21 | #endif
|
---|
22 | markInvalid();
|
---|
23 | edge_uses.reset();
|
---|
24 | }
|
---|
25 |
|
---|
26 | void Vertex::linkEdge(Edge *e)
|
---|
27 | {
|
---|
28 | edge_uses.add(e);
|
---|
29 | }
|
---|
30 |
|
---|
31 | void Vertex::unlinkEdge(Edge *e)
|
---|
32 | {
|
---|
33 | int index = edge_uses.find(e);
|
---|
34 |
|
---|
35 | #ifdef SAFETY
|
---|
36 | assert( index >= 0 );
|
---|
37 | #endif
|
---|
38 | edge_uses.remove(index);
|
---|
39 | if( edge_uses.length() <= 0 )
|
---|
40 | kill();
|
---|
41 | }
|
---|
42 |
|
---|
43 | #include <assert.h>
|
---|
44 |
|
---|
45 | void Vertex::remapTo(Vertex *v)
|
---|
46 | {
|
---|
47 | if( v != this )
|
---|
48 | {
|
---|
49 | for(int i=0; i<edge_uses.length(); i++)
|
---|
50 | {
|
---|
51 | assert( edge_uses(i)->org() == this );
|
---|
52 | edge_uses(i)->remapEndpoint(this, v);
|
---|
53 | }
|
---|
54 |
|
---|
55 | kill();
|
---|
56 | }
|
---|
57 | }
|
---|
58 |
|
---|
59 |
|
---|
60 | Edge::Edge(Vertex *a, Vertex *b)
|
---|
61 | {
|
---|
62 | v1 = a;
|
---|
63 | v1->linkEdge(this);
|
---|
64 |
|
---|
65 | face_uses = new buffer<Face *>(2);
|
---|
66 |
|
---|
67 | twin = new Edge(this, b);
|
---|
68 | }
|
---|
69 |
|
---|
70 | Edge::Edge(Edge *sibling, Vertex *org)
|
---|
71 | {
|
---|
72 | v1 = org;
|
---|
73 | v1->linkEdge(this);
|
---|
74 |
|
---|
75 | face_uses = sibling->face_uses;
|
---|
76 | twin = sibling;
|
---|
77 | }
|
---|
78 |
|
---|
79 | Edge::~Edge()
|
---|
80 | {
|
---|
81 | if( twin )
|
---|
82 | {
|
---|
83 | face_uses->f_r_e_e();
|
---|
84 | delete face_uses;
|
---|
85 |
|
---|
86 | twin->twin = NULL;
|
---|
87 | delete twin;
|
---|
88 | }
|
---|
89 | }
|
---|
90 |
|
---|
91 | void Edge::kill()
|
---|
92 | {
|
---|
93 | #ifdef SAFETY
|
---|
94 | assert( face_uses->length() == 0 );
|
---|
95 | #endif
|
---|
96 | if( isValid() )
|
---|
97 | {
|
---|
98 | org()->unlinkEdge(this);
|
---|
99 | dest()->unlinkEdge(sym());
|
---|
100 | markInvalid();
|
---|
101 | twin->markInvalid();
|
---|
102 | face_uses->reset();
|
---|
103 | }
|
---|
104 | }
|
---|
105 |
|
---|
106 | void Edge::linkFace(Face *face)
|
---|
107 | {
|
---|
108 | face_uses->add(face);
|
---|
109 | }
|
---|
110 |
|
---|
111 | void Edge::unlinkFace(Face *face)
|
---|
112 | {
|
---|
113 | int index = face_uses->find(face);
|
---|
114 |
|
---|
115 | #ifdef SAFETY
|
---|
116 | assert( index>=0 );
|
---|
117 | #endif
|
---|
118 | face_uses->remove(index);
|
---|
119 | if( face_uses->length() == 0 )
|
---|
120 | kill();
|
---|
121 | }
|
---|
122 |
|
---|
123 | void Edge::remapTo(Edge *e)
|
---|
124 | {
|
---|
125 | if( e != this )
|
---|
126 | {
|
---|
127 | for(int i=0; i<face_uses->length(); i++)
|
---|
128 | {
|
---|
129 | (*face_uses)(i)->remapEdge(this, e);
|
---|
130 | }
|
---|
131 |
|
---|
132 | // Disconnect from all faces and vertices
|
---|
133 | kill();
|
---|
134 | }
|
---|
135 | }
|
---|
136 |
|
---|
137 | void Edge::remapEndpoint(Vertex *from, Vertex *to)
|
---|
138 | {
|
---|
139 | if( org()==from )
|
---|
140 | {
|
---|
141 | v1 = to;
|
---|
142 | to->linkEdge(this);
|
---|
143 | }
|
---|
144 | else if( dest()==from )
|
---|
145 | {
|
---|
146 | twin->v1 = to;
|
---|
147 | to->linkEdge(twin);
|
---|
148 | }
|
---|
149 | else
|
---|
150 | {
|
---|
151 | std::cerr << "WARNING remapEndpoint: Illegal endpoint." << std::endl;
|
---|
152 | }
|
---|
153 |
|
---|
154 | //
|
---|
155 | // The cached Plane equations for the faces attached to us may
|
---|
156 | // no longer be valid (in general, chances are pretty slim that they're OK)
|
---|
157 | for(int i=0; i<face_uses->length(); i++)
|
---|
158 | {
|
---|
159 | face_uses->ref(i)->invalidatePlane();
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 |
|
---|
164 | Face::Face(Edge *e0, Edge *e1, Edge *e2)
|
---|
165 | : Face3(*e0->org(), *e1->org(), *e2->org())
|
---|
166 | {
|
---|
167 | edges[0] = e0;
|
---|
168 | edges[1] = e1;
|
---|
169 | edges[2] = e2;
|
---|
170 |
|
---|
171 | edges[0]->linkFace(this);
|
---|
172 | edges[1]->linkFace(this);
|
---|
173 | edges[2]->linkFace(this);
|
---|
174 |
|
---|
175 | #ifdef SUPPORT_FCOLOR
|
---|
176 | props = NULL;
|
---|
177 | #endif
|
---|
178 | }
|
---|
179 |
|
---|
180 | void Face::kill()
|
---|
181 | {
|
---|
182 | if( isValid() )
|
---|
183 | {
|
---|
184 | if( edge(0)->isValid() )
|
---|
185 | edge(0)->unlinkFace(this);
|
---|
186 |
|
---|
187 | if( edge(1)->isValid() )
|
---|
188 | edge(1)->unlinkFace(this);
|
---|
189 |
|
---|
190 | if( edge(2)->isValid() )
|
---|
191 | edge(2)->unlinkFace(this);
|
---|
192 |
|
---|
193 | markInvalid();
|
---|
194 | }
|
---|
195 | }
|
---|
196 |
|
---|
197 | void Face::remapEdge(Edge *from, Edge *to)
|
---|
198 | {
|
---|
199 | for(int i=0; i<3; i++)
|
---|
200 | {
|
---|
201 | if( edges[i] == from )
|
---|
202 | {
|
---|
203 | edges[i] = to;
|
---|
204 | to->linkFace(this);
|
---|
205 | }
|
---|
206 | else if( edges[i] == from->sym() )
|
---|
207 | {
|
---|
208 | edges[i] = to->sym();
|
---|
209 | to->sym()->linkFace(this);
|
---|
210 | }
|
---|
211 | }
|
---|
212 |
|
---|
213 | invalidatePlane();
|
---|
214 | }
|
---|
215 |
|
---|
216 |
|
---|
217 | void qslim::untagFaceLoop(Vertex *v)
|
---|
218 | {
|
---|
219 | edge_buffer& edges = v->edgeUses();
|
---|
220 |
|
---|
221 | for(int j=0; j<edges.length(); j++)
|
---|
222 | {
|
---|
223 | face_buffer& faces = edges(j)->faceUses();
|
---|
224 | for(int k=0; k<faces.length(); k++)
|
---|
225 | faces(k)->untag();
|
---|
226 | }
|
---|
227 | }
|
---|
228 |
|
---|
229 | void qslim::collectFaceLoop(Vertex *v, face_buffer& loop)
|
---|
230 | {
|
---|
231 | edge_buffer& edges = v->edgeUses();
|
---|
232 |
|
---|
233 | for(int j=0; j<edges.length(); j++)
|
---|
234 | {
|
---|
235 | face_buffer& faces = edges(j)->faceUses();
|
---|
236 | for(int k=0; k<faces.length(); k++)
|
---|
237 | if( !faces(k)->isTagged() )
|
---|
238 | {
|
---|
239 | loop.add(faces(k));
|
---|
240 | faces(k)->tag();
|
---|
241 | }
|
---|
242 | }
|
---|
243 | }
|
---|
244 |
|
---|
245 | int qslim::classifyEdge(Edge *e)
|
---|
246 | {
|
---|
247 | int cls = e->faceUses().length();
|
---|
248 |
|
---|
249 | if( cls>3 ) cls=3;
|
---|
250 |
|
---|
251 | return cls;
|
---|
252 | }
|
---|
253 |
|
---|
254 | int qslim::classifyVertex(Vertex *v)
|
---|
255 | {
|
---|
256 | int border_count = 0;
|
---|
257 | const edge_buffer& edges = v->edgeUses();
|
---|
258 |
|
---|
259 | for(int i=0; i<edges.length(); i++)
|
---|
260 | if( classifyEdge(edges(i)) == 1 )
|
---|
261 | border_count++;
|
---|
262 |
|
---|
263 | if( border_count == edges.length() )
|
---|
264 | return VERTEX_BORDER_ONLY;
|
---|
265 | else
|
---|
266 | return (border_count > 0);
|
---|
267 | }
|
---|