VCG Library
Loading...
Searching...
No Matches
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
31namespace vcg {
32namespace face {
35
40template <class FaceType>
41inline 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
54template <class FaceType>
55inline 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
83template <class FaceType>
84inline 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
117template <class FaceType>
118inline 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
127template <class FaceType>
128inline 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
143template <class FaceType>
144inline 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
176template <class FaceType>
177bool 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
219template <class FaceType>
220void 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
249template <class FaceType>
250void 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
304template <class FaceType>
305void 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
338template <class FaceType>
339void 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.
352template <class FaceType>
353void 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
361template <class FaceType>
362void 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
379template <class FaceType>
380bool 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
401template <class FaceType>
402void SwapEdge(FaceType &f, const int z) { SwapEdge<FaceType,true>(f,z); }
403
404template <class FaceType, bool UpdateTopology>
405void 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
459template <class FaceType>
460bool 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
505template <class MeshType>
506void 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
575template <class FaceType>
576bool 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
607template <class FaceType>
608bool 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
650template <class FaceType>
651bool 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
713template <class FaceType>
714void 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
792template <class FaceType>
793void 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
841template <class FaceType>
842void 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
861template <class FaceType>
862void VFDetach(FaceType & f)
863{
864 VFDetach(f,0);
865 VFDetach(f,1);
866 VFDetach(f,2);
867}
868
875template <class FaceType>
876void 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
905template <class FaceType>
906void 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
929template <class FaceType>
930void 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
957template <class FaceType>
958void 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
992template <class FaceType>
993void 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
1019template <class FaceType>
1020void 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
1085template <class FaceType>
1086void 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
1124template <class FaceType>
1125void 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
1144template <class FaceType>
1145void 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
1164template <class FaceType>
1165void 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
1204template <class FaceType>
1205void 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
1227template <class FaceType>
1228void 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
1251template <class FaceType>
1252bool 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
1272template <class FaceType>
1273int 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
1290template <class FaceType>
1291bool 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
1307template <class FaceType>
1308bool 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
1326template <class FaceType>
1327bool FindSharedFaces(typename FaceType::VertexType *v0,
1328 typename FaceType::VertexType *v1,
1329 FaceType *&f0,
1330 FaceType *&f1,
1331 int &e0,
1332 int &e1)
1333{
1334 std::vector<FaceType*> faces0;
1335 std::vector<FaceType*> faces1;
1336 std::vector<int> index0;
1337 std::vector<int> index1;
1338 VFStarVF<FaceType>(v0,faces0,index0);
1339 VFStarVF<FaceType>(v1,faces1,index1);
1341 std::sort(faces0.begin(),faces0.end());
1342 std::sort(faces1.begin(),faces1.end());
1343 std::vector<FaceType*> Intersection;
1344 std::set_intersection(faces0.begin(),faces0.end(),faces1.begin(),faces1.end(),std::back_inserter(Intersection));
1345 if (Intersection.size()<2)return false; // no pair of faces share the 2 vertices
1346 assert(Intersection.size()==2); // otherwise non manifoldness
1347 f0=Intersection[0];
1348 f1=Intersection[1];
1349 FindSharedEdge(f0,f1,e0,e1);
1350 // and finally check if the order is right
1351 if (f0->V(e0)!=v0)
1352 {
1353 std::swap(f0,f1);
1354 std::swap(e0,e1);
1355 }
1356 return true;
1357}
1358
1360} // end namespace
1361} // end namespace
1362
1363#endif
1364
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:1327
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: color4.h:30