DGtal  1.4.beta
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 
46 using namespace DGtal;
47 using namespace Z3i;
48 
49 // Using standard 3D digital space.
52 // The following typedefs are useful
54 typedef SurfMesh::Face Face;
55 typedef SurfMesh::Vertex Vertex;
57 //Polyscope global
58 polyscope::SurfaceMesh *psMesh;
59 polyscope::SurfaceMesh *psMeshReg;
60 SurfMesh surfmesh;
61 SurfMesh surfmeshReg;
62 float dt = 2.0;
63 
64 CountedPtr<SH3::BinaryImage> binary_image;
66 
67 
69 PolyCalculus *calculus;
70 
72 PolyCalculus *calculusReg;
73 
74 SHG3::RealVectors iinormals;
75 
76 int sourceVertexId=0;
77 float radiusII = 3.0;
78 
79 bool skipReg = true; //Global flag to enable/disable the regularization example.
80 bool useProjectedCalculus = true; //Use estimated normal vectors to set up te embedding
81 
82 void precompute()
83 {
84 
85  if (!useProjectedCalculus)
86  calculus = new PolyCalculus(surfmesh);
87  else
88  {
89  //Using the projection embedder
90  auto params2 = SH3::defaultParameters() | SHG3::defaultParameters() | SHG3::parametersGeometryEstimation();
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 
130 std::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 
141 void 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 
156 void clearSources()
157 {
158  heat->clearSource();
159  psMesh->addVertexScalarQuantity("source", heat->source());
160 }
161 
162 void 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 
180 bool isPrecomputed=false;
181 void 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 
226 int main()
227 {
228  auto params = SH3::defaultParameters() | SHG3::defaultParameters() | SHG3::parametersGeometryEstimation();
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...
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()
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
RealPoint & position(Vertex v)
Definition: SurfaceMesh.h:647
const Vertices & incidentVertices(Face f) const
Definition: SurfaceMesh.h:315
Size nbVertices() const
Definition: SurfaceMesh.h:288
Edges computeNonManifoldEdges() const
int main(int argc, char **argv)
Shortcuts< KSpace > SH3
K init(Point(0, 0, 0), Point(512, 512, 512), true)
KSpace K
ShortcutsGeometry< Z3i::KSpace > SHG3
TriMesh::Face Face
TriMesh::Vertex Vertex