bitquad_optimization.h
Go to the documentation of this file.
00001 #ifndef _BITQUAD_OPTIMIZATION
00002 #define _BITQUAD_OPTIMIZATION
00003 
00004 namespace vcg{namespace tri{
00005 
00006 template <class BQ>
00007 class BitQuadOptimization{
00008 
00009 typedef typename BQ::MeshType MeshType;
00010 typedef typename BQ::Pos Pos;
00011 
00012 typedef typename MeshType::ScalarType ScalarType;
00013 typedef typename MeshType::CoordType CoordType;
00014 typedef typename MeshType::FaceType FaceType;
00015 typedef typename MeshType::FaceType* FaceTypeP;
00016 typedef typename MeshType::VertexType VertexType;
00017 typedef typename MeshType::FaceIterator FaceIterator;
00018 typedef typename MeshType::VertexIterator VertexIterator;
00019 
00020 //typedef BitQuad<MeshType> BQ; // static class to make basic quad operatins
00021 
00022 public:
00023 
00024 // helper function: mark a quadface, setting Q at 0, and neight at .75, 0.5...
00025 static void MarkFace(FaceType* f, MeshType &m){
00026 
00027   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00028      fi->Q() = 1;
00029   }
00030 
00031   for (int i=0; i<3; i++) {
00032     for (int j=0; j<3; j++) f->FFp(i)->FFp(j)->Q() = 0.75;
00033   }
00034   for (int i=0; i<3; i++) {
00035     f->FFp(i)->Q() = 0.50;
00036   }
00037   f->Q() = 0;
00038 
00039 }
00040 
00041 // helper function: mark a quadface, setting Q at 0, and neight at .75, 0.5...
00042 static void MarkVertex(FaceType* f, int wedge, MeshType &m){
00043 
00044   VertexType *v = f->V(wedge);
00045 
00046   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00047      if (fi->V0(0)==v || fi->V1(0)==v ||fi->V2(0)==v ) fi->Q() = 0;
00048      // else fi->Q() = 1;
00049   }
00050 
00051 }
00052 
00053 static bool MarkSmallestEdge(MeshType &m, bool perform)
00054 {
00055   ScalarType min = std::numeric_limits<ScalarType>::max();
00056 
00057   FaceType *fa=NULL; int w=0;
00058   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD())
00059   for (int k=0; k<3; k++) {
00060     FaceType *f=&*fi;
00061 
00062     if (f->IsF(k)) continue;
00063     if (f->FFp(k) == f ) continue; // skip borders
00064 
00065     ScalarType score;
00066 
00067     score = (f->P0(k) - f->P1(k)).Norm();
00068     if (score<min) {
00069       min=score;
00070       fa = f;
00071       w = k;
00072     }
00073 
00074   }
00075   if (fa) {
00076     if (perform) {
00077       return BQ::CollapseEdge(*fa,w,m);
00078     } else {
00079       fa->Q()=0.0;
00080       fa->FFp(w)->Q()=0.0;
00081       return true;
00082     }
00083   }
00084   return false;
00085 }
00086 
00087 static ScalarType Importance(const CoordType  &/*p*/){
00088   //return ::proceduralImportance(p);
00089     return 1;
00090 }
00091 
00092 // returns: 0 if fail. 1 if edge. 2 if diag.
00093 static int MarkSmallestEdgeOrDiag(MeshType &m, ScalarType edgeMult, bool perform, Pos* affected=NULL)
00094 {
00095   ScalarType min = std::numeric_limits<ScalarType>::max();
00096 
00097   FaceType *fa=NULL; int w=0; bool counterDiag = false;
00098   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD())
00099   for (int k=0; k<3; k++) {
00100     FaceType *f=&*fi;
00101 
00102     if (f->FFp(k) >= f ) continue; // skip borders (==), and do it one per edge
00103 
00104     ScalarType score;
00105 
00106     score = (f->P0(k) - f->P1(k)).Norm();
00107 
00108     ScalarType imp = Importance( (f->P0(k) + f->P1(k))/2 );
00109 
00110     score /= imp;
00111 
00112     if (!f->IsF(k)) score*=edgeMult; // edges are supposed to be smaller!
00113 
00114 
00115 
00116     if (score<min) {
00117       min=score;
00118       fa = f;
00119       w = k;
00120       counterDiag=false;
00121     }
00122 
00123     if (f->IsF(k)) { // for diag faces, test counterdiag too
00124       score = BQ::CounterDiag(f).Norm();
00125       score /= imp;
00126 
00127       if (score<min) {
00128         min=score;
00129         fa = f;
00130         w = k;
00131         counterDiag=true;
00132       }
00133     }
00134 
00135 
00136 
00137   }
00138   if (fa) {
00139     if (perform) {
00140       if (fa->IsF(w)) {
00141         if (counterDiag) {
00142           if (BQ::CollapseCounterDiag(*fa, BQ::PosOnDiag(*fa,true), m , affected)) return 2;
00143         } else {
00144           if (BQ::CollapseDiag(*fa, BQ::PosOnDiag(*fa,false), m ,affected)) return 2;
00145         }
00146       } else {
00147         if  (BQ::CollapseEdge(*fa,w,m, affected)) return 1;
00148       }
00149     } else {
00150       fa->Q()=0.0;
00151       fa->FFp(w)->Q()=0.0;
00152       if (fa->IsF(w)) return 2; else return 1;
00153     }
00154   }
00155   return 0;
00156 }
00157 
00158 
00159 static void MarkSmallestDiag(MeshType &m)
00160 {
00161   ScalarType min = std::numeric_limits<ScalarType>::max();
00162 
00163   FaceType *fa=NULL;
00164   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00165     FaceType *f=&*fi;
00166 
00167     ScalarType score;
00168 
00169     score = BQ::Diag(f).Norm();
00170     if (score<min) {
00171       min=score;
00172       fa = f;
00173     }
00174 
00175     score = BQ::CounterDiag(f).Norm();
00176     if (score<min) {
00177       min=score;
00178       fa = f;
00179     }
00180 
00181   }
00182   if (fa) {
00183     fa->Q()=0.0;
00184     fa->FFp(BQ::FauxIndex(fa))->Q()=0.0;
00185   }
00186 
00187 }
00188 
00189 
00190 
00191 static bool IdentifyAndCollapseSmallestDiag(MeshType &m){
00192   ScalarType min = std::numeric_limits<ScalarType>::max();
00193 
00194   FaceType *fa=NULL; bool flip;
00195   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00196     FaceType *f=&*fi;
00197 
00198     ScalarType score;
00199 
00200     score = BQ::Diag(f).Norm();
00201     if (score<min) {
00202       min=score;
00203       fa = f;
00204       flip = false;
00205     }
00206 
00207     score = BQ::CounterDiag(f).Norm();
00208     if (score<min) {
00209       min=score;
00210       fa = f;
00211       flip = true;
00212     }
00213 
00214   }
00215   if (!fa) return false;
00216 
00217   if (BQ::TestAndRemoveDoublet(*fa,0,m)) { return true; }
00218   if (BQ::TestAndRemoveDoublet(*fa,1,m)) { return true; }
00219   if (BQ::TestAndRemoveDoublet(*fa,2,m)) { return true; }
00220   int k = BQ::FauxIndex(fa);
00221   if (BQ::TestAndRemoveDoublet( *fa->FFp(k),(fa->FFi(k)+2)%3, m )) return true;
00222 
00223   if (flip) {
00224     if (!BQ::CheckFlipDiag(*fa) ) {
00225       // I can't collapse (why?)
00226       MarkFace(fa,m);
00227       return false;
00228     } else
00229     BQ::CollapseCounterDiag(*fa, BQ::PosOnDiag(*fa,true), m );
00230   }
00231   else  {
00232     BQ::CollapseDiag(*fa, BQ::PosOnDiag(*fa,false), m );
00233   }
00234   return true;
00235 }
00236 
00237 
00238 
00239 /*
00240 seeks and removes all doublets (a pair of quads sharing two consecutive edges)
00241 by merging them into a single quad (thus removing one vertex and two tri faces)-
00242 Returns number of removed Doublets
00243 */
00244 static int RemoveDoublets(MeshType &m, Pos *p=NULL)
00245 {
00246   int res=0;
00247   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00248     fi->Q()=1;
00249     for (int k=0; k<3; k++) {
00250       if ( BQ::IsDoublet(*fi,k) ){
00251         res++;
00252         BQ::RemoveDoublet(*fi,k,m,p);
00253         if (fi->IsD()) break; // break wedge circle, if face disappeard
00254         if (p) return res;
00255       }
00256     }
00257   }
00258   return res;
00259 }
00260 
00261 /*
00262 marks (Quality=0) and approx. counts profitable vertex rotations
00263 (vertex rotations which make edge shorter
00264 */
00265 template <bool perform>
00266 static int MarkVertexRotations(MeshType &m, Pos *affected=NULL)
00267 {
00268   int res=0;
00269   for (VertexIterator vi = m.vert.begin();  vi!=m.vert.end(); vi++) if (!vi->IsD()) vi->ClearV();
00270   if (!perform)
00271   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) fi->Q()=1.0;
00272 
00273   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00274 
00275     for (int k=0; k<3; k++) {
00276       if (fi->V(k)->IsV()) continue;
00277       if (BQ::TestVertexRotation(*fi,k)) {
00278         res++;
00279         fi->V(k)->SetV();
00280         if (!perform) {
00281           res++; MarkVertex(&*fi, k, m); //fi->Q()=0;
00282         }
00283         else {
00284           if (BQ::RotateVertex(*fi, k, m, affected)) res++; //fi->Q()=0;
00285           if (affected) return res; // uncomment for only one rotation
00286         }
00287       }
00288     }
00289   }
00290   return res;
00291 }
00292 
00293 // mark (and count) all edges that are worth rotating
00294 // if perform == true, actually rotate them
00295 template <bool perform>
00296 static int MarkEdgeRotations(MeshType &m, Pos *p=NULL)
00297 {
00298   int count = 0;
00299 
00300   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) fi->Q()=1;
00301 
00302   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00303     //if (count>0) break;
00304     for (int k=0; k<3; k++) {
00305       if (fi->IsF(k)) continue;
00306       if (fi->FFp(k)<= &*fi) continue; // only once per real (non faux) edge, and only for non border ones
00307       int best = BQ::TestEdgeRotation(*fi, k);
00308       if (perform) {
00309         if (best==+1) if (BQ::template RotateEdge< true>(*fi, k, m, p)) count++;
00310         if (best==-1) if (BQ::template RotateEdge<false>(*fi, k, m, p)) count++;
00311         if (p) if (count>0) return count;
00312       }
00313       else {
00314         if (best!=0) { fi->Q()=0; fi->FFp(k)->Q()=0; count++; }
00315       }
00316     }
00317   }
00318 
00319   return count;
00320 }
00321 
00322 /*
00323 marks (Quality=0) and approx. counts doublets (a pair of quads sharing two consecutive edges)
00324 */
00325 static int MarkDoublets(MeshType &m)
00326 {
00327   int res=0;
00328   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00329     fi->Q()=1;
00330     for (int k=0; k<3; k++) {
00331       if ( BQ::IsDoublet(*fi,k) ){
00332         res++;
00333         if (fi->IsF((k+1)%3)) res++; // counts for a quad
00334         fi->Q()=0;
00335       }
00336     }
00337   }
00338   assert (res%2==0);
00339   return res/4; // return doublet pairs (approx, as a quad could be a part of many pairs)
00340 }
00341 
00342 /*
00343 marks (Quality=0) and counts singlets (vertex B in an A-B-A-C quad)
00344 */
00345 static int MarkSinglets(MeshType &m)
00346 {
00347   int res=0;
00348   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00349     fi->Q()=1;
00350     for (int k=0; k<3; k++) {
00351       if ( BQ::IsSinglet(*fi,k) ){
00352         res++;
00353         fi->Q()=0;
00354       }
00355     }
00356   }
00357   assert (res%2==0);
00358   return res/2; // return number of  singlet pairs
00359 }
00360 
00361 /*
00362 deletes singlets, reutrns number of
00363 */
00364 static int RemoveSinglets(MeshType &m, Pos *p=NULL)
00365 {
00366   int res=0;
00367   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00368     for (int k=0; k<3; k++) {
00369       if ( BQ::IsSinglet(*fi,k) ){
00370         res++;
00371         BQ::RemoveSinglet(*fi,k,m, p);
00372         if (p) return res;
00373         break;
00374       }
00375     }
00376   }
00377   return res; // return singlet pairs (approx, as a quad could be a part of many pairs)
00378 }
00379 
00380 
00381 /* returns average quad quality, and assigns it to triangle quality
00382 */
00383 static ScalarType MeasureQuality(MeshType &m)
00384 {
00385   assert(MeshType::HasPerFaceFlags());
00386   ScalarType res = 0;
00387   int div = 0;
00388   for (FaceIterator fi = m.face.begin();  fi!=m.face.end(); fi++) if (!fi->IsD()) {
00389     if (fi->IsAnyF()) {
00390 
00391       ScalarType q = BQ::quadQuality( &*fi, BQ::FauxIndex(&*fi) );
00392 
00393       if (MeshType::HasPerFaceQuality()) fi->Q() = q;
00394       res += q;
00395       div++;
00396     }
00397   }
00398   if (!div) return 0; else return res / div;
00399 }
00400 
00401 };
00402 }} // end namespace vcg::tri
00403 
00404 #endif


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