00001 #include <vcg/complex/algorithms/bitquad_support.h>
00002
00059 #ifndef VCG_BITQUAD_CRE
00060 #define VCG_BITQUAD_CRE
00061
00062 namespace vcg{namespace tri{
00063
00064 template <class _MeshType,
00065 class Interpolator = GeometricInterpolator<typename _MeshType::VertexType> >
00066 class BitQuadCreation{
00067
00068 public:
00069
00070 typedef _MeshType MeshType;
00071 typedef typename MeshType::ScalarType ScalarType;
00072 typedef typename MeshType::CoordType CoordType;
00073 typedef typename MeshType::FaceType FaceType;
00074 typedef typename MeshType::FaceType* FaceTypeP;
00075 typedef typename MeshType::VertexType VertexType;
00076 typedef typename MeshType::FaceIterator FaceIterator;
00077 typedef typename MeshType::VertexIterator VertexIterator;
00078 typedef typename MeshType::ConstFaceIterator ConstFaceIterator;
00079
00080 typedef BitQuad<MeshType> BQ;
00081
00082
00083
00084 template <bool override>
00085 static void selectBestDiag(FaceType *fi){
00086
00087 if (!override) {
00088 if (fi->IsAnyF()) return;
00089 }
00090
00091
00092 int whichEdge = -1;
00093 ScalarType bestScore = fi->Q();
00094
00095 whichEdge=-1;
00096
00097 for (int k=0; k<3; k++){
00098
00099
00100
00101 if (!override) {
00102 if (fi->FFp(k)->IsAnyF()) continue;
00103 }
00104 if (fi->FFp(k)==fi) continue;
00105
00106 ScalarType score = BQ::quadQuality( &*fi, k );
00107 if (override) {
00108
00109 if (score < fi->FFp(k)->Q()) continue;
00110 }
00111 if (score>bestScore) {
00112 bestScore = score;
00113 whichEdge = k;
00114 }
00115 }
00116
00117
00118 if (whichEdge>=0) {
00119
00120
00121
00122
00123
00124
00125 if (override) {
00126
00127 for (int k=0; k<3; k++)
00128 if (fi->FFp(whichEdge)->IsF(k)) {
00129 fi->FFp(whichEdge)->ClearF(k);
00130 fi->FFp(whichEdge)->FFp(k)->ClearF( fi->FFp(whichEdge)->FFi(k) );
00131 fi->FFp(whichEdge)->FFp(k)->Q()=0.0;
00132 }
00133
00134
00135 for (int k=0; k<3; k++)
00136 if (fi->IsF(k)) {
00137 fi->ClearF(k);
00138 fi->FFp(k)->ClearF( fi->FFi(k) );
00139 fi->FFp(k)->Q()= 0.0;
00140 }
00141 }
00142
00143 fi->SetF(whichEdge);
00144 fi->FFp(whichEdge)->SetF( fi->FFi(whichEdge) );
00145 fi->Q() = fi->FFp(whichEdge)->Q() = bestScore;
00146
00147 }
00148
00149
00150 }
00151
00152
00153
00154
00155
00156 template <bool override>
00157 static void MakeDominantPass(MeshType &m){
00158
00159 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00160 selectBestDiag<override>(&(*fi));
00161 }
00162
00163 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 static std::pair<typename MeshType::FaceType *, typename MeshType::VertexType *> FaceSplitBorderEdge(MeshType &m, typename MeshType::FaceType &f, int edge, typename MeshType::FaceType *newFace, typename MeshType::VertexType *newVert )
00182 {
00183
00184 typename MeshType::FaceType *sideFFp;
00185 int sideFFi;
00186
00187 assert(tri::HasFFAdjacency(m));
00188 assert(face::IsBorder(f,edge));
00189
00190 if(newFace==0) newFace=&*tri::Allocator<MeshType>::AddFaces(m,1);
00191 if(newVert==0) {
00192 newVert=&*tri::Allocator<MeshType>::AddVertices(m,1);
00193 newVert->P()=(f.P0(edge)+f.P1(edge))/2.0;
00194 }
00195 newFace->V0(edge)=newVert;
00196 newFace->V1(edge)=f.V1(edge);
00197 newFace->V2(edge)=f.V2(edge);
00198
00199 f.V1(edge)=newVert;
00200
00201
00202
00203
00204
00205
00206 newFace->FFp((edge+2)%3) = &f;
00207 newFace->FFi((edge+2)%3) = (edge+1)%3;
00208
00209 newFace->FFp((edge+0)%3) = newFace;
00210 newFace->FFi((edge+0)%3) = (edge+0)%3;
00211
00212 newFace->FFp((edge+1)%3) = f.FFp((edge+1)%3);
00213 newFace->FFi((edge+1)%3) = f.FFi((edge+1)%3);
00214
00215 sideFFp = f.FFp((edge+1)%3);
00216 sideFFi = f.FFi((edge+1)%3);
00217
00218 f.FFp((edge+1)%3) = newFace;
00219 f.FFi((edge+1)%3) = (edge+2)%3;
00220
00221 sideFFp->FFp(sideFFi)=newFace;
00222 sideFFp->FFi(sideFFi)=(edge+1)%3;
00223
00224 assert(face::IsBorder(f,edge));
00225 assert(face::IsBorder(*newFace,edge));
00226
00227 return std::make_pair(newFace,newVert);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 static bool MakeTriEvenBySplit(MeshType& m){
00240 if (m.fn%2==0) return false;
00241
00242 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++)
00243 {
00244 if(!(*fi).IsD())
00245 {
00246 for (int k=0; k<3; k++) {
00247 if (face::IsBorder(*fi,k)){
00248
00249 int index=tri::Index(m,*fi);
00250 VertexIterator vnew=tri::Allocator<MeshType>::AddVertices(m,1);
00251 (*vnew).P()=((*fi).P0(k)+(*fi).P1(k))/2.0;
00252
00253 FaceIterator fnew=tri::Allocator<MeshType>::AddFaces(m,1);
00254
00255 FaceSplitBorderEdge(m,m.face[index],k,&*fnew,&*vnew);
00256 return true;
00257 }
00258 }
00259 }
00260
00261 }
00262 return true;
00263 }
00264
00265
00266 static bool MakeTriEvenByDelete(MeshType& m)
00267 {
00268 if (m.fn%2==0) return false;
00269
00270 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) {
00271 for (int k=0; k<3; k++) {
00272 if (face::IsBorder(*fi,k) ) {
00273 FFDetachManifold(*fi,(k+1)%3);
00274 FFDetachManifold(*fi,(k+2)%3);
00275 Allocator<MeshType>::DeleteFace(m,*fi);
00276 return true;
00277 }
00278 }
00279 }
00280 assert(0);
00281 return true;
00282 }
00283
00284
00285
00286
00287
00288 static int SplitNonFlatQuads(MeshType &m, ScalarType deg=0){
00289 int res=0;
00290 float th = math::Cos(math::ToRad(deg));
00291 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00292 if (fi->IsAnyF()) {
00293 int faux = BQ::FauxIndex(&*fi);
00294 FaceType *fb = fi->FFp(faux);
00295 if (fb->N()*fi->N()<th) {
00296 fi->ClearF(faux);
00297 fb->ClearF(fi->FFi(faux));
00298 res++;
00299 }
00300 }
00301 }
00302 return res;
00303 }
00304
00305
00309 static void MakeBitTriOnly(MeshType &m){
00310 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) {
00311 fi->ClearAllF();
00312 }
00313 }
00314
00321 static bool MakeBitTriQuadConventional(MeshType &){
00322 assert(0);
00323 return false;
00324 }
00325
00326
00327
00328 static bool IsBitTriQuadConventional(const MeshType &m){
00329 for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00330 if (fi->IsAnyF())
00331 if ( (fi->Flags() & FaceType::FAUX012 ) != FaceType::FAUX2 ) {
00332 return false;
00333 }
00334 }
00335 return true;
00336 }
00337
00338
00339 static bool IsTriOnly(const MeshType &m){
00340 for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00341 if (fi->IsAnyF()) return false;
00342 }
00343 return true;
00344 }
00345
00346
00347 static bool IsQuadOnly(const MeshType &m){
00348 for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00349 int count = 0;
00350 if (fi->IsF(0)) count++;
00351 if (fi->IsF(1)) count++;
00352 if (fi->IsF(2)) count++;
00353 if (count!=1) return false;
00354 }
00355 return true;
00356 }
00357
00358
00359 static bool IsTriQuadOnly(const MeshType &m){
00360 for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00361 int count = 0;
00362 if (fi->IsF(0)) count++;
00363 if (fi->IsF(1)) count++;
00364 if (fi->IsF(2)) count++;
00365 if (count>1) return false;
00366 }
00367 return true;
00368 }
00369
00370
00371 static void CopyTopology(FaceType *fnew, FaceType * fold)
00372 {
00373 fnew->FFp(0)=fold->FFp(0); fnew->FFi(0)=fold->FFi(0);
00374 fnew->FFp(1)=fold->FFp(1); fnew->FFi(1)=fold->FFi(1);
00375 fnew->FFp(2)=fold->FFp(2); fnew->FFi(2)=fold->FFi(2);
00376 fnew->V(0) = fold->V(0);
00377 fnew->V(1) = fold->V(1);
00378 fnew->V(2) = fold->V(2);
00379 }
00385 static void MakePureByRefine(MeshType &m){
00386
00387
00388
00389
00390 int ev = 0;
00391 int ef = 0;
00392
00393
00394 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00395 int k=0;
00396 if (face::IsBorder(*fi,0)) k++;
00397 if (face::IsBorder(*fi,1)) k++;
00398 if (face::IsBorder(*fi,2)) k++;
00399 if (!fi->IsAnyF()) {
00400
00401 if (k==0)
00402 { ev+=2; ef+=2; }
00403 if (k==1)
00404 { }
00405 if (k==2)
00406 { }
00407 if (k==3)
00408 { }
00409 }
00410 else {
00411
00412
00413 ev+=1; ef+=1;
00414 assert(k!=3);
00415 }
00416 }
00417 assert(ev%2==0);
00418 ev/=2;
00419
00420
00421 FaceIterator nfi = tri::Allocator<MeshType>::AddFaces(m,ef);
00422 VertexIterator nvi = tri::Allocator<MeshType>::AddVertices(m,ev);
00423
00424 tri::UpdateFlags<MeshType>::FaceClearV(m);
00425
00426
00427 int nsplit=0;
00428 for (FaceIterator fi = m.face.begin(), fend = nfi; fi!=fend; fi++) if (!fi->IsD() && !fi->IsV() ) {
00429
00430 fi->SetV();
00431
00432 if (!fi->IsAnyF()) {
00433
00434
00435 int k=0;
00436 if (face::IsBorder(*fi,0)) k++;
00437 if (face::IsBorder(*fi,1)) k++;
00438 if (face::IsBorder(*fi,2)) k++;
00439
00440 if (k==0)
00441 {
00442 assert(nvi!=m.vert.end());
00443 VertexType *nv = &*nvi; nvi++;
00444
00445 nv->ImportData(*(fi->V0( 0 )));
00446
00447 nv->P() = ( fi->V(0)->P() + fi->V(1)->P() + fi->V(2)->P() ) /3.0;
00448 FaceType *fa = &*fi;
00449 FaceType *fb = &*nfi; nfi++;
00450 FaceType *fc = &*nfi; nfi++;
00451
00452 fb->ImportData(*fa); CopyTopology(fb,fa);
00453 fc->ImportData(*fa); CopyTopology(fc,fa);
00454
00455 fa->V(0) = nv;
00456 fb->V(1) = nv;
00457 fc->V(2) = nv;
00458
00459 fb->FFp(2)=fa->FFp(2); fb->FFi(2)=fa->FFi(2);
00460 fc->FFp(0)=fa->FFp(0); fc->FFi(0)=fa->FFi(0);
00461
00462 assert( fa->FFp(1)->FFp(fa->FFi(1)) == fa );
00463 fb->FFp(2)->FFp(fb->FFi(2)) = fb;
00464 fc->FFp(0)->FFp(fc->FFi(0)) = fc;
00465
00466 fa->FFp(0) = fc; fa->FFp(2) = fb; fa->FFi(0) = fa->FFi(2) = 1;
00467 fb->FFp(1) = fa; fb->FFp(0) = fc; fb->FFi(0) = fb->FFi(1) = 2;
00468 fc->FFp(1) = fa; fc->FFp(2) = fb; fc->FFi(1) = fc->FFi(2) = 0;
00469
00470 if (fb->FFp(2)==fa) fb->FFp(2)=fb;
00471 if (fc->FFp(0)==fa) fc->FFp(0)=fc;
00472
00473 fa->ClearAllF();
00474 fb->ClearAllF();
00475 fc->ClearAllF();
00476 fa->SetF(1);
00477 fb->SetF(2);
00478 fc->SetF(0);
00479
00480 fa->SetV();fb->SetV();fc->SetV();
00481 }
00482 if (k==1) {
00483 fi->SetF(0);
00484 fi->SetF(1);
00485 fi->SetF(2);
00486 nsplit++;
00487 }
00488 if (k==2)
00489 {
00490 fi->ClearAllF();
00491 for (int w=0; w<3; w++) if (fi->FFp(w) != &*fi) fi->SetF(w);
00492 }
00493 if (k==3)
00494 {
00495 fi->ClearAllF();
00496 fi->SetF(2);
00497 nsplit++;
00498 }
00499 }
00500 else {
00501
00502 FaceType *fa = &*fi;
00503 int ea2 = BQ::FauxIndex(fa);
00504 FaceType *fb = fa->FFp(ea2);
00505 int eb2 = fa->FFi(ea2);
00506 assert(fb->FFp(eb2)==fa) ;
00507 assert(fa->IsF(ea2));
00508
00509
00510 int ea0 = (ea2+1) %3;
00511 int ea1 = (ea2+2) %3;
00512 int eb0 = (eb2+1) %3;
00513 int eb1 = (eb2+2) %3;
00514
00515
00516 assert(nvi!=m.vert.end());
00517 VertexType *nv = &*nvi; nvi++;
00518
00519 nv->ImportData(*(fa->V0( ea2 ) ));
00520
00521 Interpolator::Apply(*(fa->V(ea2)),*(fa->V(ea0)),0.5,*nv);
00522
00523 assert(nfi!=m.face.end());
00524 FaceType *fc = &*nfi; nfi++;
00525 assert(nfi!=m.face.end());
00526 FaceType *fd = &*nfi; nfi++;
00527
00528 fc->ImportData(*fa ); CopyTopology(fc,fa);
00529 fd->ImportData(*fb ); CopyTopology(fd,fb);
00530
00531 fa->V(ea2) = fc->V(ea0) =
00532 fb->V(eb2) = fd->V(eb0) = nv ;
00533
00534 fa->FFp(ea1)->FFp( fa->FFi(ea1) ) = fc;
00535 fb->FFp(eb1)->FFp( fb->FFi(eb1) ) = fd;
00536
00537 fa->FFp(ea1) = fc ; fa->FFp(ea2) = fd;
00538 fa->FFi(ea1) = ea0; fa->FFi(ea2) = eb2;
00539 fb->FFp(eb1) = fd ; fb->FFp(eb2) = fc;
00540 fb->FFi(eb1) = eb0; fb->FFi(eb2) = ea2;
00541 fc->FFp(ea0) = fa ; fc->FFp(ea2) = fb;
00542 fc->FFi(ea0) = ea1; fc->FFi(ea2) = eb2;
00543 fd->FFp(eb0) = fb ; fd->FFp(eb2) = fa;
00544 fd->FFi(eb0) = eb1; fd->FFi(eb2) = ea2;
00545
00546
00547 bool ba = fa->FFp(ea0)==fa;
00548 bool bc = fc->FFp(ea1)==fa;
00549 bool bb = fb->FFp(eb0)==fb;
00550 bool bd = fd->FFp(eb1)==fb;
00551
00552 if (bc) fc->FFp(ea1)=fc;
00553 if (bd) fd->FFp(eb1)=fd;
00554
00555 fa->SetV();
00556 fb->SetV();
00557 fc->SetV();
00558 fd->SetV();
00559
00560 fa->ClearAllF();
00561 fb->ClearAllF();
00562 fc->ClearAllF();
00563 fd->ClearAllF();
00564
00565 fa->SetF( ea0 );
00566 fb->SetF( eb0 );
00567 fc->SetF( ea1 );
00568 fd->SetF( eb1 );
00569
00570
00571 if (ba&&bc) {
00572 fa->ClearAllF(); fa->SetF(ea1);
00573 fc->ClearAllF(); fc->SetF(ea0);
00574 ba = bc = false;
00575 }
00576 if (bc&&bb) {
00577 fc->ClearAllF(); fc->SetF(ea2);
00578 fb->ClearAllF(); fb->SetF(eb2);
00579 bc = bb = false;
00580 }
00581 if (bb&&bd) {
00582 fb->ClearAllF(); fb->SetF(eb1);
00583 fd->ClearAllF(); fd->SetF(eb0);
00584 bb = bd = false;
00585 }
00586 if (bd&&ba) {
00587 fd->ClearAllF(); fd->SetF(eb2);
00588 fa->ClearAllF(); fa->SetF(ea2);
00589 bd = ba = false;
00590 }
00591
00592 if (ba) nsplit++;
00593 if (bb) nsplit++;
00594 if (bc) nsplit++;
00595 if (bd) nsplit++;
00596 }
00597 }
00598 assert(nfi==m.face.end());
00599 assert(nvi==m.vert.end());
00600
00601
00602
00603
00604
00605 if (nsplit>0) {
00606 FaceIterator nfi = tri::Allocator<MeshType>::AddFaces(m,nsplit);
00607 VertexIterator nvi = tri::Allocator<MeshType>::AddVertices(m,nsplit);
00608 for (FaceIterator fi = m.face.begin(), fend = nfi; fi!=fend; fi++) if (!fi->IsD()) {
00609 FaceType* fa = &*fi;
00610 int ea2 = -1;
00611 if (fa->FFp(0)==fa && fa->IsF(0) ) ea2=0;
00612 if (fa->FFp(1)==fa && fa->IsF(1) ) ea2=1;
00613 if (fa->FFp(2)==fa && fa->IsF(2) ) ea2=2;
00614
00615 if (ea2 != -1) {
00616
00617 int ea0 = (ea2+1) %3;
00618 int ea1 = (ea2+2) %3;
00619
00620
00621 VertexType *nv = &*nvi; nvi++;
00622
00623 nv->ImportData(*(fa->V0( ea2 ) ));
00624 nv->P() = ( fa->V(ea2)->P() + fa->V(ea0)->P() ) /2.0;
00625 Interpolator::Apply(*(fa->V(ea2)),*(fa->V(ea0)),0.5,*nv);
00626
00627 FaceType *fc = &*nfi; nfi++;
00628
00629 fc->ImportData(*fa);CopyTopology(fc,fa);
00630
00631 fa->V(ea2) = fc->V(ea0) = nv ;
00632
00633 fc->FFp(ea2) = fc;
00634
00635 fa->FFp(ea1)->FFp( fa->FFi(ea1) ) = fc;
00636
00637 fa->FFp(ea1) = fc ;
00638 fa->FFi(ea1) = ea0;
00639 fc->FFp(ea0) = fa ; fc->FFp(ea2) = fc;
00640 fc->FFi(ea0) = ea1;
00641
00642 if (fc->FFp(ea1)==fa) fc->FFp(ea1)=fc;
00643
00644 assert(fa->IsF(ea0) == fa->IsF(ea1) );
00645 bool b = fa->IsF(ea1);
00646
00647 fa->ClearAllF();
00648 fc->ClearAllF();
00649
00650 if (b) {
00651 fa->SetF( ea0 );
00652 fc->SetF( ea1 );
00653 } else {
00654 fa->SetF( ea1 );
00655 fc->SetF( ea0 );
00656 }
00657 }
00658 }
00659 }
00660
00661
00662 }
00663
00664
00665
00666
00667 static void MakePureByCatmullClark(MeshType &m){
00668 MakePureByRefine(m);
00669 MakePureByRefine(m);
00670
00671 }
00672
00673
00674
00675
00676 static FaceType * MarkEdgeDistance(MeshType &m, FaceType *startF, int maxDist){
00677 assert(tri::HasPerFaceQuality(m));
00678
00679 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00680 fi->Q()=maxDist;
00681 }
00682
00683 FaceType * firstTriangleFound = NULL;
00684
00685 startF->Q() = 0;
00686 std::vector<FaceType*> stack;
00687 int stackPos=0;
00688 stack.push_back(startF);
00689
00690 while ( stackPos<int(stack.size())) {
00691 FaceType *f = stack[stackPos++];
00692 for (int k=0; k<3; k++) {
00693 assert(FFCorrectness(*f,k));
00694 FaceType *fk = f->FFp(k);
00695 int fq = int(f->Q()) + ( ! f->IsF(k) );
00696 if (fk->Q()> fq && fq <= maxDist) {
00697 if (!fk->IsAnyF()) { firstTriangleFound = fk; maxDist = fq;}
00698 fk->Q() = fq;
00699 stack.push_back(fk);
00700 }
00701 }
00702 }
00703 return firstTriangleFound;
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 static int MakePureByFlipStepByStep(MeshType &m, int maxdist=10000, int restart=false){
00718
00719 static FaceType *ta, *tb;
00720
00721 static int step = 0;
00722
00723 if (restart) { step=0; return false; }
00724 if (step==0) {
00725
00726
00727 ta = NULL;
00728 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
00729 if (!fi->IsAnyF()) { ta=&*fi; break; }
00730 }
00731 if (!ta) return 0;
00732
00733
00734 tb = MarkEdgeDistance(m,ta,maxdist);
00735 if (!tb) return 1;
00736
00737 step=1;
00738
00739 } else {
00740 int marriageEdge=-1;
00741 bool done = false;
00742 while (!done) {
00743
00744 int bestScore = int(tb->Q());
00745 int edge = -1;
00746 bool mustDoFlip;
00747
00748
00749 for (int k=0; k<3; k++) {
00750 if (tb->FFp(k) == tb) continue;
00751
00752 FaceType* tbk = tb->FFp(k);
00753
00754 if (!tbk->IsAnyF()) {done=true; marriageEdge=k; break; }
00755
00756 int back = tb->FFi(k);
00757 int faux = BQ::FauxIndex(tbk);
00758 int other = 3-back-faux;
00759
00760 int scoreA = int(tbk->FFp(other)->Q());
00761
00762 FaceType* tbh = tbk->FFp(faux);
00763 int fauxh = BQ::FauxIndex(tbh);
00764
00765 int scoreB = int(tbh->FFp( (fauxh+1)%3 )->Q());
00766 int scoreC = int(tbh->FFp( (fauxh+2)%3 )->Q());
00767
00768 int scoreABC = std::min( scoreC, std::min( scoreA, scoreB ) );
00769 if (scoreABC<bestScore) {
00770 bestScore = scoreABC;
00771 edge = k;
00772 mustDoFlip = !(scoreB == scoreABC || scoreC == scoreABC);
00773 }
00774 }
00775
00776 if (done) break;
00777
00778
00779 if (mustDoFlip) {
00780 BQ::FlipDiag( *(tb->FFp(edge)) );
00781 }
00782
00783 FaceType* next = tb->FFp(edge)->FFp( BQ::FauxIndex(tb->FFp(edge)) );
00784
00785
00786 next->ClearAllF();
00787 tb->FFp(edge)->ClearAllF();
00788
00789
00790 tb->SetF(edge);
00791 tb->FFp(edge)->SetF( tb->FFi(edge) );
00792 tb->FFp(edge)->Q() = tb->Q();
00793
00794 tb = next;
00795 break;
00796 }
00797
00798 if (marriageEdge!=-1) {
00799
00800 assert(!(tb->IsAnyF()));
00801 assert(!(tb->FFp(marriageEdge)->IsAnyF()));
00802 tb->SetF(marriageEdge);
00803 tb->FFp(marriageEdge)->SetF(tb->FFi(marriageEdge));
00804
00805 step=0;
00806 }
00807 }
00808 return -1;
00809 }
00810
00811
00812
00813
00814
00815
00816
00817 static bool MakePureByFlip(MeshType &m, int maxdist=10000)
00818 {
00819 MakePureByFlipStepByStep(m, maxdist, true);
00820 int res=-1;
00821 while (res==-1) res = MakePureByFlipStepByStep(m, maxdist);
00822 return res==0;
00823 }
00824
00832 static void MakeDominant(MeshType &m, int level){
00833
00834 for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) {
00835 fi->ClearAllF();
00836 fi->Q() = 0;
00837 }
00838
00839
00840 MakeDominantPass<false> (m);
00841 if (level>0) MakeDominantPass<true> (m);
00842 if (level>1) MakeDominantPass<true> (m);
00843 if (level>0) MakeDominantPass<false> (m);
00844 }
00845
00846 };
00847 }}
00848 #endif