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
00021
00022 public:
00023
00024
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
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
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;
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
00089 return 1;
00090 }
00091
00092
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;
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;
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)) {
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
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
00241
00242
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;
00254 if (p) return res;
00255 }
00256 }
00257 }
00258 return res;
00259 }
00260
00261
00262
00263
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);
00282 }
00283 else {
00284 if (BQ::RotateVertex(*fi, k, m, affected)) res++;
00285 if (affected) return res;
00286 }
00287 }
00288 }
00289 }
00290 return res;
00291 }
00292
00293
00294
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
00304 for (int k=0; k<3; k++) {
00305 if (fi->IsF(k)) continue;
00306 if (fi->FFp(k)<= &*fi) continue;
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
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++;
00334 fi->Q()=0;
00335 }
00336 }
00337 }
00338 assert (res%2==0);
00339 return res/4;
00340 }
00341
00342
00343
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;
00359 }
00360
00361
00362
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;
00378 }
00379
00380
00381
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 }}
00403
00404 #endif