DGtal 1.4.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;
73float scale = 10;
75int nbSources=1;
76std::vector< std::vector<SurfMesh::Index> > faces;
77std::vector<RealPoint> positions;
78
79//DEC
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 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
195double 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
215void 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
223void 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
260void computeGeodesics()
261{
262 PC calculus(surfmesh);
263 GeodesicsInHeat<PC> GHM(calculus);
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
284void computeHeatVectors()
285{
286 PC calculus(surfmesh);
287 VectorsInHeat<PC> VHM(calculus);
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
309void 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();
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
334int 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 Crane2013 on polygonal surfaces (using Discrete differential calculus on polygo...
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.
double norm(const NormType type=L_2) const
Implements differential operators on polygonal surfaces from degoes2020discrete.
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 Sharp:2019:VHM on polygonal surfaces (using Discrete differential calculus on p...
PolygonalCalculus< SH3::RealPoint, SH3::RealVector >::Vector phiEigen
double phiVertex(const Vertex v)
void initPhi()
void myCallback()
polyscope::SurfaceMesh * psMesh
SurfMesh surfmesh
void initQuantities()
PolygonalCalculus< SH3::RealPoint, SH3::RealVector >::Vector phi(const Face f)
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
const Vertices & incidentVertices(Face f) const
Scalar distance(const Vertex i, const Vertex j) const
const std::vector< RealPoint > & positions() const
Size nbFaces() const
Edges computeManifoldBoundaryEdges() const
RealPoint & position(Vertex v)
Size nbVertices() const
Edges computeNonManifoldEdges() const
std::vector< Vertices > computeManifoldBoundaryChains() const
Scalar averageEdgeLength() const
int main(int argc, char **argv)
EigenLinearAlgebraBackend::SparseMatrix SparseMatrix
EigenLinearAlgebraBackend::DenseMatrix DenseMatrix
TriMesh::Face Face
TriMesh::Vertex Vertex