1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2016 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 /****************************************************************************
24 History
25
26
27
28 ****************************************************************************/
29
30 #ifndef __VCG_TETRA_POS
31 #define __VCG_TETRA_POS
32
33 namespace vcg {
34 namespace tetra {
35
36 /** \addtogroup tetra */
37 /*@{*/
38
39
40 /** Class VTIterator.
41 This is a vertex - tetrahedron iterator
42 @param MTTYPE (Template Parameter) Specifies the type of the tetrahedron.
43 */
44 template < class MTTYPE>
45 class VTIterator
46 {
47 public:
48 /// The tetrahedron type
49 typedef MTTYPE TetraType;
50 private:
51 /// Pointer to a tetrahedron
52 TetraType *_vt;
53 /// Index of one vertex
54 int _vi;
55 /// Default Constructor
56 public:
VTIterator()57 VTIterator() : _vt(0), _vi(-1){}
58 /// Constructor which associates the EdgePos elementet with a face and its edge
VTIterator(TetraType * const tp,int const zp)59 VTIterator(TetraType * const tp, int const zp)
60 {
61 _vt=tp;
62 _vi=zp;
63 }
64
~VTIterator()65 ~VTIterator(){};
66
67 /// Return the tetrahedron stored in the half edge
Vt()68 inline TetraType* & Vt()
69 {
70 return _vt;
71 }
72
73 /// Return the index of vertex as seen from the tetrahedron
Vi()74 inline int & Vi()
75 {
76 return _vi;
77 }
78
79 /// Return the index of vertex as seen from the tetrahedron
Vi()80 inline const int & Vi() const
81 {
82 return _vi;
83 }
84
End()85 inline bool End(){return (Vt()==NULL);}
86
87 /// move on the next tetrahedron that share the vertex
88 void operator++()
89 {
90 int vi=Vi();
91 TetraType * tw = Vt();
92 Vt() = tw->TVp(vi);
93 Vi() = tw->TVi(vi);
94
95 assert((Vt()==NULL)||((tw->V(vi))==(Vt()->V(Vi()))));
96 }
97
98 };
99
100
101 /** Templated over the class tetrahedron, it stores a \em position over a tetrahedron in a mesh.
102 It contain a pointer to the current tetrahedron,
103 the index of one face,edge and a edge's incident vertex.
104 */
105 template < class MTTYPE>
106 class Pos
107 {
108 public:
109
110 /// The tetrahedron type
111 typedef MTTYPE TetraType;
112 /// The vertex type
113 typedef typename TetraType::VertexType VertexType;
114 /// The coordinate type
115 typedef typename TetraType::VertexType::CoordType CoordType;
116 ///The HEdgePos type
117 typedef Pos<TetraType> BasePosType;
118
119 private:
120 /// Pointer to the tetrahedron of the half-edge
121 TetraType *_t;
122 /// Index of the face
123 char _f;
124 /// Index of the edge
125 char _e;
126 /// Pointer to the vertex
127 char _v;
128
129 public:
130 /// Default constructor
Pos()131 Pos(){SetNull();};
132 /// Constructor which associates the half-edge elementet with a face, its edge and its vertex
Pos(TetraType * const tp,char const fap,char const ep,char const vp)133 Pos(TetraType * const tp, char const fap,char const ep,
134 char const vp){_t=tp;_f=fap;_e=ep;_v=vp;}
135
~Pos()136 ~Pos(){};
137
138 /// Return the tetrahedron stored in the half edge
T()139 inline TetraType* & T()
140 {
141 return _t;
142 }
143
144 /// Return the tetrahedron stored in the half edge
T()145 inline TetraType* const & T() const
146 {
147 return _t;
148 }
149
150 /// Return the index of face as seen from the tetrahedron
F()151 inline char & F()
152 {
153 return _f;
154 }
155
156 /// Return the index of face as seen from the tetrahedron
F()157 inline const char & F() const
158 {
159 return _f;
160 }
161
162 /// Return the index of face as seen from the tetrahedron
E()163 inline char & E()
164 {
165 return _e;
166 }
167
168 /// Return the index of face as seen from the tetrahedron
E()169 inline const char & E() const
170 {
171 return _e;
172 }
173
174 /// Return the index of vertex as seen from the tetrahedron
V()175 inline char & V()
176 {
177 return _v;
178 }
179
180 /// Return the index of vertex as seen from the tetrahedron
V()181 inline const char & V() const
182 {
183 return _v;
184 }
185
186 /// Operator to compare two half-edge
187 inline bool operator == ( BasePosType const & p ) const {
188 return (T()==p.T() && F()==p.F() && E==p.E() && V==p.V());
189 }
190
191 /// Operator to compare two half-edge
192 inline bool operator != ( BasePosType const & p ) const {
193 return (!((*this)==p));
194 }
195
196 /// Set to null the half-edge
SetNull()197 void SetNull(){
198 T()=0;
199 F()=-1;
200 E()=-1;
201 V()=-1;
202 }
203
204 /// Check if the half-edge is null
IsNull()205 bool IsNull() const {
206 return ((T()==0) || (F()<0) || (E()<0) || (V()<0));
207 }
208
209
210 /// Changes edge maintaining the same face and the same vertex
FlipE()211 void FlipE()
212 {
213
214 //take the absolute index of the tree edges of the faces
215 char e0=vcg::Tetra::EofF(_f ,0);
216 char e1=vcg::Tetra::EofF(_f ,1);
217 char e2=vcg::Tetra::EofF(_f ,2);
218 //eliminate the same as himself
219 if (e0==E())
220 {
221 e0=e1;
222 e1=e2;
223 }
224 else
225 if (e1==E())
226 {
227 e1=e2;
228 }
229
230 //now choose the one that preserve the same vertex
231 if ((vcg::Tetra::VofE(e1,0)==V())||(vcg::Tetra::VofE(e1,1)==V()))
232 E()=e1;
233 else
234 E()=e0;
235 }
236
237
238 /// Changes vertex maintaining the same face and the same edge
FlipV()239 void FlipV()
240 {
241 // in the same edge choose the one that change
242 char v0=vcg::Tetra::VofE(E(),0);
243 char v1=vcg::Tetra::VofE(E(),1);
244 if (v0!=V())
245 V()=v0;
246 else
247 V()=v1;
248 }
249
250 /// Changes face maintaining the same vertex and the same edge
FlipF()251 void FlipF()
252 {
253 char f0=vcg::Tetra::FofE(E(),0);
254 char f1=vcg::Tetra::FofE(E(),1);
255 if (f0!=F())
256 F()=f0;
257 else
258 F()=f1;
259 }
260
261 /// Changes tetrahedron maintaining the same face edge and vertex'... to finish
FlipT()262 void FlipT()
263 {
264
265 //save the two vertices of the old edge
266 VertexType *v0=T()->V(vcg::Tetra::VofE(E(),0));
267 VertexType *v1=T()->V(vcg::Tetra::VofE(E(),1));
268
269 //get the current vertex
270 VertexType *vcurr=T()->V(V());
271
272 //get new tetrahedron according to faceto face topology
273 TetraType *nt=T()->TTp(F());
274 char nfa=T()->TTi(F());
275 if (nfa!=-1)
276 {
277 //find the right edge
278 char ne0=vcg::Tetra::EofF(nfa,0);
279 char ne1=vcg::Tetra::EofF(nfa,1);
280 char ne2=vcg::Tetra::EofF(nfa,2);
281
282 //the vertices of new edges
283 VertexType *vn0=nt->V(vcg::Tetra::VofE(ne0,0));
284 VertexType *vn1=nt->V(vcg::Tetra::VofE(ne0,1));
285 //verify that the two vertices of tetrahedron are identical
286 if (((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1)))
287 E()=ne0;
288 else
289 {
290 vn0=nt->V(vcg::Tetra::VofE(ne1,0));
291 vn1=nt->V(vcg::Tetra::VofE(ne1,1));
292 if (((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1)))
293 E()=ne1;
294 else
295 {
296 #ifdef _DEBUG
297 vn0=nt->V(vcg::Tetra::VofE(ne2,0));
298 vn1=nt->V(vcg::Tetra::VofE(ne2,1));
299 assert(((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1)));
300 #endif
301 E()=ne2;
302 }
303 }
304
305 //find the right vertex
306 vn0=nt->V(vcg::Tetra::VofE(E(),0));
307 #ifdef _DEBUG
308 vn1=nt->V(vcg::Tetra::VofE(E(),1));
309 assert((vn0==vcurr)||(vn1==vcurr));
310 #endif
311 if (vn0==vcurr)
312 V()=vcg::Tetra::VofE(E(),0);
313 else
314 V()=vcg::Tetra::VofE(E(),1);
315
316 T()=nt;
317 assert(T()->V(V())==vcurr);
318 F()=nfa;
319 }
320 }
321
322 ///returns the next half edge on the same edge
NextT()323 void NextT( )
324 {
325 #ifdef _DEBUG
326 VertexType *vold=T()->V(V());
327 #endif
328 FlipT();
329 FlipF();
330 #ifdef _DEBUG
331 VertexType *vnew=T()->V(V());
332 assert(vold==vnew);
333 #endif
334 }
335
Assert()336 void Assert()
337 #ifdef _DEBUG
338 {
339 HETYPE ht=*this;
340 ht.FlipT();
341 ht.FlipT();
342 assert(ht==*this);
343
344 ht=*this;
345 ht.FlipF();
346 ht.FlipF();
347 assert(ht==*this);
348
349 ht=*this;
350 ht.FlipE();
351 ht.FlipE();
352 assert(ht==*this);
353
354 ht=*this;
355 ht.FlipV();
356 ht.FlipV();
357 assert(ht==*this);
358 }
359 #else
360 {}
361 #endif
362 };
363
364 ///this pos structure jump on next tetrahedron if find an external face
365 template < class MTTYPE>
366 class PosJump:public Pos<MTTYPE>
367 {
368 private:
369 MTTYPE *_t_initial;
370 short int _back;
371 public :
372 typedef MTTYPE TetraType;
PosJump(const TetraType * tp,const int fap,const int ep,int vp)373 PosJump(const TetraType* tp,const int fap,const int ep,
374 int vp){this->T()=tp;this->F()=fap;this->E()=ep;this->V()=vp;_t_initial=tp;_back=0;}
375
NextT()376 void NextT()
377 {
378 #ifdef _DEBUG
379 int cont=0;
380 #endif
381 MTTYPE *tpred=this->T();
382 Pos<MTTYPE>::NextT();
383 //external face
384 if (tpred==this->T())
385 {
386 while (this->T()!=_t_initial)
387 {
388 Pos<MTTYPE>::NextT();
389 #ifdef _DEBUG
390 cont++;
391 assert (cont<500);
392 #endif
393 }
394 _back++;
395 if (_back==1)
396 {
397 Pos<MTTYPE>::NextT();
398 }
399 }
400 }
401 };
402
403 ///this pos structure jump on next tetrahedron in rotational sense if find an external face
404 template < class MTTYPE>
405 class PosLoop:public Pos<MTTYPE>
406 {
407 private:
408 MTTYPE *_t_initial;
409 bool _jump;
410 bool _loop;
411 public :
412 typedef MTTYPE TetraType;
PosLoop(TetraType * tp,const int fap,const int ep,int vp)413 PosLoop(TetraType* tp,const int fap,const int ep,
414 int vp){this->T()=tp;this->F()=fap;this->E()=ep;this->V()=vp;_t_initial=tp;_jump=false;_loop=false;}
415
LoopEnd()416 bool LoopEnd()
417 {
418 return (_loop);
419 }
420
Jump()421 bool Jump()
422 {
423 return(_jump);
424 }
425
Reset()426 void Reset()
427 {
428 _loop=false;
429 _jump=false;
430 }
431
NextT()432 void NextT()
433 {
434 #ifdef _DEBUG
435 TetraType *t_old=this->T();
436 #endif
437 TetraType *tpred=this->T();
438 Pos<TetraType>::NextT();
439 _loop=false;
440 _jump=false;
441
442 //external face
443 if (tpred==this->T())
444 {
445 tpred=this->T();
446 //jump next one
447 Pos<TetraType>::NextT();
448 //find the next external face
449 while (tpred!=this->T())
450 {
451 tpred=this->T();
452 Pos<TetraType>::NextT();
453 }
454 ////reset right rotation sense
455 // Pos<TetraType>::NextT();
456 _jump=true;
457 }
458 if (this->T()==_t_initial)
459 _loop=true;
460 #ifdef _DEBUG
461 if (_loop==false)
462 assert(t_old!=this->T());
463 #endif
464 }
465
466 };
467 //@}
468 }//end namespace tetra
469 }//end namespace vcg
470
471 #endif
472