bitquad_creation.h
Go to the documentation of this file.
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; // static class to make basic quad operations
00081 
00082 // helper function:
00083 // given a triangle, merge it with its best neightboord to form a quad
00084 template <bool override>
00085 static void selectBestDiag(FaceType *fi){
00086 
00087   if (!override) {
00088     if (fi->IsAnyF()) return;
00089   }
00090 
00091   // select which edge to make faux (if any)...
00092   int whichEdge = -1;
00093   ScalarType bestScore = fi->Q();
00094 
00095   whichEdge=-1;
00096 
00097   for (int k=0; k<3; k++){
00098 
00099     // todo: check creases? (continue if edge k is a crease)
00100 
00101     if (!override) {
00102       if (fi->FFp(k)->IsAnyF()) continue;
00103     }
00104     if (fi->FFp(k)==fi) continue; // never make a border faux
00105 
00106     ScalarType score = BQ::quadQuality( &*fi, k );
00107     if (override) {
00108       // don't override anyway iff other face has a better match
00109       if (score < fi->FFp(k)->Q()) continue;
00110     }
00111     if (score>bestScore) {
00112       bestScore = score;
00113       whichEdge = k;
00114     }
00115   }
00116 
00117   // ...and make it faux
00118   if (whichEdge>=0) {
00119     //if (override && fi->FFp(whichEdge)->IsAnyF()) {
00120       // new score is the average of both scores
00121     //  fi->Q() = fi->FFp(whichEdge)->Q() = ( bestScore + fi->FFp(whichEdge)->Q() ) /2;
00122     //} else {
00123     //}
00124 
00125     if (override) {
00126       // clear any faux edge of the other face
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; // other face's ex-buddy is now single and sad :(
00132       }
00133 
00134       // clear all faux edges of this face...
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; // my ex-buddy is now sad
00140       }
00141     }
00142     // set (new?) quad
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 // helper funcion:
00155 // a pass though all triangles to merge triangle pairs into quads
00156 template <bool override> // override previous decisions?
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 //                                  sideF
00169 //          sideF         V2(e) ------------- v2
00170 //  V0 -------------V2 V2(e)  \               /
00171 //  |             /     |  \    \  newF     /
00172 //  |           /       |    \    \       / e
00173 //  |   f     /         |      \    \   /
00174 //  |       / e         | f   V1(e)=newV =
00175 //  |     /             |      /
00176 //  |   /               |    /
00177 //  | /                 |  /
00178 //  V1                  V0(e)
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     //qDebug("OldFacePRE  %i %i %i",tri::Index(m,f.V(0)),tri::Index(m,f.V(1)),tri::Index(m,f.V(2)));
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     //qDebug("NewFace %i %i %i",tri::Index(m,newFace->V(0)),tri::Index(m,newFace->V(1)),tri::Index(m,newFace->V(2)));
00202     //qDebug("OldFace %i %i %i",tri::Index(m,f.V(0)),tri::Index(m,f.V(1)),tri::Index(m,f.V(2)));
00203 
00204    // Topology
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 // make tri count even by splitting a single triangle...
00230 //
00231 //  V0 -------V2    V0 --------V2
00232 //  |       /       |  \ Fnew /
00233 //  |     /         |    Vnew
00234 //  |   /           |    /
00235 //  | /             |  /
00236 //  V1              V1
00237 //
00238 
00239 static bool MakeTriEvenBySplit(MeshType& m){
00240   if (m.fn%2==0) return false; // it's already Even
00241   // Search for a triangle on the border
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                   // We have found a face with a border
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 // make tri count even by delete...
00266 static bool MakeTriEvenByDelete(MeshType& m)
00267 {
00268   if (m.fn%2==0) return false; // it's already Even
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); // no border face found? then how could the number of tri be Odd?
00281   return true;
00282 }
00283 
00284 
00285 /*
00286   Splits any quad that makes an angle steeper than given degrees
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 &/*m*/){
00322   assert(0); // todo
00323   return false;
00324 }
00325 
00326 /* returns true if mesh is a "conventional" quad mesh.
00327    I.e. if it is all quads, with third edge faux for all triangles*/
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 /* returns true if mesh is a pure tri-mesh. (no faux edges) */
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 /* returns true if mesh is a pure quad-mesh.  */
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 /* returns true if mesh has only tris and quads (no penta etc) */
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   // todo: update VF connectivity if present
00388 
00389 
00390   int ev = 0; // EXTRA vertices (times 2)
00391   int ef = 0; // EXTRA faces
00392 
00393   // first pass: count triangles to be added
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       // it's a triangle
00401       if (k==0) // add a vertex in the center of the face, splitting it in 3
00402        { ev+=2; ef+=2; }
00403       if (k==1) // add a vertex in the border edge, splitting it in 2
00404        { }
00405       if (k==2) // do nothing, just mark the non border edge as faux
00406        { }
00407       if (k==3) // disconnected single triangle (all borders): make one edge as faus
00408        { }
00409     }
00410     else {
00411       // assuming is a quad (not a penta, etc), i.e. only one faux
00412       // add a vertex in the center of the faux edge, splitting the face in 2
00413       ev+=1; ef+=1;
00414       assert(k!=3);
00415     }
00416   }
00417   assert(ev%2==0); // should be even by now
00418   ev/=2; // I was counting each of them twice
00419 
00420   //int originalFaceNum = m.fn;
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   // second pass: add faces and vertices
00427   int nsplit=0; // spits to be done on border in the third pass
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       // it's a triangle
00434 
00435       int k=0; // number of borders
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) // add a vertex in the center of the face, splitting it in 3
00441       {
00442         assert(nvi!=m.vert.end());
00443         VertexType *nv = &*nvi; nvi++;
00444         //*nv = *fi->V0( 0 ); // lazy: copy everything from the old vertex
00445                 nv->ImportData(*(fi->V0( 0 ))); // lazy: copy everything from the old vertex
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; // recover border status
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) { // make a border face faux, anf other two as well
00483         fi->SetF(0);
00484         fi->SetF(1);
00485         fi->SetF(2);
00486         nsplit++;
00487       }
00488       if (k==2) // do nothing, just mark the non border edge as faux
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) // disconnected single triangle (all borders): use catmull-clark (tree vertices, split it in 6
00494       {
00495         fi->ClearAllF();
00496         fi->SetF(2);
00497         nsplit++;
00498       }
00499     }
00500     else {
00501       // assuming is a part of quad (not a penta, etc), i.e. only one faux
00502       FaceType *fa = &*fi;
00503       int ea2 = BQ::FauxIndex(fa); // index of the only faux edge
00504       FaceType *fb = fa->FFp(ea2);
00505       int eb2 = fa->FFi(ea2);
00506       assert(fb->FFp(eb2)==fa) ;
00507       assert(fa->IsF(ea2));
00508       //assert(fb->IsF(eb2)); // reciprocal faux edge
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       // create new vert in center of faux edge
00516       assert(nvi!=m.vert.end());
00517       VertexType *nv = &*nvi; nvi++;
00518       // *nv = * fa->V0( ea2 );
00519             nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex
00520       //nv->P() = ( fa->V(ea2)->P() + fa->V(ea0)->P() ) /2.0;
00521       Interpolator::Apply(*(fa->V(ea2)),*(fa->V(ea0)),0.5,*nv);
00522       // split faces: add 2 faces (one per side)
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); // lazy: copy everything from the old vertex
00529             fd->ImportData(*fb ); CopyTopology(fd,fb);// lazy: copy everything from the old vertex
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       // detect boundaries
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; // repristinate boundary status
00553       if (bd) fd->FFp(eb1)=fd; // of new faces
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       // fix faux mesh boundary... if two any consecutive, merge it in a quad
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       // remaninig boudaries will be fixed by splitting in the last pass
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   // now and there are no tris left, but there can be faces with ONE edge border & faux ()
00602 
00603 
00604   // last pass: add vertex on faux border faces... (if any)
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; // border and faux face (if any)
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) { // ea2 edge is naughty (border AND faux)
00616 
00617         int ea0 = (ea2+1) %3;
00618         int ea1 = (ea2+2) %3;
00619 
00620         // create new vert in center of faux edge
00621         VertexType *nv = &*nvi; nvi++;
00622         //*nv = * fa->V0( ea2 );
00623                 nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex
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         // split face: add 1 face
00627         FaceType *fc = &*nfi; nfi++;
00628 
00629                 fc->ImportData(*fa);CopyTopology(fc,fa); // lazy: copy everything from the old vertex
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; // recover border status
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 // uses Catmull Clark to enforce quad only meshes
00666 // each old edge (but not faux) is split in two.
00667 static void MakePureByCatmullClark(MeshType &m){
00668   MakePureByRefine(m);
00669   MakePureByRefine(m);
00670   // done
00671 }
00672 
00673 // Helper funcion:
00674 // marks edge distance froma a given face.
00675 // Stops at maxDist or at the distance when a triangle is found
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   given a tri-quad mesh,
00709   uses edge rotates to make a tri move toward another tri and to merges them into a quad.
00710 
00711   Retunrs number of surviving triangles (0, or 1), or -1 if not done yet.
00712   StepbyStep: makes just one step!
00713   use it in a loop as long as it returns 0 or 1.
00714 
00715   maxdist is the maximal edge distance where to look for a companion triangle
00716 */
00717 static int MakePureByFlipStepByStep(MeshType &m, int maxdist=10000, int restart=false){
00718 
00719   static FaceType *ta, *tb; // faces to be matched into a quad
00720 
00721   static int step = 0; // hack
00722 
00723   if (restart) { step=0; return false; }
00724 if (step==0) {
00725 
00726   // find a triangular face ta
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; // success: no triangle left (done?)
00732 
00733 
00734   tb = MarkEdgeDistance(m,ta,maxdist);
00735   if (!tb) return 1; // fail: no matching triagle found (increase maxdist?)
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     // select which edge to use
00749     for (int k=0; k<3; k++) {
00750       if (tb->FFp(k) == tb) continue; // border
00751 
00752       FaceType* tbk = tb->FFp(k);
00753 
00754       if (!tbk->IsAnyF()) {done=true; marriageEdge=k; break; } // found my match
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     // use that edge to proceed
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     // create new edge
00786     next->ClearAllF();
00787     tb->FFp(edge)->ClearAllF();
00788 
00789     // dissolve old edge
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     // consume the marriage (two tris = one quad)
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; // not done yet
00809 }
00810 
00811 /*
00812   given a tri-quad mesh,
00813   uses edge rotates to make a tri move toward another tri and to merges them into a quad.
00814   - maxdist is the maximal edge distance where to look for a companion triangle
00815   - retunrs true if all triangles are merged (always, unless they are odd, or maxdist not enough).
00816 */
00817 static bool MakePureByFlip(MeshType &m, int maxdist=10000)
00818 {
00819   MakePureByFlipStepByStep(m, maxdist, true); // restart
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 }} // end namespace vcg::tri
00848 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:29:16