DGtal 1.3.0
Loading...
Searching...
No Matches
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
51using namespace DGtal;
52using namespace Z3i;
53
54// Using standard 3D digital space.
57// The following typedefs are useful
59typedef SurfMesh::Face Face;
61
63typedef std::vector<Vertex> chain;
65typedef Conditions::IntegerVector IntegerVector;
68typedef PC::Solver Solver;
69
70//Polyscope global
71polyscope::SurfaceMesh *psMesh;
72SurfMesh surfmesh;
73float scale = 10;
74PC::Vector phiEigen;
75int nbSources=1;
76std::vector< std::vector<SurfMesh::Index> > faces;
77std::vector<RealPoint> positions;
78
79//DEC
80PC *calculus;
81
82
83
90std::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
118void 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
144DenseMatrix 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 size_t cpt=0;
158 for(const auto v: B)
159 pos.push_back(surfmesh.position(v));
160 polyscope::registerCurveNetworkLoop("Longest boundary", pos);
161
162 IntegerVector boundary = IntegerVector::Zero(n);
163 for (Vertex v : B)
164 boundary(v) = 1;
165
166 std::pair<PC::Vector,PC::Vector> uv_b = FixBoundaryParametrization(B);//maps boundary to circle
167
168 calculus = new PC(surfmesh);
169
170 //Impose dirichlet boundary condition to laplace problem
171 PC::Vector Z = PC::Vector::Zero(n);
172 SparseMatrix L = calculus->globalLaplaceBeltrami();
173 SparseMatrix L_d = Conditions::dirichletOperator( L, boundary );
174
175 PC::Solver solver;
176 solver.compute(L_d);
177
178 PC::Vector b_u = Conditions::dirichletVector( L, Z,boundary, uv_b.first );
179 PC::Vector b_v = Conditions::dirichletVector( L, Z,boundary, uv_b.second );
180
181 PC::Vector rslt_u_d = solver.solve(b_u);
182 PC::Vector rslt_v_d = solver.solve(b_v);
183
184 PC::Vector rslt_u = Conditions::dirichletSolution(rslt_u_d,boundary,uv_b.first);
185 PC::Vector rslt_v = Conditions::dirichletSolution(rslt_v_d,boundary,uv_b.second);
186
187 DenseMatrix uv(n,2);
188 uv.col(0) = rslt_u;
189 uv.col(1) = rslt_v;
190
191 return uv;
192}
193
194
195//Restriction of a scalar function to vertices
196double phiVertex(const Vertex v)
197{
198 return cos(scale*(surfmesh.position(v)[0]))*sin(scale*surfmesh.position(v)[1]);
199}
200
201//Restriction of a scalar function to vertices
203{
204 auto vertices = surfmesh.incidentVertices(f);
205 auto nf = vertices.size();
206 Eigen::VectorXd ph(nf);
207 size_t cpt=0;
208 for(auto v: vertices)
209 {
210 ph(cpt) = phiVertex(v);
211 ++cpt;
212 }
213 return ph;
214}
215
216void initPhi()
217{
218 phiEigen.resize(surfmesh.nbVertices());
219 for(auto i = 0; i < surfmesh.nbVertices(); ++i)
220 phiEigen(i) = phiVertex(i);
221 psMesh->addVertexScalarQuantity("Phi", phiEigen);
222}
223
224void initQuantities()
225{
226 trace.beginBlock("Basic quantities");
228
229 std::vector<PC::Vector> gradients;
230 std::vector<PC::Vector> cogradients;
231 std::vector<PC::Real3dPoint> normals;
232 std::vector<PC::Real3dPoint> vectorArea;
233 std::vector<PC::Real3dPoint> centroids;
234
235 std::vector<double> faceArea;
236
237 for(auto f=0; f < surfmesh.nbFaces(); ++f)
238 {
239 PC::Vector grad = calculus.gradient(f) * phi(f);
240 gradients.push_back( grad );
241
242 PC::Vector cograd = calculus.coGradient(f) * phi(f);
243 cogradients.push_back( cograd );
244
245 normals.push_back(calculus.faceNormalAsDGtalVector(f));
246
247 PC::Vector vA = calculus.vectorArea(f);
248 vectorArea.push_back({vA(0) , vA(1), vA(2)});
249
250 faceArea.push_back( calculus.faceArea(f));
251 }
252 trace.endBlock();
253
254 psMesh->addFaceVectorQuantity("Gradients", gradients);
255 psMesh->addFaceVectorQuantity("co-Gradients", cogradients);
256 psMesh->addFaceVectorQuantity("Normals", normals);
257 psMesh->addFaceScalarQuantity("Face area", faceArea);
258 psMesh->addFaceVectorQuantity("Vector area", vectorArea);
259}
260
261void computeGeodesics()
262{
263 PC calculus(surfmesh);
264 GeodesicsInHeat<PC> GHM(calculus);
265 typedef PC::Vector Vector;
266 std::vector<double> X_0;
267
268 auto nv = surfmesh.nbVertices();
269 auto ael = surfmesh.averageEdgeLength();
270 GHM.init(ael*ael);//init vector heat method solvers
271
272 X_0.resize(nv,0);//extrinsic Source vectors
273
274 //Random Sources
275 for(auto i=0; i < nbSources; ++i)
276 {
277 size_t id = rand()%surfmesh.nbVertices();
278 GHM.addSource(id);
279 X_0[id] = 42.0;
280 }
281 psMesh->addVertexScalarQuantity("X_0",X_0);
282 psMesh->addVertexDistanceQuantity("GeodeiscInHeat", GHM.compute());
283}
284
285
286void computeHeatVectors()
287{
288 PC calculus(surfmesh);
289 VectorsInHeat<PC> VHM(calculus);
290 typedef PC::Vector Vector;
291 std::vector<Vector> X_0;
292
293 auto nv = surfmesh.nbVertices();
294 auto ael = surfmesh.averageEdgeLength();
295 VHM.init(ael*ael);//init vector heat method solvers
296
297 X_0.resize(nv,Vector::Zero(3));//extrinsic Source vectors
298
299 //Random Sources
300 for(auto i=0; i < nbSources; ++i)
301 {
302 size_t id = rand()%surfmesh.nbVertices();
303 VHM.addSource(id,Eigen::Vector3d::Random(3).normalized());
304 X_0[id] = VHM.extrinsicVectorSourceAtVertex(id);
305 }
306
307 psMesh->addVertexVectorQuantity("X_0",X_0);
308 psMesh->addVertexVectorQuantity("VHM field",VHM.compute());
309}
310
311void myCallback()
312{
313 ImGui::SliderFloat("Phi scale", &scale, 0., 10.);
314 ImGui::SliderInt("Nb Sources", &nbSources, 1, 10);
315
316 if (ImGui::Button("Phi and basic operators"))
317 {
318 initPhi();
319 initQuantities();
320 }
321 if (ImGui::Button("Geodesics in heat"))
322 computeGeodesics();
323 if (ImGui::Button("Heat Vectors"))
324 computeHeatVectors();
325 if(ImGui::Button("Harmonic parametrization"))
326 {
327 //compute parametrization
328 DenseMatrix UV = HarmonicParametrization();
329
330 //visualize parametrization on 2D circle
331 VisualizeParametrizationOnCircle(UV);
332 psMesh->addVertexParameterizationQuantity("Harmonic parametrization",UV)->setEnabled(true);
333 }
334}
335
336int main()
337{
338 std::string inputFilename(examplesPath + "samples/bunnyheadhole.obj" );
339
340 Mesh<RealPoint> a3DMesh;
341 a3DMesh << inputFilename;
342
343 for(auto it = a3DMesh.faceBegin(), itend = a3DMesh.faceEnd(); it != itend; ++it)
344 faces.push_back(*it);
345
346 //Need to convert the faces
347 surfmesh = SurfMesh(a3DMesh.vertexBegin(),
348 a3DMesh.vertexEnd(),
349 faces.begin(),
350 faces.end());
351
352 std::cout<<"number of non-manifold Edges = " << surfmesh.computeNonManifoldEdges().size()<<std::endl;
353 psMesh = polyscope::registerSurfaceMesh("Bimba surface", surfmesh.positions(), faces);
354
355 // Initialize polyscope
356 polyscope::init();
357
358 // Set the callback function
359 polyscope::state::userCallback = myCallback;
360 polyscope::show();
361 return EXIT_SUCCESS;
362}
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
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:154
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
const Vertices & incidentVertices(Face f) const
Definition: SurfaceMesh.h:307
Scalar distance(const Vertex i, const Vertex j) const
Definition: SurfaceMesh.h:692
const std::vector< RealPoint > & positions() const
Definition: SurfaceMesh.h:631
Size nbFaces() const
Definition: SurfaceMesh.h:288
Edges computeManifoldBoundaryEdges() const
RealPoint & position(Vertex v)
Definition: SurfaceMesh.h:637
Size nbVertices() const
Definition: SurfaceMesh.h:280
Edges computeNonManifoldEdges() const
std::vector< Vertices > computeManifoldBoundaryChains() const
Definition: SurfaceMesh.h:473
Scalar averageEdgeLength() const
int main(int argc, char **argv)
EigenLinearAlgebraBackend::SparseMatrix SparseMatrix
EigenLinearAlgebraBackend::DenseMatrix DenseMatrix
TriMesh::Face Face
TriMesh::Vertex Vertex