DGtal 1.3.0
Loading...
Searching...
No Matches
dgtalCalculus-geodesic.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
37#include <polyscope/polyscope.h>
38#include <polyscope/surface_mesh.h>
39#include <polyscope/point_cloud.h>
40
41#include "ConfigExamples.h"
42
43#include <Eigen/Dense>
44#include <Eigen/Sparse>
45
46using namespace DGtal;
47using namespace Z3i;
48
49// Using standard 3D digital space.
52// The following typedefs are useful
54typedef SurfMesh::Face Face;
57//Polyscope global
58polyscope::SurfaceMesh *psMesh;
59polyscope::SurfaceMesh *psMeshReg;
60SurfMesh surfmesh;
61SurfMesh surfmeshReg;
62float dt = 2.0;
63
66
67
69PolyCalculus *calculus;
70
72PolyCalculus *calculusReg;
73
74SHG3::RealVectors iinormals;
75
76int sourceVertexId=0;
77float radiusII = 3.0;
78
79bool skipReg = true; //Global flag to enable/disable the regularization example.
80bool useProjectedCalculus = true; //Use estimated normal vectors to set up te embedding
81
82void precompute()
83{
84
85 if (!useProjectedCalculus)
86 calculus = new PolyCalculus(surfmesh);
87 else
88 {
89 //Using the projection embedder
91 params2("r-radius", (double) radiusII);
92 auto surfels = SH3::getSurfelRange( surface, params2 );
93 iinormals = SHG3::getIINormalVectors(binary_image, surfels,params2);
94 trace.info()<<iinormals.size()<<std::endl;
95 auto myProjEmbedder = [&](Face f, Vertex v)
96 {
97 const auto nn = iinormals[f];
98 RealPoint centroid(0.0,0.0,0.0); //centroid of the original face
99 auto cpt=0;
100 for(auto v: surfmesh.incidentVertices(f))
101 {
102 cpt++;
103 centroid += surfmesh.position(v);
104 }
105 centroid = centroid / (double)cpt;
106 RealPoint p = surfmesh.position(v);
107 auto cp = p-centroid;
108 RealPoint q = p - nn.dot(cp)*nn;
109 return q;
110 };
111 psMesh->addFaceVectorQuantity("II normals", iinormals);
112 calculus = new PolyCalculus(surfmesh);
113 calculus->setEmbedder( myProjEmbedder );
114 }
115
116 heat = new GeodesicsInHeat<PolyCalculus>(calculus);
117
118 if (!skipReg)
119 {
120 calculusReg = new PolyCalculus(surfmeshReg);
121 heatReg = new GeodesicsInHeat<PolyCalculus>(calculusReg);
122 }
123 trace.beginBlock("Init solvers");
124 heat->init(dt);
125 if (!skipReg)
126 heatReg->init(dt);
127 trace.endBlock();
128}
129
130std::vector<std::pair<size_t,int>> source2count(GeodesicsInHeat<PolyCalculus>::Vector &source)
131{
132 std::vector<std::pair<size_t,int>> counts;
133 for(auto i=0; i< source.size(); ++i)
134 {
135 if (source(i)!=0.0)
136 counts.push_back(std::pair<size_t,int>(i,1));
137 }
138 return counts;
139}
140
141void addSource()
142{
143 auto pos =rand() % surfmesh.nbVertices();
144 heat->addSource( pos );
145 GeodesicsInHeat<PolyCalculus>::Vector source = heat->source();
146 psMesh->addVertexCountQuantity("Sources", source2count(source));
147
148 if (!skipReg)
149 {
150 heatReg->addSource( pos );
151 GeodesicsInHeat<PolyCalculus>::Vector source = heatReg->source();
152 psMeshReg->addVertexCountQuantity("Sources", source2count(source));
153 }
154}
155
156void clearSources()
157{
158 heat->clearSource();
159 psMesh->addVertexScalarQuantity("source", heat->source());
160}
161
162void computeGeodesics()
163{
164 heat->addSource( sourceVertexId ); //Forcing one seed (for screenshots)
165 GeodesicsInHeat<PolyCalculus>::Vector source = heat->source();
166 psMesh->addVertexCountQuantity("Sources", source2count(source));
167 GeodesicsInHeat<PolyCalculus>::Vector dist = heat->compute();
168 psMesh->addVertexDistanceQuantity("geodesic", dist);
169
170 if (!skipReg)
171 {
172 heatReg->addSource( sourceVertexId ); //Forcing one seed (for screenshots)371672
173 GeodesicsInHeat<PolyCalculus>::Vector sourceReg = heatReg->source();
174 psMeshReg->addVertexCountQuantity("Sources", source2count(sourceReg));
175 GeodesicsInHeat<PolyCalculus>::Vector dist = heatReg->compute();
176 psMeshReg->addVertexDistanceQuantity("geodesic", dist);
177 }
178}
179
180bool isPrecomputed=false;
181void myCallback()
182{
183 ImGui::SliderFloat("dt", &dt, 0.,4.);
184 ImGui::SliderFloat("ii radius for normal vector estimation", &radiusII , 0.,10.);
185 ImGui::Checkbox("Skip regularization", &skipReg);
186 ImGui::Checkbox("Using projection", &useProjectedCalculus);
187 ImGui::InputInt("Index of the first source vertex", &sourceVertexId);
188
189
190 if(ImGui::Button("Precomputation (required if you change parameters)"))
191 {
192 precompute();
193 isPrecomputed=true;
194 }
195 ImGui::Separator();
196 if(ImGui::Button("Add a random source"))
197 {
198 if (!isPrecomputed)
199 {
200 precompute();
201 isPrecomputed=true;
202 }
203 addSource();
204 }
205 if(ImGui::Button("Clear sources"))
206 {
207 if (!isPrecomputed)
208 {
209 precompute();
210 isPrecomputed=true;
211 }
212 clearSources();
213 }
214
215 if(ImGui::Button("Compute geodesic"))
216 {
217 if (!isPrecomputed)
218 {
219 precompute();
220 isPrecomputed=true;
221 }
222 computeGeodesics();
223 }
224}
225
226int main()
227{
229 params("surfaceComponents", "All");
230 params("r-radius", (double) radiusII);
231 std::string filename = examplesPath + std::string("/samples/bunny-128.vol");
232 binary_image = SH3::makeBinaryImage(filename, params );
233 auto K = SH3::getKSpace( binary_image, params );
234 surface = SH3::makeDigitalSurface( binary_image, K, params );
235 auto primalSurface = SH3::makePrimalSurfaceMesh(surface);
236
237 //Need to convert the faces
238 std::vector<std::vector<SH3::SurfaceMesh::Vertex>> faces;
239 std::vector<RealPoint> positions;
240
241 for(auto face= 0 ; face < primalSurface->nbFaces(); ++face)
242 faces.push_back(primalSurface->incidentVertices( face ));
243
244 //Recasting to vector of vertices
245 positions = primalSurface->positions();
246
247 surfmesh = SurfMesh(positions.begin(),
248 positions.end(),
249 faces.begin(),
250 faces.end());
251 std::cout << surfmesh << std::endl;
252 std::cout<<"number of non-manifold Edges = " << surfmesh.computeNonManifoldEdges().size()<<std::endl;
253
254 //Construction of a regularized surface
256 regul.init();
257 regul.attachConvolvedTrivialNormalVectors(params);
258 regul.regularize();
259 auto regularizedPosition = regul.getRegularizedPositions();
260
261 surfmeshReg = SurfMesh(regularizedPosition.begin(),
262 regularizedPosition.end(),
263 faces.begin(),
264 faces.end());
265
266 // Initialize polyscope
267 polyscope::init();
268
269 psMesh = polyscope::registerSurfaceMesh("digital surface", positions, faces);
270 psMeshReg = polyscope::registerSurfaceMesh("regularized surface", regularizedPosition, faces);
271 psMeshReg->setEnabled(false);
272
273 // Set the callback function
274 polyscope::state::userCallback = myCallback;
275 polyscope::show();
276 return EXIT_SUCCESS;
277}
Aim: Smart pointer based on reference counts.
Definition: CountedPtr.h:80
Aim: Implements Digital Surface Regularization as described in .
This class implements on polygonal surfaces (using Discrete differential calculus on polygonal surfa...
PolygonalCalculus::Vector Vector
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
auto dot(const PointVector< dim, OtherComponent, OtherStorage > &v) const -> decltype(DGtal::dotProduct(*this, v))
Dot product with a PointVector.
Implements differential operators on polygonal surfaces from .
void setEmbedder(const std::function< Real3dPoint(Face, Vertex)> &externalFunctor)
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
static Parameters parametersGeometryEstimation()
static RealVectors getIINormalVectors(CountedPtr< BinaryImage > bimage, const SurfelRange &surfels, const Parameters &params=parametersGeometryEstimation()|parametersKSpace())
static Parameters defaultParameters()
std::vector< RealVector > RealVectors
Aim: This class is used to simplify shape and surface creation. With it, you can create new shapes an...
Definition: Shortcuts.h:105
static KSpace getKSpace(const Point &low, const Point &up, Parameters params=parametersKSpace())
Definition: Shortcuts.h:332
static SurfelRange getSurfelRange(CountedPtr< ::DGtal::DigitalSurface< TDigitalSurfaceContainer > > surface, const Parameters &params=parametersDigitalSurface())
Definition: Shortcuts.h:1547
static CountedPtr< DigitalSurface > makeDigitalSurface(CountedPtr< TPointPredicate > bimage, const KSpace &K, const Parameters &params=parametersDigitalSurface())
Definition: Shortcuts.h:1209
static Parameters defaultParameters()
Definition: Shortcuts.h:203
static CountedPtr< SurfaceMesh > makePrimalSurfaceMesh(Cell2Index &c2i, CountedPtr< ::DGtal::DigitalSurface< TContainer > > aSurface)
Definition: Shortcuts.h:2372
static CountedPtr< BinaryImage > makeBinaryImage(Domain shapeDomain)
Definition: Shortcuts.h:561
void beginBlock(const std::string &keyword="")
std::ostream & info()
double endBlock()
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:154
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
RealPoint & position(Vertex v)
Definition: SurfaceMesh.h:637
Size nbVertices() const
Definition: SurfaceMesh.h:280
Edges computeNonManifoldEdges() const
int main(int argc, char **argv)
KSpace K
TriMesh::Face Face
TriMesh::Vertex Vertex