DGtal  1.5.beta
exampleBunnyHead.cpp
1 
25 #include <iostream>
26 #include <string>
27 #include <DGtal/base/Common.h>
28 #include <DGtal/helpers/StdDefs.h>
29 #include <DGtal/helpers/Shortcuts.h>
30 #include <DGtal/helpers/ShortcutsGeometry.h>
31 #include <DGtal/shapes/SurfaceMesh.h>
32 #include <DGtal/geometry/surfaces/DigitalSurfaceRegularization.h>
33 
34 #include <DGtal/dec/PolygonalCalculus.h>
35 #include <DGtal/dec/GeodesicsInHeat.h>
36 #include <DGtal/dec/VectorsInHeat.h>
37 
38 #include <DGtal/math/linalg/DirichletConditions.h>
39 
40 #include <DGtal/shapes/Mesh.h>
41 #include <DGtal/io/readers/MeshReader.h>
42 
43 #include <polyscope/polyscope.h>
44 #include <polyscope/surface_mesh.h>
45 #include <polyscope/curve_network.h>
46 #include <Eigen/Dense>
47 #include <Eigen/Sparse>
48 
49 #include "ConfigExamples.h"
50 
51 using namespace DGtal;
52 using namespace Z3i;
53 
54 // Using standard 3D digital space.
57 // The following typedefs are useful
59 typedef SurfMesh::Face Face;
60 typedef SurfMesh::Vertex Vertex;
61 
63 typedef std::vector<Vertex> chain;
65 typedef Conditions::IntegerVector IntegerVector;
68 typedef PC::Solver Solver;
69 
70 //Polyscope global
71 polyscope::SurfaceMesh *psMesh;
73 float scale = 10;
75 int nbSources=1;
76 std::vector< std::vector<SurfMesh::Index> > faces;
77 std::vector<RealPoint> positions;
78 
79 //DEC
80 PC *calculus;
81 
82 
83 
90 std::pair<PC::Vector,PC::Vector> FixBoundaryParametrization(const std::vector<Vertex>& boundary)
91 {
92  auto nb = boundary.size();
93  auto n = surfmesh.nbVertices();
94  PC::Vector u = PC::Vector::Zero(n);
95  PC::Vector v = PC::Vector::Zero(n);
96  double totalBoundaryLength = 0;
97  for (Vertex i = 0;i<nb;i++)
98  totalBoundaryLength += surfmesh.distance(boundary[(i+1)%nb],boundary[i]);
99 
100  double partialSum = 0;
101  for (Vertex i = 0;i<nb;i++)
102  {
103  double th = 2*M_PI*partialSum/totalBoundaryLength;
104  auto vi = boundary[i];
105  auto vj = boundary[(i+1)%nb];
106  u(vi) = std::cos(th);
107  v(vj) = std::sin(th);
108  partialSum += surfmesh.distance(vi,vj);
109  }
110  return {u,v};
111 }
112 
118 void VisualizeParametrizationOnCircle(const DenseMatrix& UV)
119 {
120  auto n= surfmesh.nbVertices();
121  std::vector<RealPoint> pos(n);
122  double scale = 0;
123  RealPoint avg = {0.,0.,0.};
124  for (size_t v = 0;v<n;v++)
125  {
126  auto p = surfmesh.position(v);
127  avg += p;
128  if (p.norm() > scale)
129  scale = p.norm();
130  }
131  avg /= surfmesh.nbVertices();
132  scale /= 2;
133  for (size_t v = 0;v<n;v++)
134  pos[v] = RealPoint{scale*UV(v,0),scale*UV(v,1),0.} + avg;
135  polyscope::registerSurfaceMesh("On circle parametrization", pos, faces)->setEnabled(false);
136 }
137 
144 DenseMatrix HarmonicParametrization()
145 {
146  auto n = surfmesh.nbVertices();
147 
148  std::cout<<"Nb boundary edges = "<< surfmesh.computeManifoldBoundaryEdges().size()<<std::endl;
149  std::vector<chain> chains = surfmesh.computeManifoldBoundaryChains();
150  //choose longest chain as boundary of the parametrization
151  std::cout<<"Nb boundaries = "<< chains.size() << std::endl;
152 
153  auto B = *std::max_element(chains.begin(),chains.end(),[] (const chain& A,const chain& B) {return A.size() < B.size();});
154 
155  //Visualization of the boundary edges
156  std::vector<RealPoint> pos;
157  for(const auto v: B)
158  pos.push_back(surfmesh.position(v));
159  polyscope::registerCurveNetworkLoop("Longest boundary", pos);
160 
161  IntegerVector boundary = IntegerVector::Zero(n);
162  for (Vertex v : B)
163  boundary(v) = 1;
164 
165  std::pair<PC::Vector,PC::Vector> uv_b = FixBoundaryParametrization(B);//maps boundary to circle
166 
167  calculus = new PC(surfmesh);
168 
169  //Impose dirichlet boundary condition to laplace problem
170  PC::Vector Z = PC::Vector::Zero(n);
172  SparseMatrix L_d = Conditions::dirichletOperator( L, boundary );
173 
174  PC::Solver solver;
175  solver.compute(L_d);
176 
177  PC::Vector b_u = Conditions::dirichletVector( L, Z,boundary, uv_b.first );
178  PC::Vector b_v = Conditions::dirichletVector( L, Z,boundary, uv_b.second );
179 
180  PC::Vector rslt_u_d = solver.solve(b_u);
181  PC::Vector rslt_v_d = solver.solve(b_v);
182 
183  PC::Vector rslt_u = Conditions::dirichletSolution(rslt_u_d,boundary,uv_b.first);
184  PC::Vector rslt_v = Conditions::dirichletSolution(rslt_v_d,boundary,uv_b.second);
185 
186  DenseMatrix uv(n,2);
187  uv.col(0) = rslt_u;
188  uv.col(1) = rslt_v;
189 
190  return uv;
191 }
192 
193 
194 //Restriction of a scalar function to vertices
195 double phiVertex(const Vertex v)
196 {
197  return cos(scale*(surfmesh.position(v)[0]))*sin(scale*surfmesh.position(v)[1]);
198 }
199 
200 //Restriction of a scalar function to vertices
202 {
204  auto nf = vertices.size();
205  Eigen::VectorXd ph(nf);
206  size_t cpt=0;
207  for(auto v: vertices)
208  {
209  ph(cpt) = phiVertex(v);
210  ++cpt;
211  }
212  return ph;
213 }
214 
215 void initPhi()
216 {
217  phiEigen.resize(surfmesh.nbVertices());
218  for(auto i = 0; i < surfmesh.nbVertices(); ++i)
219  phiEigen(i) = phiVertex(i);
220  psMesh->addVertexScalarQuantity("Phi", phiEigen);
221 }
222 
223 void initQuantities()
224 {
225  trace.beginBlock("Basic quantities");
227 
228  std::vector<PC::Vector> gradients;
229  std::vector<PC::Vector> cogradients;
230  std::vector<PC::Real3dPoint> normals;
231  std::vector<PC::Real3dPoint> vectorArea;
232  std::vector<PC::Real3dPoint> centroids;
233 
234  std::vector<double> faceArea;
235 
236  for(auto f=0; f < surfmesh.nbFaces(); ++f)
237  {
238  PC::Vector grad = calculus.gradient(f) * phi(f);
239  gradients.push_back( grad );
240 
241  PC::Vector cograd = calculus.coGradient(f) * phi(f);
242  cogradients.push_back( cograd );
243 
244  normals.push_back(calculus.faceNormalAsDGtalVector(f));
245 
247  vectorArea.push_back({vA(0) , vA(1), vA(2)});
248 
249  faceArea.push_back( calculus.faceArea(f));
250  }
251  trace.endBlock();
252 
253  psMesh->addFaceVectorQuantity("Gradients", gradients);
254  psMesh->addFaceVectorQuantity("co-Gradients", cogradients);
255  psMesh->addFaceVectorQuantity("Normals", normals);
256  psMesh->addFaceScalarQuantity("Face area", faceArea);
257  psMesh->addFaceVectorQuantity("Vector area", vectorArea);
258 }
259 
260 void computeGeodesics()
261 {
264  std::vector<double> X_0;
265 
266  auto nv = surfmesh.nbVertices();
267  auto ael = surfmesh.averageEdgeLength();
268  GHM.init(ael*ael);//init vector heat method solvers
269 
270  X_0.resize(nv,0);//extrinsic Source vectors
271 
272  //Random Sources
273  for(auto i=0; i < nbSources; ++i)
274  {
275  size_t id = rand()%surfmesh.nbVertices();
276  GHM.addSource(id);
277  X_0[id] = 42.0;
278  }
279  psMesh->addVertexScalarQuantity("X_0",X_0);
280  psMesh->addVertexDistanceQuantity("GeodeiscInHeat", GHM.compute());
281 }
282 
283 
284 void computeHeatVectors()
285 {
288  typedef PC::Vector Vector;
289  std::vector<Vector> X_0;
290 
291  auto nv = surfmesh.nbVertices();
292  auto ael = surfmesh.averageEdgeLength();
293  VHM.init(ael*ael);//init vector heat method solvers
294 
295  X_0.resize(nv,Vector::Zero(3));//extrinsic Source vectors
296 
297  //Random Sources
298  for(auto i=0; i < nbSources; ++i)
299  {
300  size_t id = rand()%surfmesh.nbVertices();
301  VHM.addSource(id,Eigen::Vector3d::Random(3).normalized());
302  X_0[id] = VHM.extrinsicVectorSourceAtVertex(id);
303  }
304 
305  psMesh->addVertexVectorQuantity("X_0",X_0);
306  psMesh->addVertexVectorQuantity("VHM field",VHM.compute());
307 }
308 
309 void myCallback()
310 {
311  ImGui::SliderFloat("Phi scale", &scale, 0., 10.);
312  ImGui::SliderInt("Nb Sources", &nbSources, 1, 10);
313 
314  if (ImGui::Button("Phi and basic operators"))
315  {
316  initPhi();
317  initQuantities();
318  }
319  if (ImGui::Button("Geodesics in heat"))
321  if (ImGui::Button("Heat Vectors"))
322  computeHeatVectors();
323  if(ImGui::Button("Harmonic parametrization"))
324  {
325  //compute parametrization
326  DenseMatrix UV = HarmonicParametrization();
327 
328  //visualize parametrization on 2D circle
329  VisualizeParametrizationOnCircle(UV);
330  psMesh->addVertexParameterizationQuantity("Harmonic parametrization",UV)->setEnabled(true);
331  }
332 }
333 
334 int main()
335 {
336  std::string inputFilename(examplesPath + "samples/bunnyheadhole.obj" );
337 
338  Mesh<RealPoint> a3DMesh;
339  a3DMesh << inputFilename;
340 
341  for(auto it = a3DMesh.faceBegin(), itend = a3DMesh.faceEnd(); it != itend; ++it)
342  faces.push_back(*it);
343 
344  //Need to convert the faces
345  surfmesh = SurfMesh(a3DMesh.vertexBegin(),
346  a3DMesh.vertexEnd(),
347  faces.begin(),
348  faces.end());
349 
350  std::cout<<"number of non-manifold Edges = " << surfmesh.computeNonManifoldEdges().size()<<std::endl;
351  psMesh = polyscope::registerSurfaceMesh("Bimba surface", surfmesh.positions(), faces);
352 
353  // Initialize polyscope
354  polyscope::init();
355 
356  // Set the callback function
357  polyscope::state::userCallback = myCallback;
358  polyscope::show();
359  return EXIT_SUCCESS;
360 }
Aim: A helper class to solve a system with Dirichlet boundary conditions.
LinearAlgebraBackend::IntegerVector IntegerVector
static DenseVector dirichletVector(const SparseMatrix &A, const DenseVector &b, const IntegerVector &p, const DenseVector &u)
static SparseMatrix dirichletOperator(const SparseMatrix &A, const IntegerVector &p)
static DenseVector dirichletSolution(const DenseVector &xd, const IntegerVector &p, const DenseVector &u)
This class implements on polygonal surfaces (using Discrete differential calculus on polygonal surfa...
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Definition: Mesh.h:92
FaceStorage::const_iterator faceEnd() const
Definition: Mesh.h:414
ConstIterator vertexEnd() const
Definition: Mesh.h:369
FaceStorage::const_iterator faceBegin() const
Definition: Mesh.h:402
ConstIterator vertexBegin() const
Definition: Mesh.h:359
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
double norm(const NormType type=L_2) const
Implements differential operators on polygonal surfaces from .
LinAlg::SparseMatrix SparseMatrix
Type of sparse matrix.
Real3dVector faceNormalAsDGtalVector(const Face f) const
Vector vectorArea(const Face f) const
SparseMatrix globalLaplaceBeltrami(const double lambda=1.0) const
LinAlg::SolverSimplicialLDLT Solver
Type of a sparse matrix solver.
double faceArea(const Face f) const
DenseMatrix coGradient(const Face f) const
DenseMatrix gradient(const Face f) const
LinAlg::DenseMatrix DenseMatrix
Type of dense matrix.
LinAlg::DenseVector Vector
Type of Vector.
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Definition: Shortcuts.h:105
void beginBlock(const std::string &keyword="")
double endBlock()
This class implements on polygonal surfaces (using Discrete differential calculus on polygonal surfa...
Definition: VectorsInHeat.h:63
SurfaceMesh< RealPoint, RealVector > SurfMesh
PolygonalCalculus< SH3::RealPoint, SH3::RealVector >::Vector phiEigen
double phiVertex(const Vertex v)
void initPhi()
void myCallback()
polyscope::SurfaceMesh * psMesh
PolygonalCalculus< SH3::RealPoint, SH3::RealVector >::Vector phi(const Face f)
SurfMesh surfmesh
void initQuantities()
PolyCalculus * calculus
void computeGeodesics()
Space::Vector Vector
Definition: StdDefs.h:169
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:153
std::pair< typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator, typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator > vertices(const DGtal::DigitalSurface< TDigitalSurfaceContainer > &digSurf)
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
Definition: SurfaceMesh.h:92
RealPoint & position(Vertex v)
Definition: SurfaceMesh.h:647
const std::vector< RealPoint > & positions() const
Definition: SurfaceMesh.h:641
std::vector< Vertices > computeManifoldBoundaryChains() const
Definition: SurfaceMesh.h:483
const Vertices & incidentVertices(Face f) const
Definition: SurfaceMesh.h:315
Scalar distance(const Vertex i, const Vertex j) const
Definition: SurfaceMesh.h:702
Size nbFaces() const
Definition: SurfaceMesh.h:296
Edges computeManifoldBoundaryEdges() const
Size nbVertices() const
Definition: SurfaceMesh.h:288
Edges computeNonManifoldEdges() const
Scalar averageEdgeLength() const
int main(int argc, char **argv)
Shortcuts< KSpace > SH3
K init(Point(0, 0, 0), Point(512, 512, 512), true)
EigenLinearAlgebraBackend::SparseMatrix SparseMatrix
EigenLinearAlgebraBackend::DenseMatrix DenseMatrix
ShortcutsGeometry< Z3i::KSpace > SHG3
TriMesh::Face Face
TriMesh::Vertex Vertex