DGtal  1.5.beta
dgtalCalculus-geodesic.cpp
Go to the documentation of this file.
1 
26 #include <iostream>
27 #include <string>
28 #include <DGtal/base/Common.h>
29 #include <DGtal/helpers/StdDefs.h>
30 #include <DGtal/helpers/Shortcuts.h>
31 #include <DGtal/helpers/ShortcutsGeometry.h>
32 #include <DGtal/shapes/SurfaceMesh.h>
33 #include <DGtal/geometry/surfaces/DigitalSurfaceRegularization.h>
34 
35 #include <DGtal/dec/PolygonalCalculus.h>
36 #include <DGtal/dec/GeodesicsInHeat.h>
37 
38 #include <polyscope/polyscope.h>
39 #include <polyscope/surface_mesh.h>
40 #include <polyscope/point_cloud.h>
41 
42 #include "ConfigExamples.h"
43 
44 #include <Eigen/Dense>
45 #include <Eigen/Sparse>
46 
47 using namespace DGtal;
48 using namespace Z3i;
49 
50 // Using standard 3D digital space.
53 // The following typedefs are useful
58 //Polyscope global
59 polyscope::SurfaceMesh *psMesh;
60 polyscope::SurfaceMesh *psMeshReg;
63 float dt = 2.0;
64 
67 
68 
71 
74 
76 
78 float radiusII = 3.0;
79 
80 bool skipReg = true; //Global flag to enable/disable the regularization example.
81 bool useProjectedCalculus = true; //Use estimated normal vectors to set up te embedding
82 
83 void precompute()
84 {
85 
88  else
89  {
90  //Using the projection embedder
91  auto params2 = SH3::defaultParameters() | SHG3::defaultParameters() | SHG3::parametersGeometryEstimation();
92  params2("r-radius", (double) radiusII);
93  auto surfels = SH3::getSurfelRange( surface, params2 );
94  iinormals = SHG3::getIINormalVectors(binary_image, surfels,params2);
95  trace.info()<<iinormals.size()<<std::endl;
96  psMesh->addFaceVectorQuantity("II normals", iinormals);
97 
100  calculus->setEmbedder( embedderFromNormals );
101  }
102 
104 
105  if (!skipReg)
106  {
109  }
110  trace.beginBlock("Init solvers");
111  heat->init(dt);
112  if (!skipReg)
113  heatReg->init(dt);
114  trace.endBlock();
115 }
116 
117 std::vector<std::pair<size_t,int>> source2count(GeodesicsInHeat<PolyCalculus>::Vector &source)
118 {
119  std::vector<std::pair<size_t,int>> counts;
120  for(auto i=0; i< source.size(); ++i)
121  {
122  if (source(i)!=0.0)
123  counts.push_back(std::pair<size_t,int>(i,1));
124  }
125  return counts;
126 }
127 
128 void addSource()
129 {
130  auto pos =rand() % surfmesh.nbVertices();
131  heat->addSource( pos );
132  GeodesicsInHeat<PolyCalculus>::Vector source = heat->source();
133  psMesh->addVertexCountQuantity("Sources", source2count(source));
134 
135  if (!skipReg)
136  {
137  heatReg->addSource( pos );
139  psMeshReg->addVertexCountQuantity("Sources", source2count(source));
140  }
141 }
142 
144 {
145  heat->clearSource();
146  psMesh->addVertexScalarQuantity("source", heat->source());
147 }
148 
150 {
151  heat->addSource( sourceVertexId ); //Forcing one seed (for screenshots)
152  GeodesicsInHeat<PolyCalculus>::Vector source = heat->source();
153  psMesh->addVertexCountQuantity("Sources", source2count(source));
155  psMesh->addVertexDistanceQuantity("geodesic", dist);
156 
157  if (!skipReg)
158  {
159  heatReg->addSource( sourceVertexId ); //Forcing one seed (for screenshots)371672
160  GeodesicsInHeat<PolyCalculus>::Vector sourceReg = heatReg->source();
161  psMeshReg->addVertexCountQuantity("Sources", source2count(sourceReg));
163  psMeshReg->addVertexDistanceQuantity("geodesic", dist);
164  }
165 }
166 
167 bool isPrecomputed=false;
169 {
170  ImGui::SliderFloat("dt", &dt, 0.,4.);
171  ImGui::SliderFloat("ii radius for normal vector estimation", &radiusII , 0.,10.);
172  ImGui::Checkbox("Skip regularization", &skipReg);
173  ImGui::Checkbox("Using projection", &useProjectedCalculus);
174  ImGui::InputInt("Index of the first source vertex", &sourceVertexId);
175 
176 
177  if(ImGui::Button("Precomputation (required if you change parameters)"))
178  {
179  precompute();
180  isPrecomputed=true;
181  }
182  ImGui::Separator();
183  if(ImGui::Button("Add a random source"))
184  {
185  if (!isPrecomputed)
186  {
187  precompute();
188  isPrecomputed=true;
189  }
190  addSource();
191  }
192  if(ImGui::Button("Clear sources"))
193  {
194  if (!isPrecomputed)
195  {
196  precompute();
197  isPrecomputed=true;
198  }
199  clearSources();
200  }
201 
202  if(ImGui::Button("Compute geodesic"))
203  {
204  if (!isPrecomputed)
205  {
206  precompute();
207  isPrecomputed=true;
208  }
210  }
211 }
212 
213 int main()
214 {
215  auto params = SH3::defaultParameters() | SHG3::defaultParameters() | SHG3::parametersGeometryEstimation();
216  params("surfaceComponents", "All");
217  params("r-radius", (double) radiusII);
218  std::string filename = examplesPath + std::string("/samples/bunny-128.vol");
219  binary_image = SH3::makeBinaryImage(filename, params );
220  auto K = SH3::getKSpace( binary_image, params );
221  surface = SH3::makeDigitalSurface( binary_image, K, params );
222  auto primalSurface = SH3::makePrimalSurfaceMesh(surface);
223 
224  //Need to convert the faces
225  std::vector<std::vector<SH3::SurfaceMesh::Vertex>> faces;
226  std::vector<RealPoint> positions;
227 
228  for(auto face= 0 ; face < primalSurface->nbFaces(); ++face)
229  faces.push_back(primalSurface->incidentVertices( face ));
230 
231  //Recasting to vector of vertices
232  positions = primalSurface->positions();
233 
234  surfmesh = SurfMesh(positions.begin(),
235  positions.end(),
236  faces.begin(),
237  faces.end());
238  std::cout << surfmesh << std::endl;
239  std::cout<<"number of non-manifold Edges = " << surfmesh.computeNonManifoldEdges().size()<<std::endl;
240 
241  //Construction of a regularized surface
243  regul.init();
245  regul.regularize();
246  auto regularizedPosition = regul.getRegularizedPositions();
247 
248  surfmeshReg = SurfMesh(regularizedPosition.begin(),
249  regularizedPosition.end(),
250  faces.begin(),
251  faces.end());
252 
253  // Initialize polyscope
254  polyscope::init();
255 
256  psMesh = polyscope::registerSurfaceMesh("digital surface", positions, faces);
257  psMeshReg = polyscope::registerSurfaceMesh("regularized surface", regularizedPosition, faces);
258  psMeshReg->setEnabled(false);
259 
260  // Set the callback function
261  polyscope::state::userCallback = myCallback;
262  polyscope::show();
263  return EXIT_SUCCESS;
264 }
Aim: Smart pointer based on reference counts.
Definition: CountedPtr.h:80
Aim: Implements Digital Surface Regularization as described in .
void init(const double alpha=0.001, const double beta=1.0, const double gamma=0.05)
Initialize the parameters of the energy function.
void attachConvolvedTrivialNormalVectors(const Parameters someParams=SH3::defaultParameters()|SHG3::defaultParameters())
double regularize(const unsigned int nbIters, const double dt, const double epsilon, const AdvectionFunction &advectionFunc)
Main regularization loop.
This class implements on polygonal surfaces (using Discrete differential calculus on polygonal surfa...
PolygonalCalculus::Vector Vector
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...
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
void beginBlock(const std::string &keyword="")
std::ostream & info()
double endBlock()
std::vector< std::pair< size_t, int > > source2count(GeodesicsInHeat< PolyCalculus >::Vector &source)
void addSource()
PolyCalculus * calculusReg
void precompute()
SurfaceMesh< RealPoint, RealVector > SurfMesh
bool useProjectedCalculus
bool skipReg
GeodesicsInHeat< PolyCalculus > * heatReg
PolyCalculus * calculus
void clearSources()
SurfMesh::Face Face
CountedPtr< SH3::DigitalSurface > surface
bool isPrecomputed
float radiusII
PolygonalCalculus< SH3::RealPoint, SH3::RealVector > PolyCalculus
void computeGeodesics()
CountedPtr< SH3::BinaryImage > binary_image
int sourceVertexId
void myCallback()
polyscope::SurfaceMesh * psMesh
SurfMesh::Vertex Vertex
Shortcuts< Z3i::KSpace > SH3
SurfMesh surfmesh
ShortcutsGeometry< Z3i::KSpace > SHG3
SHG3::RealVectors iinormals
polyscope::SurfaceMesh * psMeshReg
GeodesicsInHeat< PolyCalculus > * heat
SurfMesh surfmeshReg
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:153
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
Definition: SurfaceMesh.h:92
Size nbVertices() const
Definition: SurfaceMesh.h:288
Edges computeNonManifoldEdges() const
Functor that projects a face vertex of a surface mesh onto the tangent plane given by a per-face norm...
K init(Point(0, 0, 0), Point(512, 512, 512), true)
KSpace K