00001 #ifndef VCG_BITQUAD_SUPPORT
00002 #define VCG_BITQUAD_SUPPORT
00003 #include <vector>
00004 #include <vcg/complex/trimesh/subset.h>
00005 #include <vcg/simplex/face/jumping_pos.h>
00006 #include <vcg/space/planar_polygon_tessellation.h>
00007
00053
00054 #define DELETE_VERTICES 1
00055
00056
00057
00058
00059
00060 #define LENGTH_CRITERION 1
00061
00062 namespace vcg{namespace tri{
00063
00064
00065
00066 template <class VertexType>
00067 class GeometricInterpolator{
00068 public:
00069 typedef typename VertexType::ScalarType ScalarType;
00070 static void Apply( const VertexType &a, const VertexType &b, ScalarType t, VertexType &res){
00071
00072 res.P() = a.P()*(1-t) + b.P()*(t);
00073 if (a.IsB()||b.IsB()) res.SetB();
00074 }
00075 };
00076
00077 template <
00078
00079 class _MeshType,
00080
00081 class Interpolator = GeometricInterpolator<typename _MeshType::VertexType>
00082 >
00083 class BitQuad{
00084 public:
00085
00086 typedef _MeshType MeshType;
00087 typedef typename MeshType::ScalarType ScalarType;
00088 typedef typename MeshType::CoordType CoordType;
00089 typedef typename MeshType::FaceType FaceType;
00090 typedef typename MeshType::FaceType* FaceTypeP;
00091 typedef typename MeshType::VertexType VertexType;
00092 typedef typename MeshType::FaceIterator FaceIterator;
00093 typedef typename MeshType::VertexIterator VertexIterator;
00094
00095 class Pos{
00096 FaceType *f;
00097 int e;
00098 public:
00099 enum{ PAIR, AROUND , NOTHING } mode;
00100 FaceType* &F(){return f;}
00101 FaceType* F() const {return f;}
00102 VertexType* V() {return f->V(e);}
00103 const VertexType* cV() const {return f->V(e);}
00104 int& E(){return e;}
00105 int E() const {return e;}
00106
00107
00108 Pos(){ f=NULL; e=0; mode=AROUND;}
00109
00110 Pos(FaceType* _f, int _e){f=_f; e=_e;}
00111 Pos NextE()const {return Pos(f, (e+1)%3); }
00112 Pos PrevE(){return Pos(f, (e+2)%3); }
00113 bool IsF(){return f->IsF(e);}
00114 Pos FlipF(){return Pos(f->FFp(e), f->FFi(e)); }
00115
00116 };
00117
00118
00119
00120 static void MarkFaceF(FaceType *f){
00121 f->V(0)->SetS();
00122 f->V(1)->SetS();
00123 f->V(2)->SetS();
00124 int i=FauxIndex(f);
00125 f->FFp( i )->V2( f->FFi(i) )->SetS();
00126 f->V(0)->SetV();
00127 f->V(1)->SetV();
00128 f->V(2)->SetV();
00129 f->FFp( i )->V2( f->FFi(i) )->SetV();
00130 }
00131
00132
00133 template <bool verse>
00134 static bool RotateEdge(FaceType& f, int w0a, MeshType &m, Pos *affected=NULL){
00135 FaceType *fa = &f;
00136 assert(! fa->IsF(w0a) );
00137
00138 VertexType *v0, *v1;
00139 v0= fa->V0(w0a);
00140 v1= fa->V1(w0a);
00141
00142 int w1a = (w0a+1)%3;
00143 int w2a = (w0a+2)%3;
00144
00145 FaceType *fb = fa->FFp(w0a);
00146
00147 MarkFaceF(fa);
00148 MarkFaceF(fb);
00149
00150 int w0b = fa->FFi(w0a);
00151 int w1b = (w0b+1)%3;
00152 int w2b = (w0b+2)%3;
00153
00154 if (fa->IsF(w2a) == verse) {
00155 if (!CheckFlipDiag(*fa)) return false;
00156 FlipDiag(*fa);
00157
00158 fa = fb->FFp(w0b);
00159 w0a = fb->FFi(w0b);
00160 }
00161
00162 if (fb->IsF(w2b) == verse) {
00163 if (!CheckFlipDiag(*fb)) return false;
00164 FlipDiag(*fb);
00165 }
00166
00167 if (!CheckFlipEdge(*fa,w0a)) return false;
00168 FlipEdge(*fa,w0a,m);
00169 if (affected) {
00170 affected->F() = fa;
00171 affected->E() = (FauxIndex(fa)+2)%3;
00172 affected->mode = Pos::PAIR;
00173 }
00174 return true;
00175 }
00176
00177
00178
00179
00180 static int FauxIndex(const FaceType* f){
00181 if (f->IsF(0)) return 0;
00182 if (f->IsF(1)) return 1;
00183 assert(f->IsF(2));
00184 return 2;
00185 }
00186
00187
00188 static void FlipDiag(FaceType &f){
00189 int faux = FauxIndex(&f);
00190 FaceType* fa = &f;
00191 FaceType* fb = f.FFp(faux);
00192 vcg::face::FlipEdge(f, faux);
00193
00194 fb->ClearAllF();
00195 fa->ClearAllF();
00196 for (int k=0; k<3; k++) {
00197 if (fa->FFp(k) == fb) fa->SetF(k);
00198 if (fb->FFp(k) == fa) fb->SetF(k);
00199 }
00200 }
00201
00202
00203
00204
00205
00206 static ScalarType EdgeLenghtVariationIfVertexRotated(const FaceType &f, int w0)
00207 {
00208 assert(!f.IsD());
00209
00210 ScalarType
00211 before=0,
00212 after=0;
00213 int guard = 0;
00214
00215
00216 const FaceType* pf = &f;
00217 int pi = w0;
00218 int n = 0;
00219 int na = 0;
00220 do {
00221 ScalarType triEdge = (pf->P0(pi) - pf->P1(pi) ).Norm();
00222 if (pf->IsF(pi)) { after += triEdge; na++;}
00223 else { before+= triEdge; n++; }
00224 if ( pf->IsF((pi+1)%3)) { after += CounterDiag( pf ).Norm(); na++; }
00225
00226 const FaceType *t = pf;
00227 t = pf->FFp( pi );
00228 if (pf == t ) return std::numeric_limits<ScalarType>::max();
00229 pi = pf->cFFi( pi );
00230 pi = (pi+1)%3;
00231 pf = t;
00232 assert(guard++<100);
00233 } while (pf != &f);
00234 assert (na == n);
00235 return (after-before);
00236 }
00237
00238
00239
00240
00241 static ScalarType QuadQualityVariationIfVertexRotated(const FaceType &f, int w0)
00242 {
00243 assert(!f.IsD());
00244
00245 ScalarType
00246 before=0,
00247 after=0;
00248 int guard = 0;
00249
00250
00251 const FaceType* pf = &f;
00252 int pi = w0;
00253 int nb = 0;
00254 int na = 0;
00255 std::vector<const VertexType *> s;
00256 do {
00257
00258 if (!pf->IsF(pi)) {
00259 if ( pf->IsF((pi+1)%3)) {
00260 s.push_back(pf->cFFp((pi+1)%3)->V2( pf->cFFi((pi+1)%3) ));
00261 } else {
00262 s.push_back( pf->V2(pi) );
00263 }
00264
00265 s.push_back( pf->V1(pi) );
00266 }
00267
00268 const FaceType *t = pf;
00269 t = pf->FFp( pi );
00270 if (pf == t ) return std::numeric_limits<ScalarType>::max();
00271 pi = pf->cFFi( pi );
00272 pi = (pi+1)%3;
00273 pf = t;
00274 assert(guard++<100);
00275 } while (pf != &f);
00276
00277 assert(s.size()%2==0);
00278 int N = s.size();
00279 for (int i=0; i<N; i+=2) {
00280 int h = (i+N-1)%N;
00281 int j = (i +1)%N;
00282 int k = (i +2)%N;
00283 before+= quadQuality( s[i]->P(),s[j]->P(),s[k]->P(),f.P(w0) );
00284 after+=quadQuality( s[h]->P(),s[i]->P(),s[j]->P(),f.P(w0) );
00285 }
00286
00287 assert (na == nb);
00288 return (after-before);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 static bool TestVertexRotation(const FaceType &f, int w0)
00312 {
00313 assert(!f.IsD());
00314
00315 #if (LENGTH_CRITERION)
00316
00317 return EdgeLenghtVariationIfVertexRotated(f,w0)<0;
00318 #else
00319
00320 #endif
00321 return QuadQualityVariationIfVertexRotated(f,w0)<0;
00322 }
00323
00324
00325 static bool RotateVertex(FaceType &f, int w0, MeshType &m, Pos *affected=NULL)
00326 {
00327
00328 int guard = 0;
00329
00330 FaceType* pf = &f;
00331 int pi = w0;
00332 int n = 0;
00333
00334 if (pf->IsF((pi+2) % 3)) {
00335 pi = (pi+2)%3;
00336
00337 int tmp = pf->FFi(pi); pf = pf->FFp(pi); pi = tmp;
00338 }
00339
00340 const FaceType* stopA = pf;
00341 const FaceType* stopB = pf->FFp(FauxIndex(pf));
00342
00343
00344 do {
00345 bool mustFlip;
00346 if (pf->IsF(pi)) {
00347
00348 int tmp = (pf->FFi(pi)+1)%3; pf = pf->FFp(pi); pi = tmp;
00349 mustFlip = false;
00350 }
00351 else {
00352 mustFlip = true;
00353 }
00354
00355 FaceType *lastF = pf;
00356
00357 int tmp = (pf->FFi(pi)+1)%3; pf = pf->FFp(pi); pi = tmp;
00358
00359 if (mustFlip) {
00360 if (!CheckFlipDiag(*lastF)) return false;
00361 FlipDiag(*lastF);
00362 }
00363 MarkFaceF(pf);
00364 } while (pf != stopA && pf!= stopB);
00365
00366
00367 stopA=pf;
00368 do {
00369 int j = pi;
00370 if (pf->IsF(j))
00371 { pf->ClearF(j); IncreaseValency(pf->V1(j)); }
00372 else
00373 { pf->SetF(j); DecreaseValencySimple(pf->V1(j),1); }
00374
00375 j = (j+2)%3;
00376 if (pf->IsF(j)) pf->ClearF(j); else pf->SetF(j);
00377 int tmp = (pf->FFi(pi)+1)%3; pf = pf->FFp(pi); pi = tmp;
00378 } while (pf != stopA );
00379
00380 if (affected) {
00381 affected->F() = pf;
00382 affected->E()=pi;
00383 }
00384 return true;
00385 }
00386
00387
00388
00389
00390
00391
00392 static void FlipEdge(FaceType &f, int k, MeshType &m){
00393 assert(!f.IsF(k));
00394 FaceType* fa = &f;
00395 FaceType* fb = f.FFp(k);
00396 assert(fa!=fb);
00397
00398
00399 FaceType* fa2 = fa->FFp( FauxIndex(fa) );
00400 FaceType* fb2 = fb->FFp( FauxIndex(fb) );
00401
00402 IncreaseValency( fa->V2(k) );
00403 IncreaseValency( fb->V2(f.FFi(k)) );
00404
00405
00406 DecreaseValency(fa, k ,m);
00407 DecreaseValency(fa,(k+1)%3,m );
00408
00409
00410 vcg::face::FlipEdge(*fa, k);
00411
00412
00413 fb->ClearAllF();
00414 fa->ClearAllF();
00415 for (int k=0; k<3; k++) {
00416
00417
00418 if (fa->FFp(k)->IsF( fa->FFi(k) )) fa->SetF(k);
00419 if (fb->FFp(k)->IsF( fb->FFi(k) )) fb->SetF(k);
00420 }
00421
00422 }
00423
00424
00425 static bool CheckFlipDiag(FaceType &f){
00426 return (vcg::face::CheckFlipEdge(f, FauxIndex(&f) ) );
00427 }
00428
00429
00430 static CoordType Diag(const FaceType* f){
00431 int i = FauxIndex(f);
00432 return f->P1( i ) - f->P0( i );
00433 }
00434
00435
00436
00437 static CoordType CounterDiag(const FaceType* f){
00438 int i = FauxIndex(f);
00439 return f->cP2( i ) - f->cFFp( i )->cP2(f->cFFi(i) ) ;
00440 }
00441
00442
00443
00444
00445 static void _CollapseDiagHalf(FaceType &f, int faux, MeshType& m)
00446 {
00447 int faux1 = (faux+1)%3;
00448 int faux2 = (faux+2)%3;
00449
00450 FaceType* fA = f.FFp( faux1 );
00451 FaceType* fB = f.FFp( faux2 );
00452
00453 MarkFaceF(fA);
00454 MarkFaceF(fB);
00455
00456 int iA = f.FFi( faux1 );
00457 int iB = f.FFi( faux2 );
00458
00459 if (fA==&f && fB==&f) {
00460
00461
00462
00463 } else {
00464 if (fA==&f) {
00465 fB->FFp(iB) = fB; fB->FFi(iB) = iB;
00466 } else {
00467 fB->FFp(iB) = fA; fB->FFi(iB) = iA;
00468 }
00469
00470 if (fB==&f) {
00471 fA->FFp(iA) = fA; fA->FFi(iA) = iA;
00472 } else {
00473 fA->FFp(iA) = fB; fA->FFi(iA) = iB;
00474 }
00475 }
00476
00477
00478
00479
00480
00481 }
00482
00483 static void RemoveDoublet(FaceType &f, int wedge, MeshType& m, Pos* affected=NULL){
00484 if (f.IsF((wedge+1)%3) ) {
00485 VertexType *v = f.V(wedge);
00486 FlipDiag(f);
00487
00488 if (f.V(0)==v) wedge = 0;
00489 else if (f.V(1)==v) wedge = 1;
00490 else {
00491 assert(f.V(2)==v);
00492 wedge = 2;
00493 }
00494 }
00495 ScalarType k=(f.IsF(wedge))?1:0;
00496 CollapseDiag(f, k, m, affected);
00497 VertexType *v = f.V(wedge);
00498 }
00499
00500 static void RemoveSinglet(FaceType &f, int wedge, MeshType& m, Pos* affected=NULL){
00501 if (affected) affected->mode = Pos::NOTHING;
00502
00503 if (f.V(wedge)->IsB()) return;
00504
00505 FaceType *fa, *fb;
00506 FaceType *fc, *fd;
00507 fa = & f;
00508 fb = fa->FFp(wedge);
00509 int wa0 = wedge;
00510 int wa1 = (wa0+1)%3 ;
00511 int wa2 = (wa0+2)%3 ;
00512 int wb0 = (fa->FFi(wa0)+1)%3;
00513 int wb1 = (wb0+1)%3 ;
00514 int wb2 = (wb0+2)%3 ;
00515 assert (fb == fa->FFp( wa2 ) );
00516
00517
00518 DecreaseValency(fa, wa1, m);
00519 DecreaseValency(fa, wa2, m);
00520 if (fa->IsF(wa0)) {
00521 DecreaseValency(fa,wa2,m);
00522 } else {
00523 DecreaseValency(fa,wa1,m);
00524 }
00525
00526
00527
00528 fc = fa->FFp(wa1);
00529 fd = fb->FFp(wb1);
00530 int wc = fa->FFi(wa1);
00531 int wd = fb->FFi(wb1);
00532 fc->FFp(wc) = fd;
00533 fc->FFi(wc) = wd;
00534 fd->FFp(wd) = fc;
00535 fd->FFi(wd) = wc;
00536
00537 assert( ! ( fc->IsF( wc) ) );
00538 assert( ! ( fd->IsF( wd) ) );
00539
00540 Allocator<MeshType>::DeleteFace( m,*fa );
00541 Allocator<MeshType>::DeleteFace( m,*fb );
00542
00543 DecreaseValency(fa,wedge,m );
00544
00545
00546 }
00547
00548
00549 static bool TestAndRemoveDoublet(FaceType &f, int wedge, MeshType& m){
00550 if (IsDoublet(f,wedge)) {
00551 RemoveDoublet(f,wedge,m);
00552 return true;
00553 }
00554 return false;
00555 }
00556
00557 static bool TestAndRemoveSinglet(FaceType &f, int wedge, MeshType& m){
00558 if (IsSinglet(f,wedge)) {
00559 RemoveSinglet(f,wedge,m);
00560 return true;
00561 }
00562 return false;
00563 }
00564
00565
00566
00567
00568 static int CountBitPolygonInternalValency(const FaceType& f, int wedge){
00569 const FaceType* pf = &f;
00570 int pi = wedge;
00571 int res = 0;
00572 do {
00573 if (!pf->IsF(pi)) res++;
00574 const FaceType *t = pf;
00575 t = pf->FFp( pi );
00576 if (pf == t ) return -1;
00577 pi = (pi+1)%3;
00578 pf = t;
00579 } while (pf != &f);
00580 return res;
00581 }
00582
00583
00584
00585 static bool IsDoubletFF(const FaceType& f, int wedge){
00586 const FaceType* pf = &f;
00587 int pi = wedge;
00588 int res = 0, guard=0;
00589 do {
00590 if (!pf->IsAnyF()) return false;
00591 if (!pf->IsF(pi)) res++;
00592 const FaceType *t = pf;
00593 t = pf->FFp( pi );
00594 if (pf == t ) return false;
00595 pi = pf->cFFi( pi );
00596 pi = (pi+1)%3;
00597 pf = t;
00598 assert(guard++<100);
00599 } while (pf != &f);
00600 return (res == 2);
00601 }
00602
00603
00604 static bool IsDoublet(const FaceType& f, int wedge){
00605 return (GetValency( f.V(wedge)) == 2) && (!f.V(wedge)->IsB() ) ;
00606 }
00607
00608 static bool IsDoubletOrSinglet(const FaceType& f, int wedge){
00609 return (GetValency( f.V(wedge)) <= 2) && (!f.V(wedge)->IsB() ) ;
00610 }
00611
00612 static bool RemoveDoubletOrSinglet(FaceType& f, int wedge, MeshType& m, Pos* affected=NULL){
00613 if (GetValency( f.V(wedge)) == 2) { RemoveDoublet(f,wedge,m,affected) ; return true; }
00614 assert (GetValency( f.V(wedge)) == 1) ;
00615 RemoveSinglet(f,wedge,m,affected) ;
00616 return true;
00617 }
00618
00619
00620
00621 static bool IsSingletFF(const FaceType& f, int wedge){
00622 const FaceType* pf = &f;
00623 int pi = wedge;
00624 int res = 0, guard=0;
00625 do {
00626 if (!pf->IsAnyF()) return false;
00627 if (!pf->IsF(pi)) res++;
00628 const FaceType *t = pf;
00629 t = pf->FFp( pi );
00630 if (pf == t ) return false;
00631 pi = pf->cFFi( pi );
00632 pi = (pi+1)%3;
00633 pf = t;
00634 assert(guard++<100);
00635 } while (pf != &f);
00636 return (res == 1);
00637 }
00638
00639
00640 static bool IsSinglet(const FaceType& f, int wedge){
00641 return (GetValency( f.V(wedge) ) == 1) && (!f.V(wedge)->IsB() ) ;
00642 }
00643
00644 static bool CollapseEdgeDirect(FaceType &f, int w0, MeshType& m){
00645 FaceType * f0 = &f;
00646
00647 assert( !f0->IsF(w0) );
00648
00649 VertexType *v0, *v1;
00650 v0 = f0->V0(w0);
00651 v1 = f0->V1(w0);
00652
00653 if (!RotateVertex(*f0,w0,m)) return false;
00654
00655
00656 if (f0->V(0) == v0) w0 = 0;
00657 else if (f0->V(1) == v0) w0 = 1;
00658 else if (f0->V(2) == v0) w0 = 2;
00659 else assert(0);
00660
00661 assert( f0->V1(w0) == v1 );
00662 assert( f0->IsF(w0) );
00663
00664 return CollapseDiag(*f0,PosOnDiag(*f0,false), m);
00665 }
00666
00667
00668 static bool CollapseEdge(FaceType &f, int w0, MeshType& m, Pos *affected=NULL){
00669 FaceTypeP f0 = &f;
00670 assert(!f0->IsF(w0));
00671
00672 if (IsDoubletOrSinglet(f,w0)) return false;
00673 if (IsDoubletOrSinglet(f,(w0+1)%3)) return false;
00674
00675 if (affected) {
00676 int w1 = 3-w0-FauxIndex(f0);
00677 affected->F() = f0->FFp(w1);
00678 affected->E() = (f0->FFi(w1)+2+w1-FauxIndex(f0))%3;
00679 }
00680
00681 FaceTypeP f1 = f0->FFp(w0);
00682 int w1 = f0->FFi(w0);
00683
00684 assert(f0!=f1);
00685
00686
00687 if (
00688 EdgeLenghtVariationIfVertexRotated(*f0,w0)
00689 <
00690 EdgeLenghtVariationIfVertexRotated(*f1,w1)
00691 ) return CollapseEdgeDirect(*f0,w0,m);
00692 else return CollapseEdgeDirect(*f1,w1,m);
00693 }
00694
00695
00696
00703 static bool CollapseCounterDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* affected=NULL){
00704 if (!CheckFlipDiag(f)) return false;
00705 FlipDiag(f);
00706 return CollapseDiag(f,interpol,m,affected);
00707 }
00708
00709
00710 class Iterator{
00711 private:
00712 typedef typename face::Pos<FaceType> FPos;
00713 Pos start, cur;
00714 bool over;
00715 public:
00716 Iterator(Pos& pos){
00717 if (pos.mode==Pos::NOTHING) {over = true; return; }
00718 start = pos;
00719 if (start.F()->IsD()) { over = true; return;}
00720 assert(!start.F()->IsD());
00721 if (pos.mode==Pos::AROUND) {
00722 if (start.F()->IsF((start.E()+2)%3))
00723 {
00724 int i = start.F()->FFi( start.E() );
00725 start.F() = start.F()->FFp( start.E() );
00726 start.E() = (i+1)%3;
00727 }
00728 }
00729 cur=start;
00730 over = false;
00731 }
00732 bool End() const {
00733 return over;
00734 }
00735 void operator ++ () {
00736 if (start.mode==Pos::PAIR) {
00737 if (cur.F()!=start.F()) over=true;
00738 int i = (cur.E()+2)%3;
00739 cur.E() = (cur.F()->FFi( i )+1)%3;
00740 cur.F() = cur.F()->FFp( i );
00741 } else {
00742 if (cur.F()->IsF(cur.E())) {
00743
00744 int i = cur.F()->FFi( cur.E() );
00745 cur.F() = cur.F()->FFp( cur.E() );
00746 cur.E() = (i+1)%3;
00747 }
00748
00749 FaceType *f =cur.F()->FFp( cur.E() );
00750 if (f==cur.F()) over=true;
00751 cur.E() = (cur.F()->FFi( cur.E() ) +1 )%3;
00752 cur.F() = f;
00753 if (cur.F()==start.F()) over=true;
00754 }
00755 }
00756
00757 Pos GetPos(){
00758 return cur;
00759 }
00760 };
00761
00762 static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* affected=NULL){
00763
00764 FaceType* fa = &f;
00765 int fauxa = FauxIndex(fa);
00766
00767
00768
00769 if (IsDoubletOrSinglet(f,(fauxa+2)%3)) return false;
00770 if (IsDoubletOrSinglet(*(f.FFp(fauxa)),(f.FFi(fauxa)+2)%3)) return false;
00771
00772 if (affected) {
00773 int w1 = (fauxa+2)%3;
00774 affected->F() = fa->FFp(w1);
00775 affected->E() = fa->FFi(w1);
00776 if (affected->F() == fa){
00777 int w1 = (fauxa+1)%3;
00778 affected->F() = fa->FFp(w1);
00779 affected->E() = (fa->FFi(w1)+2)%3;
00780 }
00781 }
00782
00783 FaceType* fb = fa->FFp(fauxa);
00784 assert (fb!=fa);
00785 int fauxb = FauxIndex(fb);
00786
00787 VertexType* va = fa->V(fauxa);
00788 VertexType* vb = fb->V(fauxb);
00789
00790 Interpolator::Apply( *(f.V0(fauxa)), *(f.V1(fauxa)), interpol, *va);
00791
00792 bool border = false;
00793 int val =0;
00794
00795
00796
00797
00798 int pi = fauxb;
00799 FaceType* pf = fb;
00800 do {
00801
00802 if (((pf->V2(pi) == va)||(pf->V1(pi) == va))
00803 &&(pf!=fa)&&(pf!=fb))
00804 return false;
00805 pi=(pi+2)%3;
00806 FaceType *t = pf->FFp(pi);
00807 if (t==pf) { border= true; break; }
00808 pi = pf->FFi(pi);
00809 pf = t;
00810 } while ((pf!=fb));
00811
00812 pi = fauxb;
00813 pf = fb;
00814
00815 do {
00816 pf->V(pi) = va;
00817
00818 pi=(pi+2)%3;
00819 FaceType *t = pf->FFp(pi);
00820 if (t==pf) { border= true; break; }
00821 if (!pf->IsF(pi)) val++;
00822 pi = pf->FFi(pi);
00823 pf = t;
00824 } while (pf!=fb);
00825
00826
00827 if (border) {
00828 val++;
00829 int pi = fauxa;
00830 FaceType* pf = fa;
00831 do {
00832 pi=(pi+1)%3;
00833 pf->V(pi) = va;
00834 FaceType *t = pf->FFp(pi);
00835 if (t==pf) break;
00836 if (!pf->IsF(pi)) val++;
00837 pi = pf->FFi(pi);
00838 pf = t;
00839 } while (pf!=fb);
00840 }
00841
00842
00843 _CollapseDiagHalf(*fb, fauxb, m);
00844 _CollapseDiagHalf(*fa, fauxa, m);
00845
00846 SetValency(va, GetValency(va)+val-2);
00847 DecreaseValency(fb,(fauxb+2)%3,m);
00848 DecreaseValency(fa,(fauxa+2)%3,m);
00849 Allocator<MeshType>::DeleteFace(m,*fa);
00850 Allocator<MeshType>::DeleteFace(m,*fb);
00851
00852
00853
00854
00855 DecreaseValencyNoSingletTest(vb, val, m);
00856
00857
00858
00859 assert(GetValency(vb)!=1 || vb->IsB());
00860
00861
00862
00863
00864
00865
00866
00867 return true;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876 static ScalarType PosOnDiag(const FaceType& f, bool counterDiag){
00877 bool b0, b1, b2, b3;
00878
00879 const FaceType* fa=&f;
00880 int ia = FauxIndex(fa);
00881 const FaceType* fb=fa->cFFp(ia);
00882 int ib = fa->cFFi(ia);
00883
00884 b0 = fa->FFp((ia+1)%3) == fa;
00885 b1 = fa->FFp((ia+2)%3) == fa;
00886 b2 = fb->FFp((ib+1)%3) == fb;
00887 b3 = fb->FFp((ib+2)%3) == fb;
00888
00889 if (counterDiag) {
00890 if ( (b0||b1) && !(b2||b3) ) return 1;
00891 if ( !(b0||b1) && (b2||b3) ) return 0;
00892 } else {
00893 if ( (b1||b2) && !(b3||b0) ) return 0;
00894 if ( !(b1||b2) && (b3||b0) ) return 1;
00895 }
00896
00897 return 0.5f;
00898 }
00899
00900
00901 typedef enum { VALENCY_FLAGS = 24 } ___;
00902
00903 static void SetValency(VertexType *v, int n){
00904
00905 assert(n>=0 && n<=255);
00906 v->Flags()&= ~(255<<VALENCY_FLAGS);
00907 v->Flags()|= n<<VALENCY_FLAGS;
00908 }
00909
00910 static int GetValency(const VertexType *v){
00911
00912 return ( v->Flags() >> (VALENCY_FLAGS) ) & 255;
00913 }
00914
00915 static void IncreaseValency(VertexType *v, int dv=1){
00916 #ifdef NDEBUG
00917 v->Flags() += dv<<VALENCY_FLAGS;
00918 #else
00919 SetValency( v, GetValency(v)+dv );
00920 #endif
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 static void DecreaseValency(FaceType *f, int wedge, MeshType &m){
00935 VertexType *v = f->V(wedge);
00936 int val = GetValency(v)-1;
00937 SetValency( v, val );
00938 if (val==0) Allocator<MeshType>::DeleteVertex(m,*v);
00939 if (val==1)
00940 RemoveSinglet(*f,wedge,m);
00941 }
00942
00943
00944 static void DecreaseValencyNoSingletTest(VertexType *v, int dv, MeshType &m){
00945 int val = GetValency(v)-dv;
00946 SetValency( v, val );
00947 if (DELETE_VERTICES)
00948 if (val==0) Allocator<MeshType>::DeleteVertex(m,*v);
00949 }
00950
00951 static void DecreaseValencySimple(VertexType *v, int dv){
00952 int val = GetValency(v)-dv;
00953 SetValency( v, val );
00954 }
00955
00956 static void UpdateValencyInFlags(MeshType& m){
00957 for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) {
00958 SetValency(&*vi,0);
00959 }
00960 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00961 for (int w=0; w<3; w++)
00962 if (!fi->IsF(w))
00963 IncreaseValency( fi->V(w));
00964 }
00965 }
00966
00967 static void UpdateValencyInQuality(MeshType& m){
00968 for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) {
00969 vi->Q() = 0;
00970 }
00971
00972 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00973 for (int w=0; w<3; w++)
00974 fi->V(w)->Q() += (fi->IsF(w)||fi->IsF((w+2)%3) )? 0.5f:1;
00975 }
00976 }
00977
00978 static bool HasConsistentValencyFlag(MeshType &m) {
00979 UpdateValencyInQuality(m);
00980 bool isok=true;
00981 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00982 for (int k=0; k<3; k++)
00983 if (GetValency(fi->V(k))!=fi->V(k)->Q()){
00984 MarkFaceF(&*fi);
00985 isok=false;
00986 }
00987 }
00988 return isok;
00989 }
00990
00991
00992
00993 static ScalarType quadQuality(FaceType *f, int edge){
00994
00995 CoordType
00996 a = f->V0(edge)->P(),
00997 b = f->FFp(edge)->V2( f->FFi(edge) )->P(),
00998 c = f->V1(edge)->P(),
00999 d = f->V2(edge)->P();
01000
01001 return quadQuality(a,b,c,d);
01002
01003 }
01004
01014 static int TestEdgeRotation(const FaceType &f, int w0, ScalarType *gain=NULL)
01015 {
01016 const FaceType *fa = &f;
01017 assert(! fa->IsF(w0) );
01018 ScalarType q0,q1,q2;
01019 CoordType v0,v1,v2,v3,v4,v5;
01020 int w1 = (w0+1)%3;
01021 int w2 = (w0+2)%3;
01022
01023 v0 = fa->P(w0);
01024 v3 = fa->P(w1);
01025
01026 if (fa->IsF(w2) ) {
01027 v1 = fa->cFFp(w2)->V2( fa->cFFi(w2) )->P();
01028 v2 = fa->P(w2);
01029 } else {
01030 v1 = fa->P(w2);
01031 v2 = fa->cFFp(w1)->V2( fa->cFFi(w1) )->P();
01032 }
01033
01034 const FaceType *fb = fa->cFFp(w0);
01035 w0 = fa->cFFi(w0);
01036
01037 w1 = (w0+1)%3;
01038 w2 = (w0+2)%3;
01039 if (fb->IsF(w2) ) {
01040 v4 = fb->cFFp(w2)->V2( fb->cFFi(w2) )->P();
01041 v5 = fb->P(w2);
01042 } else {
01043 v4 = fb->P(w2);
01044 v5 = fb->cFFp(w1)->V2( fb->cFFi(w1) )->P();
01045 }
01046
01047
01048 #if (!LENGTH_CRITERION)
01049
01050 q0 = quadQuality(v0,v1,v2,v3) + quadQuality(v3,v4,v5,v0);
01051 q1 = quadQuality(v1,v2,v3,v4) + quadQuality(v4,v5,v0,v1);
01052 q2 = quadQuality(v5,v0,v1,v2) + quadQuality(v2,v3,v4,v5);
01053
01054 if (q0>=q1 && q0>=q2) return 0;
01055 if (q1>=q2) return 1;
01056
01057 #else
01058
01059 q0 = (v0 - v3).SquaredNorm();
01060 q1 = (v1 - v4).SquaredNorm();
01061 q2 = (v5 - v2).SquaredNorm();
01062
01063 if (q0<=q1 && q0<=q2) return 0;
01064
01065
01066
01067
01068
01069 if (q1<=q2) {
01070 if (gain) *gain = sqrt(q1)-sqrt(q0);
01071
01072 if (
01073 (v0-v2).SquaredNorm() < (v4-v2).SquaredNorm() ||
01074 (v3-v5).SquaredNorm() < (v1-v5).SquaredNorm()
01075 ) {
01076
01077 return 0;
01078 }
01079
01080 return 1;
01081 }
01082
01083 {
01084 if (gain) *gain = sqrt(q2)-sqrt(q0);
01085
01086 if (
01087 (v0-v4).SquaredNorm() < (v2-v4).SquaredNorm() ||
01088 (v3-v1).SquaredNorm() < (v5-v1).SquaredNorm()
01089 ) {
01090
01091 return 0;
01092 }
01093
01094 return -1;
01095 }
01096 #endif
01097 }
01098
01099 private:
01100
01101
01102
01103
01104 static ScalarType quadQuality(const CoordType &a, const CoordType &b, const CoordType &c, const CoordType &d){
01105 ScalarType score = 0;
01106 score += 1 - math::Abs( Cos( a,b,c) );
01107 score += 1 - math::Abs( Cos( b,c,d) );
01108 score += 1 - math::Abs( Cos( c,d,a) );
01109 score += 1 - math::Abs( Cos( d,a,b) );
01110 return score / 4;
01111 }
01112
01113
01114
01115
01116 private:
01117
01118
01119
01120 static ScalarType Cos(const CoordType &a, const CoordType &b, const CoordType &c )
01121 {
01122 CoordType
01123 e0 = b - a,
01124 e1 = b - c;
01125 ScalarType d = (e0.Norm()*e1.Norm());
01126 if (d==0) return 0.0;
01127 return (e0*e1)/d;
01128 }
01129
01130 };
01131 }}
01132
01133 #endif