$darkmode
VCG Library
topology.h
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 #ifndef _VCG_FACE_TOPOLOGY
25 #define _VCG_FACE_TOPOLOGY
26 
27 #include "pos.h"
28 
29 #include <vcg/complex/allocate.h>
30 
31 namespace vcg {
32 namespace face {
35 
40 template <class FaceType>
41 inline bool IsManifold( FaceType const & f, const int j )
42 {
43  assert(f.cFFp(j) != 0); // never try to use this on uninitialized topology
44  if(FaceType::HasFFAdjacency())
45  return ( f.cFFp(j) == &f || &f == f.cFFp(j)->cFFp(f.cFFi(j)) );
46  else
47  return true;
48 }
49 
54 template <class FaceType>
55 inline bool IsBorder(FaceType const & f, const int j )
56 {
57  if(FaceType::HasFFAdjacency())
58  return f.cFFp(j)==&f;
59  //return f.IsBorder(j);
60 
61  assert(0);
62  return true;
63 }
64 
83 template <class FaceType>
84 inline typename FaceType::ScalarType DihedralAngleRad(FaceType & f, const int i )
85 {
86  typedef typename FaceType::ScalarType ScalarType;
87  typedef typename FaceType::CoordType CoordType;
88  typedef typename FaceType::VertexType VertexType;
89 
90  FaceType *f0 = &f;
91  FaceType *f1 = f.FFp(i);
92  int i0=i;
93  int i1=f.FFi(i);
94  VertexType *vf0 = f0->V2(i0);
95  VertexType *vf1 = f1->V2(i1);
96 
97  CoordType n0 = TriangleNormal(*f0).Normalize();
98  CoordType n1 = TriangleNormal(*f1).Normalize();
99  ScalarType off0 = n0*vf0->P();
100  ScalarType off1 = n1*vf1->P();
101 
102  ScalarType dist01 = off0 - n0*vf1->P();
103  ScalarType dist10 = off1 - n1*vf0->P();
104 
105  // just to be sure use the sign of the largest in absolute value;
106  ScalarType sign;
107  if(fabs(dist01) > fabs(dist10)) sign = dist01;
108  else sign=dist10;
109 
110  ScalarType angleRad=AngleN(n0,n1);
111 
112  if(sign > 0 ) return angleRad;
113  else return -angleRad;
114 }
115 
117 template <class FaceType>
118 inline typename FaceType::ScalarType WedgeAngleRad(FaceType & f, const int i )
119 {
120  auto &P0=f.P(i);
121  auto &P1=f.P(f.Next(i));
122  auto &P2=f.P(f.Prev(i));
123  return vcg::Angle(P2 - P0,P1 - P0);
124 }
125 
127 template <class FaceType>
128 inline int BorderCount(FaceType const & f)
129 {
130  if(FaceType::HasFFAdjacency())
131  {
132  int t = 0;
133  if( IsBorder(f,0) ) ++t;
134  if( IsBorder(f,1) ) ++t;
135  if( IsBorder(f,2) ) ++t;
136  return t;
137  }
138  else return 3;
139 }
140 
141 
143 template <class FaceType>
144 inline int ComplexSize(FaceType & f, const int e)
145 {
146  if(FaceType::HasFFAdjacency())
147  {
148  if(face::IsBorder<FaceType>(f,e)) return 1;
149  if(face::IsManifold<FaceType>(f,e)) return 2;
150 
151  // Non manifold case
152  Pos< FaceType > fpos(&f,e);
153  int cnt=0;
154  do
155  {
156  fpos.NextF();
157  assert(!fpos.IsBorder());
158  assert(!fpos.IsManifold());
159  ++cnt;
160  }
161  while(fpos.f!=&f);
162  assert (cnt>2);
163  return cnt;
164  }
165  assert(0);
166  return 2;
167 }
168 
169 
176 template <class FaceType>
177 bool FFCorrectness(FaceType & f, const int e)
178 {
179  if(f.FFp(e)==0) return false; // Not computed or inconsistent topology
180 
181  if(f.FFp(e)==&f) // Border
182  {
183  if(f.FFi(e)==e) return true;
184  else return false;
185  }
186 
187  if(f.FFp(e)->FFp(f.FFi(e))==&f) // plain two manifold
188  {
189  if(f.FFp(e)->FFi(f.FFi(e))==e) return true;
190  else return false;
191  }
192 
193  // Non Manifold Case
194  // all the faces must be connected in a loop.
195 
196  Pos< FaceType > curFace(&f,e); // Build the half edge
197  int cnt=0;
198  do
199  {
200  if(curFace.IsManifold()) return false;
201  if(curFace.IsBorder()) return false;
202  curFace.NextF();
203  cnt++;
204  assert(cnt<100);
205  (void)cnt;
206  }
207  while ( curFace.f != &f);
208  return true;
209 }
210 
211 
219 template <class FaceType>
220 void FFDetachManifold(FaceType & f, const int e)
221 {
222  assert(FFCorrectness<FaceType>(f,e));
223  assert(!IsBorder<FaceType>(f,e)); // Never try to detach a border edge!
224  FaceType *ffp = f.FFp(e);
225  //int ffi=f.FFp(e);
226  int ffi=f.FFi(e);
227 
228  f.FFp(e)=&f;
229  f.FFi(e)=e;
230  ffp->FFp(ffi)=ffp;
231  ffp->FFi(ffi)=ffi;
232 
233  f.SetB(e);
234  f.ClearF(e);
235  ffp->SetB(ffi);
236  ffp->ClearF(ffi);
237 
238  assert(FFCorrectness<FaceType>(f,e));
239  assert(FFCorrectness<FaceType>(*ffp,ffi));
240 }
241 
249 template <class FaceType>
250 void FFDetach(FaceType & f, const int e)
251 {
252  assert(FFCorrectness<FaceType>(f,e));
253  assert(!IsBorder<FaceType>(f,e)); // Never try to detach a border edge!
254  int complexity=ComplexSize(f,e);
255  (void) complexity;
256  assert(complexity>0);
257  vcg::face::Pos<FaceType> FirstFace(&f,e); // Build the half edge
258  vcg::face::Pos<FaceType> LastFace(&f,e); // Build the half edge
259  FirstFace.NextF();
260  LastFace.NextF();
261  int cnt=0;
262 
263 // then in case of non manifold face continue to advance LastFace
264 // until I find it become the one that is before the one I want to detach
265 
266  while ( LastFace.f->FFp(LastFace.z) != &f)
267  {
268  assert(ComplexSize(*LastFace.f,LastFace.z)==complexity);
269  assert(!LastFace.IsManifold()); // We enter in this loop only if we are on a non manifold edge
270  assert(!LastFace.IsBorder());
271  LastFace.NextF();
272  cnt++;
273  assert(cnt<100);
274  (void)cnt;
275  }
276 
277  assert(LastFace.f->FFp(LastFace.z)==&f);
278  assert(f.FFp(e)== FirstFace.f);
279 
280  // Now we link the last one to the first one, skipping the face to be detached;
281  LastFace.f->FFp(LastFace.z) = FirstFace.f;
282  LastFace.f->FFi(LastFace.z) = FirstFace.z;
283  assert(ComplexSize(*LastFace.f,LastFace.z)==complexity-1);
284 
285  // At the end self-connect the chosen edge to make a border.
286  f.FFp(e) = &f;
287  f.FFi(e) = e;
288  assert(ComplexSize(f,e)==1);
289 
290  assert(FFCorrectness<FaceType>(*LastFace.f,LastFace.z));
291  assert(FFCorrectness<FaceType>(f,e));
292 }
293 
294 
295 
304 template <class FaceType>
305 void FFAttach(FaceType &f, int z1, FaceType &f2, int z2)
306 {
307  vcg::face::Pos< FaceType > EPB(&f2,z2);
308  vcg::face::Pos< FaceType > TEPB = EPB;;
309  // search the last face in the non manifold loop before the one to be attached
310  EPB.NextF();
311  while( EPB.f != &f2)
312  {
313  TEPB = EPB;
314  EPB.NextF();
315  }
316  // save the old values
317  FaceType *f1prec = f.FFp(z1);
318  int z1prec = f.FFi(z1);
319 
320  assert(f1prec == &f);
321  assert(TEPB.f->FFp(TEPB.z) == &f2);
322  f.FFp(z1) = TEPB.f->FFp(TEPB.z);
323  f.FFi(z1) = TEPB.f->FFi(TEPB.z);
324 
325  TEPB.f->FFp(TEPB.z) = f1prec;
326  TEPB.f->FFi(TEPB.z) = z1prec;
327  assert(FFCorrectness<FaceType>(f,z1));
328  assert(FFCorrectness<FaceType>(*TEPB.f, TEPB.z));
329 }
330 
338 template <class FaceType>
339 void FFAttachManifold(FaceType * f1, int z1, FaceType * f2, int z2)
340 {
341  assert(IsBorder<FaceType>(*f1,z1) || f1->FFp(z1)==0);
342  assert(IsBorder<FaceType>(*f2,z2) || f2->FFp(z2)==0);
343  assert(f1->V0(z1) == f2->V0(z2) || f1->V0(z1) == f2->V1(z2));
344  assert(f1->V1(z1) == f2->V0(z2) || f1->V1(z1) == f2->V1(z2));
345  f1->FFp(z1) = f2;
346  f1->FFi(z1) = z2;
347  f2->FFp(z2) = f1;
348  f2->FFi(z2) = z1;
349 }
350 
351 // This one should be called only on uninitialized faces.
352 template <class FaceType>
353 void FFSetBorder(FaceType * f1, int z1)
354 {
355  assert(f1->FFp(z1)==0 || IsBorder(*f1,z1));
356 
357  f1->FFp(z1)=f1;
358  f1->FFi(z1)=z1;
359 }
360 
361 template <class FaceType>
362 void AssertAdj(FaceType & f)
363 {
364  (void)f;
365  assert(f.FFp(0)->FFp(f.FFi(0))==&f);
366  assert(f.FFp(1)->FFp(f.FFi(1))==&f);
367  assert(f.FFp(2)->FFp(f.FFi(2))==&f);
368 
369  assert(f.FFp(0)->FFi(f.FFi(0))==0);
370  assert(f.FFp(1)->FFi(f.FFi(1))==1);
371  assert(f.FFp(2)->FFi(f.FFi(2))==2);
372 }
373 
379 template <class FaceType>
380 bool CheckOrientation(FaceType &f, int z)
381 {
382  if (IsBorder(f, z))
383  return true;
384  else
385  {
386  FaceType *g = f.FFp(z);
387  int gi = f.FFi(z);
388  if (f.V0(z) == g->V1(gi))
389  return true;
390  else
391  return false;
392  }
393 }
394 
395 
401 template <class FaceType>
402 void SwapEdge(FaceType &f, const int z) { SwapEdge<FaceType,true>(f,z); }
403 
404 template <class FaceType, bool UpdateTopology>
405 void SwapEdge(FaceType &f, const int z)
406 {
407  // swap V0(z) with V1(z)
408  std::swap(f.V0(z), f.V1(z));
409 
410  // Management of faux edge information (edge z is not affected)
411  bool Faux1 = f.IsF((z+1)%3);
412  bool Faux2 = f.IsF((z+2)%3);
413  if(Faux1) f.SetF((z+2)%3); else f.ClearF((z+2)%3);
414  if(Faux2) f.SetF((z+1)%3); else f.ClearF((z+1)%3);
415 
416  if(f.HasFFAdjacency() && UpdateTopology)
417  {
418  // store information to preserve topology
419  int z1 = (z+1)%3;
420  int z2 = (z+2)%3;
421  FaceType *g1p = f.FFp(z1);
422  FaceType *g2p = f.FFp(z2);
423  int g1i = f.FFi(z1);
424  int g2i = f.FFi(z2);
425 
426  // g0 face topology is not affected by the swap
427 
428  if (g1p != &f)
429  {
430  g1p->FFi(g1i) = z2;
431  f.FFi(z2) = g1i;
432  }
433  else
434  {
435  f.FFi(z2) = z2;
436  }
437 
438  if (g2p != &f)
439  {
440  g2p->FFi(g2i) = z1;
441  f.FFi(z1) = g2i;
442  }
443  else
444  {
445  f.FFi(z1) = z1;
446  }
447 
448  // finalize swap
449  f.FFp(z1) = g2p;
450  f.FFp(z2) = g1p;
451  }
452 }
453 
459 template <class FaceType>
460 bool FFLinkCondition(FaceType &f, const int z)
461 {
462  typedef typename FaceType::VertexType VertexType;
463  typedef typename vcg::face::Pos< FaceType > PosType;
464 
465  VertexType *v0=f.V0(z);
466  VertexType *v1=f.V1(z);
467 
468  PosType p0(&f,v0);
469  PosType p1(&f,v1);
470  std::vector<VertexType *>v0Vec;
471  std::vector<VertexType *>v1Vec;
472  VVOrderedStarFF(p0,v0Vec);
473  VVOrderedStarFF(p1,v1Vec);
474  std::set<VertexType *> v0set;
475  v0set.insert(v0Vec.begin(),v0Vec.end());
476  assert(v0set.size() == v0Vec.size());
477  int cnt =0;
478  for(size_t i=0;i<v1Vec.size();++i)
479  if(v0set.find(v1Vec[i]) != v0set.end())
480  cnt++;
481 
482  if(face::IsBorder(f,z) && (cnt==1)) return true;
483  if(!face::IsBorder(f,z) && (cnt==2)) return true;
484  //assert(0);
485  return false;
486 }
487 
505 template <class MeshType>
506 void FFEdgeCollapse(MeshType &m, typename MeshType::FaceType &f, const int z)
507 {
508  typedef typename MeshType::FaceType FaceType;
509  typedef typename MeshType::VertexType VertexType;
510  typedef typename vcg::face::Pos< FaceType > PosType;
511  FaceType *f0 = &f;
512  int z0=z;
513  FaceType *f1 = f.FFp(z);
514  int z1=f.FFi(z);
515 
516  VertexType *delV=f.V0(z);
517  VertexType *surV=f.V1(z);
518 
519  // Collect faces that have to be updated
520  PosType delPos(f0,delV);
521  std::vector<PosType> faceToBeChanged;
522  VFOrderedStarFF(delPos,faceToBeChanged);
523 
524  // Topology Stitching
525  FaceType *f01= 0,*f02= 0,*f11= 0,*f12= 0;
526  int i01=-1, i02=-1, i11=-1, i12=-1;
527  // Note that the faux bit is preserved only if both of the edges to be stiched are faux.
528  bool f0Faux = f0->IsF((z0+1)%3) && f0->IsF((z0+2)%3);
529  bool f1Faux = f1->IsF((z1+1)%3) && f1->IsF((z1+2)%3);
530 
531  if(!face::IsBorder(*f0,(z0+1)%3)) { f01 = f0->FFp((z0+1)%3); i01=f0->FFi((z0+1)%3); FFDetachManifold(*f0,(z0+1)%3);}
532  if(!face::IsBorder(*f0,(z0+2)%3)) { f02 = f0->FFp((z0+2)%3); i02=f0->FFi((z0+2)%3); FFDetachManifold(*f0,(z0+2)%3);}
533  if(!face::IsBorder(*f1,(z1+1)%3)) { f11 = f1->FFp((z1+1)%3); i11=f1->FFi((z1+1)%3); FFDetachManifold(*f1,(z1+1)%3);}
534  if(!face::IsBorder(*f1,(z1+2)%3)) { f12 = f1->FFp((z1+2)%3); i12=f1->FFi((z1+2)%3); FFDetachManifold(*f1,(z1+2)%3);}
535 
536  // Final Pass to update the vertex ptrs in all the involved faces
537  for(size_t i=0;i<faceToBeChanged.size();++i) {
538  assert(faceToBeChanged[i].V() == delV);
539  faceToBeChanged[i].F()->V(faceToBeChanged[i].VInd()) =surV;
540  }
541 
542  if(f01 && f02)
543  {
544  FFAttachManifold(f01,i01,f02,i02);
545  if(f0Faux) {f01->SetF(i01); f02->SetF(i02);}
546  }
547  if(f11 && f12) {
548  FFAttachManifold(f11,i11,f12,i12);
549  if(f1Faux) {f11->SetF(i11); f12->SetF(i12);}
550  }
552  if(f1!=f0) tri::Allocator<MeshType>::DeleteFace(m,*f1);
554 }
555 
575 template <class FaceType>
576 bool CheckFlipEdgeNormal(FaceType &f, const int z, const float angleRad)
577 {
578  typedef typename FaceType::VertexType VertexType;
579  typedef typename VertexType::CoordType CoordType;
580 
581  VertexType *OldDiag0 = f.V0(z);
582  VertexType *OldDiag1 = f.V1(z);
583 
584  VertexType *NewDiag0 = f.V2(z);
585  VertexType *NewDiag1 = f.FFp(z)->V2(f.FFi(z));
586 
587  assert((NewDiag1 != NewDiag0) && (NewDiag1 != OldDiag0) && (NewDiag1 != OldDiag1));
588 
589  CoordType oldN0 = Normal( NewDiag0->cP(),OldDiag0->cP(),OldDiag1->cP()).Normalize();
590  CoordType oldN1 = Normal( NewDiag1->cP(),OldDiag1->cP(),OldDiag0->cP()).Normalize();
591  CoordType newN0 = Normal( OldDiag0->cP(),NewDiag1->cP(),NewDiag0->cP()).Normalize();
592  CoordType newN1 = Normal( OldDiag1->cP(),NewDiag0->cP(),NewDiag1->cP()).Normalize();
593  if(AngleN(oldN0,newN0) > angleRad) return false;
594  if(AngleN(oldN0,newN1) > angleRad) return false;
595  if(AngleN(oldN1,newN0) > angleRad) return false;
596  if(AngleN(oldN1,newN1) > angleRad) return false;
597 
598  return true;
599 }
600 
607 template <class FaceType>
608 bool CheckFlipEdge(FaceType &f, int z)
609 {
610  typedef typename FaceType::VertexType VertexType;
611  typedef typename vcg::face::Pos< FaceType > PosType;
612 
613  if (z<0 || z>2) return false;
614 
615  // boundary edges cannot be flipped
616  if (face::IsBorder(f, z)) return false;
617 
618  FaceType *g = f.FFp(z);
619  int w = f.FFi(z);
620 
621  // check if the vertices of the edge are the same
622  // e.g. the mesh has to be well oriented
623  if (g->V(w)!=f.V1(z) || g->V1(w)!=f.V(z) )
624  return false;
625 
626  // check if the flipped edge is already present in the mesh
627  // f_v2 and g_v2 are the vertices of the new edge
628  VertexType *f_v2 = f.V2(z);
629  VertexType *g_v2 = g->V2(w);
630 
631  // just a sanity check. If this happens the mesh is not manifold.
632  if (f_v2 == g_v2) return false;
633 
634  // Now walk around f_v2, one of the two vertexes of the new edge
635  // and check that it does not already exists.
636 
637  PosType pos(&f, (z+2)%3, f_v2);
638  PosType startPos=pos;
639  do
640  {
641  pos.NextE();
642  if (g_v2 == pos.VFlip())
643  return false;
644  }
645  while (pos != startPos);
646 
647  return true;
648 }
649 
650 template <class FaceType>
651 bool checkFlipEdgeNotManifold (FaceType &f, const int z)
652 {
653  typedef typename FaceType::VertexType VertexType;
654  typedef typename vcg::face::Pos< FaceType > PosType;
655  if (z<0 || z>2) return false;
656 
657  // boundary edges cannot be flipped
658  if (vcg::face::IsBorder(f, z)) return false;
659 
660  FaceType *g = f.FFp(z);
661  int w = f.FFi(z);
662 
663  // check if the vertices of the edge are the same
664  // e.g. the mesh has to be well oriented
665  if (g->V(w)!=f.V1(z) || g->V1(w)!=f.V(z) )
666  return false;
667 
668  // check if the flipped edge is already present in the mesh
669  // f_v2 and g_v2 are the vertices of the new edge
670  VertexType *f_v2 = f.V2(z);
671  VertexType *g_v2 = g->V2(w);
672 
673  PosType pos(&f, (z+2)%3, f_v2);
674  PosType startPos=pos;
675  do
676  {
677  pos.FlipE();
678  pos.NextF();
679 // if (g_v2 == pos.F()->V((pos.E()+1) % 3))
680  if (g_v2 == pos.VFlip())
681  return false;
682  }
683  while (pos != startPos);
684 
685  return true;
686 
687 }
688 
713 template <class FaceType>
714 void FlipEdge(FaceType &f, const int z)
715 {
716  assert(z>=0);
717  assert(z<3);
718  assert( !IsBorder(f,z) );
719  assert( face::IsManifold<FaceType>(f, z));
720 
721  FaceType *g = f.FFp(z); // The other face
722  int w = f.FFi(z); // and other side
723 
724  assert( g->V0(w) == f.V1(z) );
725  assert( g->V1(w) == f.V0(z) );
726  assert( g->V2(w) != f.V0(z) );
727  assert( g->V2(w) != f.V1(z) );
728  assert( g->V2(w) != f.V2(z) );
729 
730  f.V1(z) = g->V2(w);
731  g->V1(w) = f.V2(z);
732 
733  //topology update
734 
735 
736  f.FFp(z) = g->FFp((w+1)%3);
737  f.FFi(z) = g->FFi((w+1)%3);
738  g->FFp(w) = f.FFp((z+1)%3);
739  g->FFi(w) = f.FFi((z+1)%3);
740 
741  f.FFp((z+1)%3) = g;
742  f.FFi((z+1)%3) = (w+1)%3;
743  g->FFp((w+1)%3) = &f;
744  g->FFi((w+1)%3) = (z+1)%3;
745 
746  if(f.FFp(z)==g)
747  {
748  f.FFp(z) = &f;
749  f.FFi(z) = z;
750  }
751  else
752  {
753  f.FFp(z)->FFp( f.FFi(z) ) = &f;
754  f.FFp(z)->FFi( f.FFi(z) ) = z;
755  }
756  if(g->FFp(w)==&f)
757  {
758  g->FFp(w)=g;
759  g->FFi(w)=w;
760  }
761  else
762  {
763  g->FFp(w)->FFp( g->FFi(w) ) = g;
764  g->FFp(w)->FFi( g->FFi(w) ) = w;
765  }
766 
767 }
768 
792 template <class FaceType>
793 void FlipEdgeNotManifold(FaceType &f, const int z)
794 {
795  assert(z>=0);
796  assert(z<3);
797  assert( !IsBorder(f,z) );
798  assert( face::IsManifold<FaceType>(f, z));
799 
800  FaceType *g = f.FFp(z); // The other face
801  int w = f.FFi(z); // and other side
802 
803  assert( g->V0(w) == f.V1(z) );
804  assert( g->V1(w) == f.V0(z) );
805  assert( g->V2(w) != f.V0(z) );
806  assert( g->V2(w) != f.V1(z) );
807  assert( g->V2(w) != f.V2(z) );
808 
809  int fi1 = f.FFi(f.Next(z));
810  FaceType* fp1 = f.FFp(f.Next(z));
811 
812  int gi1 = g->FFi(g->Next(w));
813  FaceType* gp1 = g->FFp(g->Next(w));
814 
815 
816  FFDetach(f, z);
817  if (!IsBorder(f, (z+1)%3))
818  FFDetach(f, (z+1)%3);
819  if (!IsBorder(*g, (w+1)%3))
820  FFDetach(*g, (w+1)%3);
821 
822  f.V1(z) = g->V2(w);
823  g->V1(w) = f.V2(z);
824 
825  //topology update
826  FaceType* ftmp = &f;
827 
828  if (gp1 != g)
829  FFAttach(f, z, *gp1, gi1);
830  if (fp1 != &f)
831  FFAttach(*g, w, *fp1, fi1);
832 
833  FFAttachManifold(ftmp, (z+1)%3, g, (w+1)%3);
834 }
835 
841 template <class FaceType>
842 void TriSplit(FaceType *fToSplit, FaceType *newf0, FaceType *newf1, typename FaceType::VertexType *newVert)
843 {
844  typedef typename FaceType::VertexType VertexType;
845 
846  VertexType *vp0 = fToSplit->V(0);
847  VertexType *vp1 = fToSplit->V(1);
848  VertexType *vp2 = fToSplit->V(2);
849 
850  fToSplit->V(0) = vp0; fToSplit->V(1) = vp1; fToSplit->V(2) = newVert;
851  newf0->V(0) = vp1; newf0->V(1) = vp2; newf0->V(2) = newVert;
852  newf1->V(0) = vp2; newf1->V(1) = vp0; newf1->V(2) = newVert;
853 }
854 
861 template <class FaceType>
862 void VFDetach(FaceType & f)
863 {
864  VFDetach(f,0);
865  VFDetach(f,1);
866  VFDetach(f,2);
867 }
868 
875 template <class FaceType>
876 void VFDetach(FaceType & f, int z)
877 {
878  if(f.V(z)->VFp()==&f ) // if it is the first face detach from the begin
879  {
880  int fz = f.V(z)->VFi();
881  f.V(z)->VFp() = f.VFp(fz);
882  f.V(z)->VFi() = f.VFi(fz);
883  }
884  else // scan the list of faces in order to find the current face f to be detached
885  {
886  VFIterator<FaceType> x(f.V(z)->VFp(),f.V(z)->VFi());
887  VFIterator<FaceType> y;
888 
889  for(;;)
890  {
891  y = x;
892  ++x;
893  assert(x.f!=0);
894  if(x.f==&f) // found!
895  {
896  y.f->VFp(y.z) = f.VFp(z);
897  y.f->VFi(y.z) = f.VFi(z);
898  break;
899  }
900  }
901  }
902 }
903 
905 template <class FaceType>
906 void VFAppend(FaceType * f, int z)
907 {
908  typename FaceType::VertexType *v = f->V(z);
909  if (v->VFp()!=0)
910  {
911  FaceType *f0=v->VFp();
912  int z0=v->VFi();
913  //append
914  f->VFp(z)=f0;
915  f->VFi(z)=z0;
916  }
917  v->VFp()=f;
918  v->VFi()=z;
919 }
920 
929 template <class FaceType>
930 void VVStarVF( typename FaceType::VertexType* vp, std::vector<typename FaceType::VertexType *> &starVec)
931 {
932  typedef typename FaceType::VertexType* VertexPointer;
933  starVec.clear();
934  starVec.reserve(16);
935  face::VFIterator<FaceType> vfi(vp);
936  while(!vfi.End())
937  {
938  const int vn = vfi.F()->VN();
939  starVec.push_back(vfi.F()->V1(vfi.I()));
940  starVec.push_back(vfi.F()->V((vfi.I()+vn-1)%vn));
941  ++vfi;
942  }
943 
944  std::sort(starVec.begin(),starVec.end());
945  typename std::vector<VertexPointer>::iterator new_end = std::unique(starVec.begin(),starVec.end());
946  starVec.resize(new_end-starVec.begin());
947 }
948 
957 template <class FaceType>
958 void VVExtendedStarVF(typename FaceType::VertexType* vp,
959  const int num_step,
960  std::vector<typename FaceType::VertexType *> &vertVec)
961  {
962  typedef typename FaceType::VertexType VertexType;
964  vertVec.clear();
965  vcg::face::VVStarVF<FaceType>(vp,vertVec);
968  for (int step=0;step<num_step-1;step++)
969  {
970  std::vector<VertexType *> toAdd;
971  for (unsigned int i=0;i<vertVec.size();i++)
972  {
973  std::vector<VertexType *> Vtemp;
974  vcg::face::VVStarVF<FaceType>(vertVec[i],Vtemp);
975  toAdd.insert(toAdd.end(),Vtemp.begin(),Vtemp.end());
976  }
977  vertVec.insert(vertVec.end(),toAdd.begin(),toAdd.end());
978  std::sort(vertVec.begin(),vertVec.end());
979  typename std::vector<typename FaceType::VertexType *>::iterator new_end=std::unique(vertVec.begin(),vertVec.end());
980  int dist=distance(vertVec.begin(),new_end);
981  vertVec.resize(dist);
982  }
983  }
984 
992 template <class FaceType>
993 void VFStarVF( typename FaceType::VertexType* vp,
994  std::vector<FaceType *> &faceVec,
995  std::vector<int> &indexes)
996 {
997  faceVec.clear();
998  indexes.clear();
999  faceVec.reserve(16);
1000  indexes.reserve(16);
1001  face::VFIterator<FaceType> vfi(vp);
1002  while(!vfi.End())
1003  {
1004  faceVec.push_back(vfi.F());
1005  indexes.push_back(vfi.I());
1006  ++vfi;
1007  }
1008 }
1009 
1010 
1019 template <class FaceType>
1020 void EFStarFF( FaceType* fp, int ei,
1021  std::vector<FaceType *> &faceVec,
1022  std::vector<int> &indVed)
1023 {
1024  assert(fp->FFp(ei)!=0);
1025  faceVec.clear();
1026  indVed.clear();
1027  FaceType* fpit=fp;
1028  int eit=ei;
1029  do
1030  {
1031  faceVec.push_back(fpit);
1032  indVed.push_back(eit);
1033  FaceType *new_fpit = fpit->FFp(eit);
1034  int new_eit = fpit->FFi(eit);
1035  fpit=new_fpit;
1036  eit=new_eit;
1037  } while(fpit != fp);
1038 }
1039 
1040 
1041  /* Compute the set of faces adjacent to a given face using FF adjacency.
1042  * The set is faces is extended of a given number of step
1043  * \param fp pointer to the face whose star has to be computed.
1044  * \param num_step the number of step to extend the star
1045  * \param faceVec a std::vector of Face pointer that is filled with the adjacent faces.
1046  */
1047  template <class FaceType>
1048  static void FFExtendedStarFF(FaceType *fp,
1049  const int num_step,
1050  std::vector<FaceType*> &faceVec)
1051  {
1053  faceVec.push_back(fp);
1056  for (int step=0;step<num_step;step++)
1057  {
1058  std::vector<FaceType*> toAdd;
1059  for (unsigned int i=0;i<faceVec.size();i++)
1060  {
1061  FaceType *f=faceVec[i];
1062  for (int k=0;k<3;k++)
1063  {
1064  FaceType *f1=f->FFp(k);
1065  if (f1==f)continue;
1066  toAdd.push_back(f1);
1067  }
1068  }
1069  faceVec.insert(faceVec.end(),toAdd.begin(),toAdd.end());
1070  std::sort(faceVec.begin(),faceVec.end());
1071  typename std::vector<FaceType*>::iterator new_end=std::unique(faceVec.begin(),faceVec.end());
1072  int dist=distance(faceVec.begin(),new_end);
1073  faceVec.resize(dist);
1074  }
1075  }
1076 
1085 template <class FaceType>
1086 void VFExtendedStarVF(typename FaceType::VertexType* vp,
1087  const int num_step,
1088  std::vector<FaceType*> &faceVec)
1089  {
1091  faceVec.clear();
1092  std::vector<int> indexes;
1093  vcg::face::VFStarVF<FaceType>(vp,faceVec,indexes);
1096  for (int step=0;step<num_step;step++)
1097  {
1098  std::vector<FaceType*> toAdd;
1099  for (unsigned int i=0;i<faceVec.size();i++)
1100  {
1101  FaceType *f=faceVec[i];
1102  for (int k=0;k<3;k++)
1103  {
1104  FaceType *f1=f->FFp(k);
1105  if (f1==f)continue;
1106  toAdd.push_back(f1);
1107  }
1108  }
1109  faceVec.insert(faceVec.end(),toAdd.begin(),toAdd.end());
1110  std::sort(faceVec.begin(),faceVec.end());
1111  typename std::vector<FaceType*>::iterator new_end=std::unique(faceVec.begin(),faceVec.end());
1112  int dist=distance(faceVec.begin(),new_end);
1113  faceVec.resize(dist);
1114  }
1115  }
1116 
1124 template <class FaceType>
1125 void VVOrderedStarFF(const Pos<FaceType> &startPos,
1126  std::vector<typename FaceType::VertexType *> &vertexVec)
1127 {
1128  vertexVec.clear();
1129  vertexVec.reserve(16);
1130  std::vector<Pos<FaceType> > posVec;
1131  VFOrderedStarFF(startPos,posVec);
1132  for(size_t i=0;i<posVec.size();++i)
1133  vertexVec.push_back(posVec[i].VFlip());
1134 }
1135 
1144 template <class FaceType>
1145 void VVOrderedStarFF(const Pos<FaceType> &startPos,
1146  std::vector<typename FaceType::VertexType *> &vertexVec,
1147  const bool ccw)
1148 {
1149  vertexVec.clear();
1150  vertexVec.reserve(16);
1151  std::vector<Pos<FaceType> > posVec;
1152  VFOrderedStarFF(startPos,posVec,ccw);
1153  for(size_t i=0;i<posVec.size();++i)
1154  vertexVec.push_back(posVec[i].VFlip());
1155 }
1156 
1164 template <class FaceType>
1165 void VFOrderedStarFF(const Pos<FaceType> &startPos,
1166  std::vector<Pos<FaceType> > &posVec)
1167 {
1168  posVec.clear();
1169  posVec.reserve(16);
1170  bool foundBorder=false;
1171  size_t firstBorderInd;
1172  Pos<FaceType> curPos=startPos;
1173  do
1174  {
1175  assert(curPos.IsManifold());
1176  if(curPos.IsBorder() && !foundBorder) {
1177  foundBorder=true;
1178  firstBorderInd = posVec.size();
1179  }
1180  posVec.push_back(curPos);
1181  curPos.FlipF();
1182  curPos.FlipE();
1183  } while(curPos!=startPos);
1184  // if we found a border we visited each face exactly twice,
1185  // and we have to extract the border-to-border pos sequence
1186  if(foundBorder)
1187  {
1188  size_t halfSize=posVec.size()/2;
1189  assert((posVec.size()%2)==0);
1190  posVec.erase(posVec.begin()+firstBorderInd+1+halfSize, posVec.end());
1191  posVec.erase(posVec.begin(),posVec.begin()+firstBorderInd+1);
1192  assert(posVec.size()==halfSize);
1193  }
1194 }
1195 
1204 template <class FaceType>
1205 void VFOrderedStarFF(const Pos<FaceType> &startPos,
1206  std::vector<Pos<FaceType> > &posVec,
1207  const bool ccw)
1208 {
1209  VFOrderedStarFF(startPos, posVec);
1210  const auto & pos = posVec[0];
1211  //if (ccw != (pos.VFlip() == pos.F()->V(pos.F()->Prev(pos.VInd()))))
1212  if ((ccw) == (pos.V()!=pos.F()->V(pos.E())))
1213  {
1214  std::reverse(posVec.begin(), posVec.end());
1215  }
1216 }
1217 
1227 template <class FaceType>
1228 void VFOrderedStarFF(const Pos<FaceType> &startPos,
1229  std::vector<FaceType*> &faceVec,
1230  std::vector<int> &edgeVec)
1231 {
1232  std::vector<Pos<FaceType> > posVec;
1233  VFOrderedStarFF(startPos,posVec);
1234  faceVec.clear();
1235  edgeVec.clear();
1236  faceVec.reserve(16);
1237  edgeVec.reserve(16);
1238  for(size_t i=0;i<posVec.size();++i)
1239  {
1240  faceVec.push_back(posVec[i].F());
1241  edgeVec.push_back(posVec[i].E());
1242  }
1243 }
1244 
1251 template <class FaceType>
1252 bool ShareEdgeFF(FaceType *f0,FaceType *f1, int *i0=0, int *i1=0)
1253 {
1254  assert((!f0->IsD())&&(!f1->IsD()));
1255  for (int i=0;i<3;i++)
1256  if (f0->FFp(i)==f1)
1257  {
1258  if((i0!=0) && (i1!=0)) {
1259  *i0=i;
1260  *i1=f0->FFi(i);
1261  }
1262  return true;
1263  }
1264  return false;
1265 }
1266 
1272 template <class FaceType>
1273 int CountSharedVertex(FaceType *f0,FaceType *f1)
1274 {
1275  int sharedCnt=0;
1276  for (int i=0;i<3;i++)
1277  for (int j=0;j<3;j++)
1278  if (f0->V(i)==f1->V(j)) {
1279  sharedCnt++;
1280  }
1281  return sharedCnt;
1282 }
1283 
1290 template <class FaceType>
1291 bool FindSharedVertex(FaceType *f0,FaceType *f1, int &i, int &j)
1292 {
1293  for (i=0;i<3;i++)
1294  for (j=0;j<3;j++)
1295  if (f0->V(i)==f1->V(j)) return true;
1296 
1297  i=-1;j=-1;
1298  return false;
1299 }
1300 
1307 template <class FaceType>
1308 bool FindSharedEdge(FaceType *f0,FaceType *f1, int &i, int &j)
1309 {
1310  for (i=0;i<3;i++)
1311  for (j=0;j<3;j++)
1312  if( ( f0->V0(i)==f1->V0(j) || f0->V0(i)==f1->V1(j) ) &&
1313  ( f0->V1(i)==f1->V0(j) || f0->V1(i)==f1->V1(j) ) )
1314  return true;
1315  i=-1;j=-1;
1316  return false;
1317 }
1318 
1325 template <class FaceType>
1326 bool FindSharedFaces(typename FaceType::VertexType *v0,
1327  typename FaceType::VertexType *v1,
1328  FaceType *&f0,
1329  FaceType *&f1,
1330  int &e0,
1331  int &e1)
1332 {
1333  std::vector<FaceType*> faces0;
1334  std::vector<FaceType*> faces1;
1335  std::vector<int> index0;
1336  std::vector<int> index1;
1337  VFStarVF<FaceType>(v0,faces0,index0);
1338  VFStarVF<FaceType>(v1,faces1,index1);
1340  std::sort(faces0.begin(),faces0.end());
1341  std::sort(faces1.begin(),faces1.end());
1342  std::vector<FaceType*> Intersection;
1343  std::set_intersection(faces0.begin(),faces0.end(),faces1.begin(),faces1.end(),std::back_inserter(Intersection));
1344  if (Intersection.size()<2)return false; // no pair of faces share the 2 vertices
1345  assert(Intersection.size()==2); // otherwise non manifoldness
1346  f0=Intersection[0];
1347  f1=Intersection[1];
1348  FindSharedEdge(f0,f1,e0,e1);
1349  // and finally check if the order is right
1350  if (f0->V(e0)!=v0)
1351  {
1352  std::swap(f0,f1);
1353  std::swap(e0,e1);
1354  }
1355  return true;
1356 }
1357 
1359 } // end namespace
1360 } // end namespace
1361 
1362 #endif
1363 
static void DeleteFace(MeshType &m, FaceType &f)
Definition: allocate.h:923
static void DeleteVertex(MeshType &m, VertexType &v)
Definition: allocate.h:935
int ComplexSize(FaceType &f, const int e)
Counts the number of incident faces in a complex edge.
Definition: topology.h:144
void FlipEdgeNotManifold(FaceType &f, const int z)
Definition: topology.h:793
void TriSplit(FaceType *fToSplit, FaceType *newf0, FaceType *newf1, typename FaceType::VertexType *newVert)
Definition: topology.h:842
FaceType::ScalarType WedgeAngleRad(FaceType &f, const int i)
Return the internal angle (in radians) of the i-th wedge of the triangle.
Definition: topology.h:118
bool IsManifold(FaceType const &f, const int j)
Definition: topology.h:41
void FFAttachManifold(FaceType *f1, int z1, FaceType *f2, int z2)
Definition: topology.h:339
void VFExtendedStarVF(typename FaceType::VertexType *vp, const int num_step, std::vector< FaceType * > &faceVec)
Compute the set of faces adjacent to a given vertex using VF adjacency.
Definition: topology.h:1086
void EFStarFF(FaceType *fp, int ei, std::vector< FaceType * > &faceVec, std::vector< int > &indVed)
Compute the set of faces incident onto a given edge using FF adjacency.
Definition: topology.h:1020
int CountSharedVertex(FaceType *f0, FaceType *f1)
Definition: topology.h:1273
bool IsBorder(FaceType const &f, const int j)
Definition: topology.h:55
FaceType::ScalarType DihedralAngleRad(FaceType &f, const int i)
Compute the signed dihedral angle between the normals of two adjacent faces.
Definition: topology.h:84
void VVOrderedStarFF(const Pos< FaceType > &startPos, std::vector< typename FaceType::VertexType * > &vertexVec)
Compute the ordered set of vertices adjacent to a given vertex using FF adjacency.
Definition: topology.h:1125
bool CheckOrientation(FaceType &f, int z)
Definition: topology.h:380
void VVStarVF(typename FaceType::VertexType *vp, std::vector< typename FaceType::VertexType * > &starVec)
Compute the set of vertices adjacent to a given vertex using VF adjacency.
Definition: topology.h:930
void VFDetach(FaceType &f)
Definition: topology.h:862
void FFDetachManifold(FaceType &f, const int e)
Definition: topology.h:220
void SwapEdge(FaceType &f, const int z)
Definition: topology.h:402
bool CheckFlipEdge(FaceType &f, int z)
Definition: topology.h:608
bool FFCorrectness(FaceType &f, const int e)
Definition: topology.h:177
bool FindSharedFaces(typename FaceType::VertexType *v0, typename FaceType::VertexType *v1, FaceType *&f0, FaceType *&f1, int &e0, int &e1)
Definition: topology.h:1326
bool ShareEdgeFF(FaceType *f0, FaceType *f1, int *i0=0, int *i1=0)
Definition: topology.h:1252
void FlipEdge(FaceType &f, const int z)
Definition: topology.h:714
void VFAppend(FaceType *f, int z)
Append a face in VF list of vertex f->V(z)
Definition: topology.h:906
bool FindSharedEdge(FaceType *f0, FaceType *f1, int &i, int &j)
Definition: topology.h:1308
void VVExtendedStarVF(typename FaceType::VertexType *vp, const int num_step, std::vector< typename FaceType::VertexType * > &vertVec)
Compute the set of vertices adjacent to a given vertex using VF adjacency.
Definition: topology.h:958
bool FindSharedVertex(FaceType *f0, FaceType *f1, int &i, int &j)
Definition: topology.h:1291
void FFEdgeCollapse(MeshType &m, typename MeshType::FaceType &f, const int z)
a simple edge collapse using only FF adjacency
Definition: topology.h:506
void FFDetach(FaceType &f, const int e)
Definition: topology.h:250
bool CheckFlipEdgeNormal(FaceType &f, const int z, const float angleRad)
Definition: topology.h:576
void VFStarVF(typename FaceType::VertexType *vp, std::vector< FaceType * > &faceVec, std::vector< int > &indexes)
Compute the set of faces adjacent to a given vertex using VF adjacency.
Definition: topology.h:993
int BorderCount(FaceType const &f)
Count border edges of the face.
Definition: topology.h:128
void VFOrderedStarFF(const Pos< FaceType > &startPos, std::vector< Pos< FaceType > > &posVec)
Compute the ordered set of faces adjacent to a given vertex using FF adjacency.
Definition: topology.h:1165
void FFAttach(FaceType &f, int z1, FaceType &f2, int z2)
Definition: topology.h:305
bool FFLinkCondition(FaceType &f, const int z)
Definition: topology.h:460
Definition: namespaces.dox:6