poisson_solver.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 
00024 #ifndef VCG_POISSON_SOLVER
00025 #define VCG_POISSON_SOLVER
00026 
00027 #include <eigenlib/Eigen/Sparse>
00028 
00029 #include <vcg/complex/algorithms/clean.h>
00030 #include <vcg/complex/algorithms/update/bounding.h>
00031 #include <vcg/complex/algorithms/parametrization/distortion.h>
00032 #include <vcg/complex/algorithms/parametrization/uv_utils.h>
00033 
00034 namespace vcg {
00035 namespace tri{
00036 template <class MeshType>
00037 class PoissonSolver
00038 {
00039 
00040     typedef typename MeshType::ScalarType ScalarType;
00041     typedef typename MeshType::FaceType FaceType;
00042     typedef typename MeshType::VertexType VertexType;
00043     typedef typename MeshType::CoordType CoordType;
00044     typedef typename MeshType:: template PerFaceAttributeHandle<CoordType> PerFaceCoordHandle;
00045 
00047     MeshType &mesh;
00048 
00050 
00051     std::map<VertexType*,int> VertexToInd;
00052     std::map<int, VertexType*> IndToVertex;
00053 
00055     std::vector<VertexType *> to_fix;
00056 
00058 
00059     Eigen::SparseMatrix<double> A; // A
00060     Eigen::VectorXd b,x;// x and b
00061 
00062     //number of variables
00063     unsigned int n_vert_vars;
00065     unsigned int total_size;
00067     unsigned int n_fixed_vars;
00068 
00070     bool use_direction_field,fix_selected,correct_fixed;
00072     ScalarType fieldScale;
00073 //    ///handle per direction field
00074 //    PerFaceCoordHandle Fh0,Fh1;
00075 
00076     int VertexIndex(VertexType* v)
00077     {
00078         typename std::map<VertexType*,int>::iterator iteMap=VertexToInd.find(v);
00079         assert(iteMap!=VertexToInd.end());
00080         return ((*iteMap).second);
00081     }
00082 
00083     VertexType* IndexVertex(int index)
00084     {
00085         typename std::map<int,VertexType*>::iterator iteMap=IndToVertex.find(index);
00086         assert(iteMap!=IndToVertex.end());
00087         return ((*iteMap).second);
00088     }
00089 
00090     void AddVertexIndex(VertexType* v,int index)
00091     {
00092         VertexToInd.insert(std::pair<VertexType*,int>(v,index));
00093         IndToVertex.insert(std::pair<int,VertexType*>(index,v));
00094     }
00096     void SetValA(int Xindex,int Yindex,ScalarType val)
00097     {
00098         //int size=(int)S.nrows();
00099         assert(0 <= Xindex && Xindex < int(total_size));
00100         assert(0 <= Yindex && Yindex < int(total_size));
00101         //S.A().addEntryReal(Xindex,Yindex,val);
00102         //if (Xindex>=Yindex)
00103         A.coeffRef(Xindex,Yindex) +=val;
00104 
00105     }
00106 
00107 
00108     void FindFarthestVert(VertexType* &v0,VertexType* &v1)
00109     {
00110         UpdateBounding<MeshType>::Box(mesh);
00111 
00112         tri::UpdateTopology<MeshType>::FaceFace(mesh);
00113         tri::UpdateFlags<MeshType>::FaceBorderFromFF(mesh);
00114         tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(mesh);
00115 
00116         ScalarType dmax=0;
00117         v0=NULL;
00118         v1=NULL;
00119         for (unsigned int i=0;i<mesh.vert.size();i++)
00120             for (unsigned int j=(i+1);j<mesh.vert.size();j++)
00121             {
00122                 VertexType *vt0=&mesh.vert[i];
00123                 VertexType *vt1=&mesh.vert[j];
00124                 if (vt0->IsD())continue;
00125                 if (vt1->IsD())continue;
00126                 if (!vt0->IsB())continue;
00127                 if (!vt1->IsB())continue;
00128                 ScalarType d_test=(vt0->P()-vt1->P()).Norm();
00129 //                ScalarType Dx=fabs(vt0->P().X()-vt1->P().X());
00130 //                ScalarType Dy=fabs(vt0->P().Y()-vt1->P().Y());
00131 //                ScalarType Dz=fabs(vt0->P().Z()-vt1->P().Z());
00132 
00133                 //ScalarType d_test=std::max(Dx,std::max(Dy,Dz));
00134                 //ScalarType d_test=std::max(fabs(Dx-Dy),std::max(fabs(Dx-Dz),fabs(Dy-Dz)));
00135                 if (d_test>dmax)
00136                 {
00137                     dmax=d_test;
00138                     v0=vt0;
00139                     v1=vt1;
00140                 }
00141             }
00142         assert(v0!=NULL);
00143         assert(v1!=NULL);
00144     }
00145 
00147     void SetValB(int Xindex,
00148                  ScalarType val)
00149     {
00150         /*S.b()[Xindex] += val;*/
00151         b[Xindex] += val;
00152     }
00153 
00156     void AddAreaTerm(int index[3][3][2],ScalarType ScaleFactor)
00157     {
00158         const ScalarType entry=0.5*ScaleFactor;
00159         ScalarType val[3][3]= { {0,  entry, -entry},
00160                                 {-entry,  0,  entry},
00161                                 {entry, -entry,  0} };
00162 
00163         for (int i=0;i<3;i++)
00164             for (int j=0;j<3;j++)
00165             {
00167                 int Xindex=index[i][j][0]*2;
00168                 int Yindex=index[i][j][1]*2;
00169 
00170                 SetValA(Xindex+1,Yindex,-val[i][j]);
00171                 SetValA(Xindex,Yindex+1,val[i][j]);
00172 
00173             }
00174     }
00175 
00178     void SetDiagonal(ScalarType val[3][3])
00179     {
00180         for (int i=0;i<3;i++)
00181         {
00182             ScalarType sum=0;
00183             for (int j=0;j<3;j++)
00184                 sum+=val[i][j];
00185             val[i][i]=-sum;
00186         }
00187     }
00188 
00190     void AddRHS(ScalarType b[6],
00191                 int index[3])
00192     {
00193         for (int i=0;i<3;i++)
00194         {
00195             ScalarType valU=b[i*2];
00196             ScalarType valV=b[(i*2)+1];
00197             SetValB((index[i]*2),valU);
00198             SetValB((index[i]*2)+1,valV);
00199         }
00200     }
00201 
00205     void Add33Block(ScalarType val[3][3],int index[3][3][2])
00206     {
00207         for (int i=0;i<3;i++)
00208             for (int j=0;j<3;j++)
00209             {
00211                 int Xindex=index[i][j][0]*2;
00212                 int Yindex=index[i][j][1]*2;
00213                 assert(Xindex<int(n_vert_vars*2));
00214                 assert(Yindex<int(n_vert_vars*2));
00215                 SetValA(Xindex,Yindex,val[i][j]);
00216                 SetValA(Xindex+1,Yindex+1,val[i][j]);
00217             }
00218 
00219     }
00220 
00224     void Add44Block(ScalarType val[4][4],int index[4][4][2])
00225     {
00226         for (int i=0;i<4;i++)
00227             for (int j=0;j<4;j++)
00228             {
00230                 int Xindex=index[i][j][0]*2;
00231                 int Yindex=index[i][j][1]*2;
00232                 assert(Xindex<(n_vert_vars*2));
00233                 assert(Yindex<(n_vert_vars*2));
00234                 SetValA(Xindex,Yindex,val[i][j]);
00235                 SetValA(Xindex+1,Yindex+1,val[i][j]);
00236             }
00237 
00238     }
00239 
00241     void perElementLHS(FaceType *f,
00242                        ScalarType val[3][3],
00243                        int index[3][3][2])
00244     {
00246         for (int x=0;x<3;x++)
00247             for (int y=0;y<3;y++)
00248                 val[x][y]=0;
00249 
00251         VertexType *v[3];
00252         v[0]=f->V(0);
00253         v[1]=f->V(1);
00254         v[2]=f->V(2);
00255 
00258         int Vindexes[3];
00259         Vindexes[0]=VertexIndex(f->V(0));
00260         Vindexes[1]=VertexIndex(f->V(1));
00261         Vindexes[2]=VertexIndex(f->V(2));
00262 
00264         for (int x=0;x<3;x++)
00265             for (int y=0;y<3;y++)
00266             {
00267                 index[x][y][0]=Vindexes[x];
00268                 index[x][y][1]=Vindexes[y];
00269             }
00270 
00272         CoordType e[3];
00273         for (int k=0;k<3;k++)
00274             e[k]=v[(k+2)%3]->P()-v[(k+1)%3]->P();
00275 
00277         ScalarType areaT=((f->P(1)-f->P(0))^(f->P(2)-f->P(0))).Norm()/2.0;
00278          for (int x=0;x<3;x++)
00279             for (int y=0;y<3;y++)
00280                 if (x!=y)
00281                 {
00282                     ScalarType num=(e[x]*e[y]);
00283                     val[x][y] =num/(4.0*areaT);
00284                 }
00285 
00287         SetDiagonal(val);
00288     }
00289 
00291     void perElementRHS(FaceType *f,
00292                        ScalarType b[6],
00293                        ScalarType vector_field_scale=1)
00294     {
00295 
00297         CoordType scaled_Kreal;
00298         CoordType scaled_Kimag;
00299         CoordType fNorm=f->N();
00300         fNorm.Normalize();
00301         CoordType p[3];
00302         p[0]=f->P0(0);
00303         p[1]=f->P0(1);
00304         p[2]=f->P0(2);
00305 
00306         CoordType neg_t[3];
00307         neg_t[0] = fNorm ^ (p[2] - p[1]);
00308         neg_t[1] = fNorm ^ (p[0] - p[2]);
00309         neg_t[2] = fNorm ^ (p[1] - p[0]);
00310 
00311         CoordType K1,K2;
00312         /*MyMesh::PerFaceCoordHandle<ScalarType> Fh = tri::Allocator<MyMesh>::AddPerVertexAttribute<float>  (m,std::string("Irradiance"));
00313         bool CrossDir0 = tri::HasPerVertexAttribute(mesh,"CrossDir0");
00314                 bool CrossDir1 = tri::HasPerVertexAttribute(mesh,"CrossDir1");
00315                 assert(CrossDir0);
00316                 assert(CrossDir1);*/
00317 
00318         //K1=f->Q3();
00319         K1=f->PD1();
00320         K1.Normalize();
00321         //K2=fNorm^K1;
00322         K2=f->PD2();
00323         K2.Normalize();
00324 
00325         scaled_Kreal = K1*(vector_field_scale);
00326         scaled_Kimag = K2*(vector_field_scale);
00327 
00328         b[0] = scaled_Kreal * neg_t[0];
00329         b[1] = scaled_Kimag * neg_t[0];
00330         b[2] = scaled_Kreal * neg_t[1];
00331         b[3] = scaled_Kimag * neg_t[1];
00332         b[4] = scaled_Kreal * neg_t[2];
00333         b[5] = scaled_Kimag * neg_t[2];
00334 
00335     }
00336 
00338     void PerElementSystemReal(FaceType *f,
00339                               ScalarType val[3][3],
00340                               int index[3][3][2],
00341                               ScalarType b[6],
00342                               ScalarType vector_field_scale=1.0)
00343     {
00344         perElementLHS(f,val,index);
00345 
00346         if (use_direction_field)
00347             perElementRHS(f,b,vector_field_scale);
00348     }
00349 
00350     void FixPointLSquares()
00351     {
00352         ScalarType penalization=1000000;
00353         int offset_row=n_vert_vars;
00354         assert(to_fix.size()>0);
00355         for (size_t i=0;i<to_fix.size();i++)
00356         {
00358             VertexType *v=to_fix[i];
00359             assert(!v->IsD());
00360             int index=VertexIndex(v);
00361             //v->vertex_index[0];
00362             int indexvert=index*2;
00363             int indexRow=(offset_row+i)*2;
00364 
00365             SetValA(indexRow,indexRow,penalization);
00366             SetValA(indexRow+1,indexRow+1,penalization);
00367 
00369             ScalarType U=v->T().U()*penalization;
00370             ScalarType V=v->T().V()*penalization;
00371             SetValB(indexRow,U);
00372             SetValB(indexRow+1,V);
00373 
00374             /*///set upper right part
00375             SetValA(indexvert,indexCol,penalization);
00376             SetValA(indexvert+1,indexCol+1,penalization);*/
00377 
00378             SetValA(indexvert,indexvert,penalization);
00379             SetValA(indexvert+1,indexvert+1,penalization);
00380             SetValA(indexRow,indexRow,penalization);
00381             SetValA(indexRow+1,indexRow+1,penalization);
00382             SetValA(indexvert,indexRow,-penalization);
00383             SetValA(indexvert+1,indexRow+1,-penalization);
00384             SetValA(indexRow,indexvert,-penalization);
00385             SetValA(indexRow+1,indexvert+1,-penalization);
00386             //SetValA(indexCol+1,indexCol+1,-1);
00387         }
00388     }
00389 
00390     //build the laplacian matrix cyclyng over all rangemaps
00391     //and over all faces
00392     void BuildLaplacianMatrix(double vfscale=1)
00393     {
00394 
00396         for (unsigned int j=0;j<mesh.face.size();j++)
00397         {
00398 
00399             FaceType *f=&mesh.face[j];
00400             if (f->IsD())
00401                 continue;
00402 
00403             int var_idx[3];//vertex variable indices
00404             for(int k = 0; k < 3; ++k)
00405             {
00406                 VertexType *v=f->V(k);
00407                 var_idx[k] = VertexIndex(v);
00408             }
00409             ScalarType val[3][3];
00410             int index[3][3][2];
00411             ScalarType b[6];
00412             PerElementSystemReal(f, val,index, b, vfscale);
00413 
00414             //Add the element to the matrix
00415             Add33Block(val,index);
00416 
00418             /*if (!use_direction_field)
00419                 AddAreaTerm(index,1.0);//f->area);*/
00420             /*ScalarType area=((f->P(1)-f->P(0))^(f->P(2)-f->P(0))).Norm();
00421             if (!use_direction_field)
00422                 AddAreaTerm(index,area);*/
00423 
00424             //ScalarType area=((f->P(1)-f->P(0))^(f->P(2)-f->P(0))).Norm();
00425             if (!use_direction_field)
00426                 AddAreaTerm(index,1);
00427 
00429             if (use_direction_field)
00430                 AddRHS(b,var_idx);
00431         }
00432     }
00433 
00434 
00435     void FindSizes()
00436     {
00437         // tag vertices and compute numbers of equations to determine the number of rows in the matrix
00438         //TagVertices_Constrained(n_vert_vars, n_transition_eqs, n_align_sharp_eqs);
00439         n_vert_vars=mesh.vn;
00440 
00442         total_size = (n_fixed_vars + n_vert_vars)*2;
00443 
00444     }
00445 
00446     void AllocateSystem()
00447     {
00448         //--- Allocates the data for Ax=b
00449         A=Eigen::SparseMatrix<double>(total_size, total_size); // A
00450         b = Eigen::VectorXd::Zero(total_size);  // x and b
00451     }
00452 
00453 
00454 
00456     void InitMatrix()
00457     {
00458         FindSizes();
00459         AllocateSystem();
00460     }
00461 
00462     bool Solve()
00463     {
00464         //return true;
00465         A.finalize();
00466         Eigen::SparseMatrix<double> As=Eigen::SparseMatrix<double>(A);
00467         As.finalize();
00468 
00469         Eigen::SimplicialCholesky<Eigen::SparseMatrix<double> > solver(As);
00470         x = solver.solve(b);
00471         return (solver.info()==Eigen::Success);
00472     }
00473 
00474 
00475     void InitIndex()
00476     {
00477         for (size_t i=0;i<mesh.vert.size();i++)
00478             if (!mesh.vert[i].IsD())
00479                 AddVertexIndex(&mesh.vert[i],i);
00480     }
00481 
00485     void MapCoords(bool normalize=true,
00486                    ScalarType /*fieldScale*/=1.0)
00487     {
00489         if (correct_fixed)
00490             tri::UpdateFlags<MeshType>::VertexClearV(mesh);
00491         //set fixed to V
00492         for (size_t i=0;i<to_fix.size();i++)
00493             to_fix[i]->SetV();
00494 
00495         Box2<ScalarType> bbox;
00496         if (normalize)
00497         {
00498             for (size_t i=0;i<n_vert_vars;i++)
00499             {
00500                 ScalarType U=x[i*2];
00501                 ScalarType V=x[(i*2)+1];
00502                 bbox.Add(Point2<ScalarType>(U,V));
00503             }
00504         }
00505 
00506         //for each vertex
00507         for (size_t i=0;i<n_vert_vars;i++)
00508         {
00509             VertexType* v=IndexVertex(i);
00510             //take U and V
00511             ScalarType U=x[i*2];
00512             ScalarType V=x[(i*2)+1];
00513             Point2<ScalarType> p;
00514             if (!v->IsV())
00515                 p=Point2<ScalarType>(U,V);
00516             else
00517                 p=v->T().P();
00518             //p/=fieldScale;
00519             if  (normalize)
00520             {
00521                 p-=bbox.min;
00522                 p*=1/bbox.Diag();
00523             }
00524 
00525             v->T().P()=p;
00526         }
00527 
00529         for (size_t i=0;i<mesh.face.size();i++)
00530         {
00531             FaceType *f=&mesh.face[i];
00532             for (int j=0;j<3;j++)
00533             {
00534                 VertexType* v=f->V(j);
00535                 Point2<ScalarType> p=v->T().P();
00536                 f->WT(j).P()=p;
00537             }
00538         }
00539     }
00540 
00541 public:
00542 
00544     bool IsFeaseable()
00545     {
00546         tri::UpdateTopology<MeshType>::FaceFace(mesh);
00547         int NNmanifoldE=tri::Clean<MeshType>::CountNonManifoldEdgeFF(mesh);
00548         if (NNmanifoldE!=0)
00549         {
00550             printf("Non Manifold Edges \n");
00551             return false;
00552         }
00553         int NNmanifoldV=tri::Clean<MeshType>::CountNonManifoldVertexFF(mesh);
00554         if (NNmanifoldV!=0)
00555         {
00556             printf("Non Manifold Vertices \n");
00557             return false;
00558         }
00559         int H=tri::Clean<MeshType>::CountHoles(mesh);
00560         if (H==0)return false;
00561 
00562         int G=tri::Clean<MeshType>::MeshGenus(mesh);
00563         if (G!=0)
00564         {
00565             printf("Genus %d\n",G);
00566             return false;
00567         }
00568 
00569         return (true);
00570     }
00571 
00573     void SetBorderAsFixed()
00574     {
00575         for (size_t i=0;i<mesh.vert.size();i++)
00576         {
00577             VertexType* v=&mesh.vert[i];
00578             if (v->IsD())continue;
00579             if(v->IsB())to_fix.push_back(v);
00580         }
00581         std::sort(to_fix.begin(),to_fix.end());
00582         typename std::vector<VertexType*>::iterator new_end=std::unique(to_fix.begin(),to_fix.end());
00583         int dist=distance(to_fix.begin(),new_end);
00584         to_fix.resize(dist);
00585     }
00586 
00588     void SetSelectedAsFixed()
00589     {
00590         for (int i=0;i<mesh.vert.size();i++)
00591         {
00592             VertexType* v=&mesh.vert[i];
00593             if (v->IsD())continue;
00594             if(v->IsS())to_fix.push_back(v);
00595         }
00596         std::sort(to_fix.begin(),to_fix.end());
00597         typename std::vector<VertexType*>::iterator new_end=std::unique(to_fix.begin(),to_fix.end());
00598         int dist=distance(to_fix.begin(),new_end);
00599         to_fix.resize(dist);
00600     }
00601 
00602 
00606     void FixDefaultVertices()
00607     {
00609         assert(to_fix.size()==0);
00611         if (use_direction_field)
00612         {
00613             for (size_t i=0;i<mesh.vert.size();i++)
00614                 if (!mesh.vert[i].IsD())
00615                 {
00616                     mesh.vert[i].T().P()=Point2<ScalarType>(0,0);
00617                     to_fix.push_back(&mesh.vert[i]);
00618                     return;
00619                 }
00620         }
00622         else
00623         {
00624             VertexType *v0;
00625             VertexType *v1;
00626             FindFarthestVert(v0,v1);
00627             if (v0==v1)
00628             {
00629                 //                              tri::io::ExporterPLY<MeshType>::Save(mesh,"./parametrized.ply");
00630                 assert(0);
00631             }
00632             v0->T().P()=Point2<ScalarType>(0,0);
00633             v1->T().P()=Point2<ScalarType>(1,1);
00634             to_fix.push_back(v0);
00635             to_fix.push_back(v1);
00636             return;
00637         }
00638     }
00640     void Init(bool _use_direction_field=false,
00641               bool _correct_fixed=true,
00642               ScalarType _fieldScale=1.0)
00643     {
00644         use_direction_field=_use_direction_field;
00645         //query if an attribute is present or not
00646 //        if (use_direction_field)
00647 //        {
00648 //            bool CrossDir0 = tri::HasPerFaceAttribute(mesh,"CrossDir0");
00649 //            bool CrossDir1 = tri::HasPerFaceAttribute(mesh,"CrossDir1");
00650 //            assert(CrossDir0);
00651 //            assert(CrossDir1);
00652 //            Fh0= tri::Allocator<MeshType> :: template GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
00653 //            Fh1= tri::Allocator<MeshType> :: template GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir1"));
00654 //        }
00655         correct_fixed=_correct_fixed;
00656         fieldScale=_fieldScale;
00657         to_fix.clear();
00658     }
00659 
00661     bool SolvePoisson(bool _write_messages=false,
00662                       ScalarType fieldScale=1.0,
00663                       bool solve_global_fold=true)
00664     {
00665         int t0,t1,t2,t3;
00666 
00668         if (_write_messages)
00669         {
00670             printf("\n INITIALIZING THE MATRIX \n");
00671             t0=clock();
00672         }
00673 
00675         InitIndex();
00676 
00677         /*///find vertex to fix
00678         std::vector<VertexType *> to_fix;
00679         FindFixedVertices(to_fix);
00680         n_fixed_vars=to_fix.size();*/
00681         if (use_direction_field)
00682         {
00683             assert(to_fix.size()>0);
00684         }
00685         else
00686         {
00687             assert(to_fix.size()>1);
00688         }
00689 
00690         n_fixed_vars=to_fix.size();
00692         InitMatrix();
00693 
00694         if (use_direction_field)
00695         {
00696             bool CrossDir0 = tri::HasPerFaceAttribute(mesh,"CrossDir0");
00697             bool CrossDir1 = tri::HasPerFaceAttribute(mesh,"CrossDir1");
00698             assert(CrossDir0);
00699             assert(CrossDir1);
00700         }
00701 
00703         BuildLaplacianMatrix(fieldScale);
00704 
00706         FixPointLSquares();
00707 
00708         if (_write_messages)
00709         {
00710             t1=clock();
00711             printf("\n time:%d \n",t1-t0);
00712             printf("\n SOLVING \n");
00713         }
00714 
00715         //int n_vars=(n_vert_vars)*2;
00716         //int integer_constr_size=(n_transition_vars+n_fixed_vars+n_bary_transition_vars)*2;
00717         //X=std::vector< double >(n_vars+n_fixed_vars*2);
00718         bool done=Solve();
00719         if (!done)
00720             return false;
00721         if (_write_messages)
00722         {
00723             t2=clock();
00724             printf("\n time:%d \n",t2-t1);
00725             printf("\n ASSIGNING COORDS \n");
00726         }
00727 
00728         MapCoords(true,fieldScale);
00729         if (_write_messages)
00730         {
00731             t3=clock();
00732             printf("\n time:%d \n",t3-t2);
00733         }
00734 
00736         if (!solve_global_fold) return true;
00737         if (tri::Distortion<MeshType,false>::GloballyUnFolded(mesh))
00738         {
00739             tri::UV_Utils<MeshType>::GloballyMirrorX(mesh);
00740             bool isUnfolded = tri::Distortion<MeshType,false>::GloballyUnFolded(mesh);
00741             assert( ! isUnfolded);
00742         }
00743         return true;
00744     }
00745 
00746     PoissonSolver(MeshType &_mesh):mesh(_mesh)
00747     {
00748         assert(mesh.vert.size()>3);
00749         assert(mesh.face.size()>1);
00750     }
00751 
00752 
00753 }; // end class
00754 } //End Namespace Tri
00755 } // End Namespace vcg
00756 #endif


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