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