00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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;
00060 Eigen::VectorXd b,x;
00061
00062
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
00074
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
00099 assert(0 <= Xindex && Xindex < int(total_size));
00100 assert(0 <= Yindex && Yindex < int(total_size));
00101
00102
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
00130
00131
00132
00133
00134
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
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
00313
00314
00315
00316
00317
00318
00319 K1=f->PD1();
00320 K1.Normalize();
00321
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
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
00375
00376
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
00387 }
00388 }
00389
00390
00391
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];
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
00415 Add33Block(val,index);
00416
00418
00419
00420
00421
00422
00423
00424
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
00438
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
00449 A=Eigen::SparseMatrix<double>(total_size, total_size);
00450 b = Eigen::VectorXd::Zero(total_size);
00451 }
00452
00453
00454
00456 void InitMatrix()
00457 {
00458 FindSizes();
00459 AllocateSystem();
00460 }
00461
00462 bool Solve()
00463 {
00464
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 =1.0)
00487 {
00489 if (correct_fixed)
00490 tri::UpdateFlags<MeshType>::VertexClearV(mesh);
00491
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
00507 for (size_t i=0;i<n_vert_vars;i++)
00508 {
00509 VertexType* v=IndexVertex(i);
00510
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
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
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
00646
00647
00648
00649
00650
00651
00652
00653
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
00678
00679
00680
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
00716
00717
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 };
00754 }
00755 }
00756 #endif