autoalign_4pcs.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 #ifndef _AUTOALIGN_4PCS_H_
00024 #define _AUTOALIGN_4PCS_H_
00025 
00034 #include <vcg/complex/complex.h>
00035 #include <vcg/space/point_matching.h>
00036 #include <vcg/complex/algorithms/closest.h>
00037 #include <vcg/complex/algorithms/point_sampling.h>
00038 #include <vcg/math/random_generator.h>
00039 #include <ctime>
00040 namespace vcg{
00041 namespace tri{
00042 
00043 template <class MeshType>
00044 class FourPCS {
00045 public:
00046     /* mesh only for using spatial indexing functions (to remove) */
00047   class PVertex;    // dummy prototype never used
00048   class PFace;
00049 
00050   class PUsedTypes: public vcg::UsedTypes < vcg::Use<PVertex>::template AsVertexType,
00051                                             vcg::Use<PFace  >::template AsFaceType >{};
00052 
00053   class PVertex : public vcg::Vertex< PUsedTypes,vcg::vertex::BitFlags,vcg::vertex::Coord3f,vcg::vertex::Mark>{};
00054   class PFace   : public vcg::Face<   PUsedTypes> {};
00055   class PMesh   : public vcg::tri::TriMesh< std::vector<PVertex>, std::vector<PFace> > {};
00056 
00057   typedef typename MeshType::ScalarType ScalarType;
00058   typedef typename MeshType::CoordType CoordType;
00059   typedef typename vcg::Matrix44<ScalarType> Matrix44x;
00060   typedef typename vcg::Box3<ScalarType> Box3x;
00061 
00062   typedef typename MeshType::VertexIterator VertexIterator;
00063   typedef typename MeshType::VertexPointer VertexPointer;
00064   typedef typename MeshType::VertexType VertexType;
00065   typedef vcg::Point4< vcg::Point3<ScalarType> > FourPoints;
00066   typedef vcg::GridStaticPtr<typename PMesh::VertexType, ScalarType > GridType;
00067 
00068   /* class for Parameters */
00069   struct Param
00070   {
00071     ScalarType overlap;    // overlap estimation as a percentage of overlapping points.
00072 
00073     int sampleNumP;        // number of samples on moving mesh P (it determines the sampling radius to be used to sample Q too)
00074     float samplingRadius;
00075 
00076     ScalarType deltaPerc;  // Approximation Level (expressed as a percentage of the avg distance between samples)
00077     ScalarType deltaAbs;   // Approximation Level
00078     int feetSize;          // how many points in the neighborhood of each of the 4 points
00079     int scoreFeet;         // how many of the feetsize points must match (max feetsize*4) to try an early interrupt
00080     ScalarType cosAngle;   // max admittable angle that can be admitted between matching points in alignments (expressed as cos(ang) )
00081     int seed;              // random seed used. Need for repeatability.
00082 
00083     void Default(){
00084       overlap = 0.5;
00085       sampleNumP=500;
00086       samplingRadius=0;
00087 
00088       deltaPerc = 0.5;
00089       deltaAbs = 0;
00090       feetSize = 25;
00091       scoreFeet = 50;
00092       seed =0;
00093       cosAngle = 0; // normals must differ more than 90 degree to be considered bad.
00094     }
00095   };
00096 
00097   struct Stat
00098   {
00099     Stat() : initTime(0),selectCoplanarBaseTime(0),findCongruentTime(0),testAlignmentTime(0)
00100     {}
00101     clock_t initTime;
00102     clock_t selectCoplanarBaseTime;
00103     clock_t findCongruentTime;
00104     clock_t testAlignmentTime;
00105     float init()   {return 1000.0f*float(initTime)/float(CLOCKS_PER_SEC);}
00106     float select() {return 1000.0f*float(selectCoplanarBaseTime)/float(CLOCKS_PER_SEC);}
00107     float findCongruent() {return 1000.0f*float(findCongruentTime)/float(CLOCKS_PER_SEC);}
00108     float testAlignment() {return 1000.0f*float(testAlignmentTime)/float(CLOCKS_PER_SEC);}
00109   };
00110 
00111   class Couple
00112   {
00113   public:
00114     VertexPointer p0,p1;
00115     Couple(VertexPointer i, VertexPointer j, float d) : p0(i),p1(j),dist(d){}
00116     float dist;
00117     bool operator < (const   Couple & o) const {return dist < o.dist;}
00118     VertexPointer operator[](const int &i) const {return (i==0)? this->p0 : this->p1;}
00119   };
00120 
00121   struct Candidate
00122   {
00123     Candidate():score(0){}
00124     Candidate(FourPoints _p, vcg::Matrix44<ScalarType>_T):p(_p),T(_T){}
00125     FourPoints  p;
00126     vcg::Matrix44<ScalarType> T;
00127     int score;
00128     inline bool operator <(const Candidate & o) const {return score > o.score;}
00129   };
00130 
00131 
00132   // class for the point  'ei'
00133   struct EPoint{
00134     EPoint(vcg::Point3<ScalarType> _p, int _i):pos(_p),pi(_i){}
00135     vcg::Point3<ScalarType> pos;
00136     int pi;        //index to R[1|2]
00137     void GetBBox(vcg::Box3<ScalarType> & b){b.Add(pos);}
00138   };
00139 
00140 
00141   Param par;    
00142   Stat stat;
00143 
00144   MeshType  *P;    // Moving Mesh (from which the coplanar base is selected)
00145   MeshType  *Q;    // Fixed Mesh  (mesh where to find the correspondences)
00146 
00147   math::MarsenneTwisterRNG rnd;
00148 
00149   std::vector<VertexPointer> subsetQ;  // subset of the vertices in Q
00150   std::vector<VertexPointer> subsetP; // random selection on P
00151 
00152   ScalarType side;               // side
00153 
00154   PMesh     Invr;                // invariants
00155   std::vector< Candidate > U;    // the
00156   int iwinner;                   // winner == U[iwinner]
00157   std::vector<FourPoints> bases; // used bases
00158   std::vector<VertexType*> ExtB[4]; // selection of vertices "close" to the four point
00159 
00160   vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridQ;
00161   vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType > ugridP;
00162 
00163   /* returns the closest point between to segments x1-x2 and x3-x4.  */
00164     void IntersectionLineLine(const CoordType & x1,const CoordType & x2,const CoordType & x3,const CoordType & x4, CoordType&x)
00165     {
00166       CoordType a = x2-x1, b = x4-x3, c = x3-x1;
00167       x = x1 + a * ((c^b).dot(a^b)) / (a^b).SquaredNorm();
00168     }
00169 
00170 
00171 void Init(MeshType &_movP,MeshType &_fixQ)
00172 {
00173   clock_t t0= clock();
00174   P = &_movP;
00175   Q = &_fixQ;
00176   tri::UpdateBounding<MeshType>::Box(*P);
00177   if(par.seed==0) rnd.initialize(time(0));
00178   else rnd.initialize(par.seed);
00179 
00180   ugridQ.Set(Q->vert.begin(),Q->vert.end());
00181   ugridP.Set(P->vert.begin(),P->vert.end());
00182 
00183   if(par.samplingRadius==0)
00184     par.samplingRadius = tri::ComputePoissonDiskRadius(*P,par.sampleNumP);
00185   tri::PoissonPruning(*P, subsetP, par.samplingRadius, par.seed);
00186   tri::PoissonPruning(*Q, subsetQ, par.samplingRadius, par.seed);
00187   par.deltaAbs = par.samplingRadius * par.deltaPerc;
00188   side = P->bbox.Dim()[P->bbox.MaxDim()]*par.overlap; //rough implementation
00189   stat.initTime+=clock()-t0;
00190 }
00191 
00192 
00193 // Try to select four coplanar points such that they are at least side distance and
00194 //
00195 bool SelectCoplanarBase(FourPoints &B, ScalarType &r1, ScalarType &r2)
00196 {
00197   clock_t t0= clock();
00198 
00199   // choose the inter point distance
00200   ScalarType dtol = side*0.1; //rough implementation
00201 
00202 
00203   // **** first point: random
00204   B[0] = P->vert[ rnd.generate(P->vert.size())].P();
00205 
00206   // **** second point: a random point at distance side +-dtol
00207   size_t i;
00208   for(i = 0; i < P->vert.size(); ++i){
00209     int id = rnd.generate(P->vert.size());
00210     ScalarType dd = (P->vert[id].P() - B[0]).Norm();
00211     if(  ( dd < side + dtol) && (dd > side - dtol)){
00212       B[1] = P->vert[id].P();
00213       break;
00214     }
00215   }
00216   if(i ==  P->vert.size()) return false;
00217 
00218   // **** third point: at distance less than side*0.8 from middle way between B[0] and B[1]
00219   const CoordType middle = (B[0]+B[1])/2.0;
00220   for(i = 0; i < P->vert.size(); ++i){
00221     int id = rnd.generate(P->vert.size());
00222     if( Distance(P->vert[id].P(),middle) < side*0.8 ){
00223       B[2] = P->vert[id].P();
00224       break;
00225     }
00226   }
00227   if(i ==  P->vert.size()) return false;
00228 
00229   // **** fourth point:
00230   ScalarType cpr = rnd.generate01();
00231   CoordType crossP = B[0] *(1-cpr)+B[1]*cpr;
00232   CoordType B4 = B[2]+(crossP-B[2]).Normalize()*side;
00233   CoordType n = ((B[0]-B[1]).normalized() ^ (B[2]-B[1]).normalized()).normalized();
00234   ScalarType radius = dtol;
00235 
00236   std::vector<typename MeshType::VertexType*> closests;
00237   std::vector<ScalarType> distances;
00238   std::vector<CoordType> points;
00239 
00240   vcg::tri::GetInSphereVertex<
00241       MeshType,
00242       vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
00243       std::vector<typename MeshType::VertexType*>,
00244       std::vector<ScalarType>,
00245       std::vector<CoordType>
00246       >(*P,ugridP,B4,radius,closests,distances,points);
00247 
00248   if(closests.empty())
00249     return false;
00250   int bestInd = -1;   ScalarType bestv=std::numeric_limits<float>::max();
00251   for(i = 0; i <closests.size(); ++i){
00252     ScalarType dist_from_plane = fabs((closests[i]->P() - B[1]).normalized().dot(n));
00253     if( dist_from_plane < bestv){
00254       bestv = dist_from_plane;
00255       bestInd = i;
00256     }
00257   }
00258   if(bestv >dtol)
00259     return false;
00260   B[3] =  closests[bestInd]->P();
00261 
00262   //printf("B[3] %d\n", (typename MeshType::VertexType*)closests[best] - &(*P->vert.begin()));
00263 
00264   // compute r1 and r2
00265   CoordType x;
00266   //        std::swap(B[1],B[2]);
00267   IntersectionLineLine(B[0],B[1],B[2],B[3],x);
00268 
00269   r1 = (x - B[0]).dot(B[1]-B[0]) / (B[1]-B[0]).SquaredNorm();
00270   r2 = (x - B[2]).dot(B[3]-B[2]) / (B[3]-B[2]).SquaredNorm();
00271 
00272   if( ((B[0]+(B[1]-B[0])*r1)-(B[2]+(B[3]-B[2])*r2)).Norm() > par.deltaAbs )
00273     return false;
00274 
00275   radius  = side*0.5;
00276   std::vector< CoordType > samples;
00277   std::vector<ScalarType > dists;
00278 
00279   for(int i  = 0 ; i< 4; ++i){
00280     vcg::tri::GetKClosestVertex<
00281         MeshType,
00282         vcg::GridStaticPtr<typename MeshType::VertexType, ScalarType >,
00283         std::vector<VertexType*>,
00284         std::vector<ScalarType>,
00285         std::vector< CoordType > >(*P,ugridP, par.feetSize ,B[i],radius, ExtB[i], dists, samples);
00286   }
00287 
00288   //qDebug("ExtB %i",ExtB[0].size()+ExtB[1].size()+ExtB[2].size()+ExtB[3].size());
00289   stat.selectCoplanarBaseTime+=clock()-t0;
00290   return true;
00291 }
00292 
00293 bool IsTransfCongruent(const FourPoints &B, const FourPoints &fp, vcg::Matrix44<ScalarType> & mat)
00294 {
00295   std::vector<vcg::Point3<ScalarType> > fix(4);
00296   std::vector<vcg::Point3<ScalarType> > mov(4);
00297   for(int i = 0 ; i < 4; ++i) {
00298     mov[i]=B[i];
00299     fix[i]=fp[i];
00300   }
00301 
00302   if(fabs( Distance(fix[0],fix[1]) - Distance(mov[0],mov[1]) ) > par.deltaAbs) return false;
00303   if(fabs( Distance(fix[0],fix[2]) - Distance(mov[0],mov[2]) ) > par.deltaAbs) return false;
00304   if(fabs( Distance(fix[0],fix[3]) - Distance(mov[0],mov[3]) ) > par.deltaAbs) return false;
00305   if(fabs( Distance(fix[1],fix[2]) - Distance(mov[1],mov[2]) ) > par.deltaAbs) return false;
00306   if(fabs( Distance(fix[1],fix[3]) - Distance(mov[1],mov[3]) ) > par.deltaAbs) return false;
00307   if(fabs( Distance(fix[2],fix[3]) - Distance(mov[2],mov[3]) ) > par.deltaAbs) return false;
00308 
00309   vcg::ComputeRigidMatchMatrix(fix,mov,mat);
00310 
00311   ScalarType maxSquaredDistance = 0.0;
00312   for(int i = 0; i < 4; ++i)
00313     maxSquaredDistance =std::max(maxSquaredDistance, SquaredDistance(mat * mov[i] ,fix[i]));
00314   return  sqrt(maxSquaredDistance)  < par.deltaAbs;
00315 }
00316 
00319 void ComputeR1(std::vector<Couple > &R1)
00320 {
00321   R1.clear();
00322   for(size_t vi = 0; vi  < subsetQ.size(); ++vi)
00323     for(size_t vj = vi; vj < subsetQ.size(); ++vj){
00324       ScalarType d = Distance(subsetQ[vi]->P(),subsetQ[vj]->P());
00325       if( (d < side+par.deltaAbs))
00326       {
00327         R1.push_back(Couple(subsetQ[vi],subsetQ[vj], d));
00328         R1.push_back(Couple(subsetQ[vj],subsetQ[vi], d));
00329       }
00330     }
00331 
00332   std::sort(R1.begin(),R1.end());
00333 }
00334 
00335 // Find congruent elements of a base B, on Q, with approximation delta
00336 // and put them in the U vector.
00337 bool FindCongruent(const std::vector<Couple > &R1, const FourPoints &B, const ScalarType r1, const ScalarType r2)
00338 {
00339   clock_t t0=clock();
00340   int n_base=0;
00341   bool done = false;
00342   int n_closests = 0, n_congr = 0;
00343   int ac =0 ,acf = 0,tr = 0,trf =0;
00344   ScalarType d1,d2;
00345   d1 = (B[1]-B[0]).Norm();
00346   d2 = (B[3]-B[2]).Norm();
00347 
00348   typename std::vector<Couple>::const_iterator bR1,eR1,bR2,eR2,ite;
00349   bR1 = std::lower_bound(R1.begin(),R1.end(),Couple(0,0,d1-par.deltaAbs));
00350   eR1 = std::lower_bound(R1.begin(),R1.end(),Couple(0,0,d1+par.deltaAbs));
00351   bR2 = std::lower_bound(R1.begin(),R1.end(),Couple(0,0,d2-par.deltaAbs));
00352   eR2 = std::lower_bound(R1.begin(),R1.end(),Couple(0,0,d2+par.deltaAbs));
00353 
00354   // in  [bR1,eR1) there are all the pairs at a distance d1 +- par.delta
00355   // in  [bR1,eR1) there are all the pairs at a distance d2 +- par.delta
00356 
00357   if(bR1 == R1.end()) return false;// if there are no such pairs return
00358   if(bR2 == R1.end()) return false; // if there are no such pairs return
00359 
00360   // put [bR1,eR1) in a mesh to have the search operator for free (lazy me)
00361   Invr.Clear();
00362   typename PMesh::VertexIterator vii;
00363   int i = &(*bR1)-&(*R1.begin());
00364   for(ite = bR1; ite != eR1;++ite){
00365     vii = vcg::tri::Allocator<PMesh>::AddVertices(Invr,1);
00366     //      (*vii).P() = Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r1;
00367     (*vii).P() .Import(         ite->p0->P() + (        ite->p1->P() -       ite->p0->P()) * r1);
00368     ++i;
00369   }
00370   if(Invr.vert.empty() ) return false;
00371 
00372   // per vertex attribute 'index' remaps a vertex of Invr to its corresponding point in R1
00373   typename PMesh::template PerVertexAttributeHandle<int> id = vcg::tri::Allocator<PMesh>::template AddPerVertexAttribute<int>(Invr,std::string("index"));
00374   i = &(*bR1)-&(*R1.begin());
00375   for(vii = Invr.vert.begin(); vii != Invr.vert.end();++vii,++i)  id[vii] = i;
00376 
00377   vcg::tri::UpdateBounding<PMesh>::Box(Invr);
00378 
00379 
00380   std::vector<EPoint> R2inv;
00381   i = &(*bR2)-&(*R1.begin());
00382   // R2inv contains all the points generated by the couples in R2 (with the reference to remap into R2)
00383   for(ite = bR2; ite != eR2;++ite){
00384     //        R2inv.push_back( EPoint( Q->vert[R1[i][0]].P() + (Q->vert[R1[i][1]].P()-Q->vert[R1[i][0]].P()) * r2,i));
00385     R2inv.push_back( EPoint( R1[i].p0->P() + (R1[i].p1->P() - R1[i].p0->P()) * r2,i));
00386     ++i;
00387   }
00388 
00389   GridType ugrid; // griglia
00390   ugrid.Set(Invr.vert.begin(),Invr.vert.end());
00391   n_closests = 0; n_congr = 0; ac =0 ; acf = 0; tr = 0; trf = 0;
00392   printf("R2Inv.size  = %d \n",R2inv.size());
00393   for(unsigned int i = 0 ; i < R2inv.size() ; ++i)
00394   {
00395     std::vector<typename PMesh::VertexType*> closests;
00396 
00397     // for each point in R2inv get all the points in R1 closer than par.delta
00398     vcg::Matrix44<ScalarType> mat;
00399     Box3x bb;
00400     bb.Add(R2inv[i].pos+CoordType(par.deltaAbs,par.deltaAbs, par.deltaAbs));
00401     bb.Add(R2inv[i].pos-CoordType(par.deltaAbs,par.deltaAbs, par.deltaAbs));
00402 
00403     vcg::tri::GetInBoxVertex<PMesh,GridType,std::vector<typename PMesh::VertexType*> >
00404         (Invr,ugrid,bb,closests);
00405 
00406     if(closests.size() > 5)
00407       closests.resize(5);
00408 
00409     n_closests+=closests.size();
00410     for(unsigned int ip = 0; ip < closests.size(); ++ip)
00411     {
00412       FourPoints p;
00413       p[0] = R1[id[closests[ip]]][0]->cP();
00414       p[1] = R1[id[closests[ip]]][1]->cP();
00415       p[2] = R1[ R2inv[i].pi][0]->cP();
00416       p[3] = R1[ R2inv[i].pi][1]->cP();
00417 
00418       n_base++;
00419       if(!IsTransfCongruent(B,p,mat)) {
00420         trf++;
00421       }
00422       else{
00423         tr++;
00424         n_congr++;
00425         Candidate c(p,mat);
00426         EvaluateAlignment(c);
00427 
00428         if( c.score > par.scoreFeet)
00429           U.push_back(c);
00430       }
00431     }
00432   }
00433 
00434   vcg::tri::Allocator<PMesh>::DeletePerVertexAttribute(Invr,id);
00435   printf("n_closests %5d = (An %5d ) + ( Tr %5d ) + (OK) %5d\n",n_closests,acf,trf,n_congr);
00436 
00437   stat.findCongruentTime += clock()-t0;
00438   return done;
00439 }
00440 
00441 
00442 int EvaluateSample(Candidate & fp, const CoordType & tp, const CoordType & np)
00443 {
00444   CoordType ttp = fp.T * tp;
00445   vcg::Point4<ScalarType> np4 = fp.T * vcg::Point4<ScalarType>(np[0],np[1],np[2],0.0);
00446   CoordType tnp(np4[0],np4[1],np4[2]);
00447 
00448   ScalarType   dist ;
00449   VertexType* v = vcg::tri::GetClosestVertex(*Q, ugridQ, ttp, par.deltaAbs*2.0,  dist  );
00450 
00451   if(v!=0)
00452   {
00453     if( v->N().dot(tnp) > par.cosAngle )  return 1;
00454     else return -1;
00455   }
00456   else return 0;
00457 }
00458 
00459 // Check a candidate against the small subset of points ExtB
00460 void EvaluateAlignment(Candidate  & fp){
00461         int n_delta_close = 0;
00462         for(int i  = 0 ; i< 4; ++i) {
00463             for(unsigned int j = 0; j < ExtB[i].size();++j){
00464                 n_delta_close+=EvaluateSample(fp, ExtB[i][j]->P(), ExtB[i][j]->cN());
00465             }
00466         }
00467         fp.score = n_delta_close;
00468 }
00469 
00470 void TestAlignment(Candidate  & fp)
00471 {
00472   clock_t t0 = clock();
00473   int n_delta_close = 0;
00474   for(unsigned int j = 0; j < subsetP.size();++j){
00475     CoordType np = subsetP[j]->N();
00476     CoordType tp = subsetP[j]->P();
00477     n_delta_close+=EvaluateSample(fp,tp,np);
00478   }
00479   fp.score =  n_delta_close;
00480   stat.testAlignmentTime += clock()-t0;
00481 }
00482 
00483 
00484 bool Align(Matrix44x & result, vcg::CallBackPos * cb )
00485 {
00486   int maxAttempt =100;
00487   int scoreThr = par.sampleNumP*0.8;
00488 
00489   Candidate bestC;
00490 
00491   std::vector<Couple > R1;
00492   ComputeR1(R1);
00493   for(int i  = 0; i  < maxAttempt && bestC.score<scoreThr ; ++i )
00494   {
00495     FourPoints B;
00496     ScalarType r1,r2;
00497     if(SelectCoplanarBase(B,r1,r2))
00498     {
00499       U.clear();
00500       FindCongruent(R1,B,r1,r2);
00501       qDebug("Attempt %i found %i candidate best score %i",i,U.size(),bestC.score);
00502       for(size_t i = 0 ; i <  U.size() ;++i)
00503       {
00504         TestAlignment(U[i]);
00505         if(U[i].score > bestC.score)
00506           bestC = U[i];
00507       }
00508     }
00509   }
00510   result = bestC.T;
00511   return bestC.score >0;
00512 }
00513 
00514 bool Align(int L, Matrix44x & result, vcg::CallBackPos * cb )
00515 {
00516     int bestv = 0;
00517     bool found;
00518     int n_tries = 0;
00519     U.clear();
00520 
00521     if(L==0)
00522     {
00523         // overlap is expressed as the probability that a point in P(mov) can be found in Q (fix)
00524         L = (log(1.0-0.9) / log(1.0-pow((float)par.overlap,3.f)))+1;
00525         printf("using %d bases\n",L);
00526     }
00527     std::vector<Couple > R1;
00528     ComputeR1(R1);
00529 
00530     for(int t  = 0; t  < L; ++t )
00531     {
00532       FourPoints B;
00533       ScalarType r1,r2;
00534       do
00535       {
00536         n_tries = 0;
00537         do
00538         {
00539           n_tries++;
00540           found = SelectCoplanarBase(B,r1,r2);
00541         }
00542         while(!found && (n_tries < 50));
00543         if(!found) {
00544           par.overlap*=0.9;
00545           side = P->bbox.Dim()[P->bbox.MaxDim()]*par.overlap; //rough implementation
00546           ComputeR1(R1);
00547         }
00548       } while (!found && (par.overlap >0.1));
00549 
00550       if(par.overlap < 0.1) {
00551         printf("FAILED");
00552         return false;
00553       }
00554       bases.push_back(B);
00555       if(cb) cb(t*100/L,"Trying bases");
00556       if(FindCongruent(R1,B,r1,r2))
00557         break;
00558     }
00559 
00560     if(U.empty()) return false;
00561 
00562 //    std::sort(U.begin(),U.end());
00563     if(cb) cb(90,"TestAlignment");
00564     bestv  = -std::numeric_limits<float>::max();
00565     iwinner = 0;
00566 
00567     for(int i = 0 ; i <  U.size() ;++i)
00568      {
00569         TestAlignment(U[i]);
00570         if(U[i].score > bestv){
00571             bestv = U[i].score;
00572             iwinner = i;
00573             }
00574     }
00575 
00576     result = U[iwinner].T;
00577     Invr.Clear();
00578     return true;
00579 }
00580 
00581 }; // end class
00582 
00583 } // namespace tri
00584 } // namespace vcg
00585 #endif


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