DGtal  1.5.beta
windingNumbersShape.cpp
1 
25 #include <iostream>
26 #include <string>
27 #include <algorithm>
28 #include <fstream> // std::ofstream
29 
30 #include <DGtal/base/Common.h>
31 #include <DGtal/helpers/StdDefs.h>
32 #include <DGtal/helpers/Shortcuts.h>
33 #include <DGtal/helpers/ShortcutsGeometry.h>
34 #include <polyscope/polyscope.h>
35 #include <polyscope/surface_mesh.h>
36 #include <polyscope/point_cloud.h>
37 
38 #include <DGtal/shapes/WindingNumbersShape.h>
39 #include <DGtal/shapes/GaussDigitizer.h>
40 
41 #include "ConfigExamples.h"
42 
43 using namespace DGtal;
44 using namespace Z3i;
45 
46 // Using standard 3D digital space.
49 // The following typedefs are useful
51 
52 int main()
53 {
54  auto params = SH3::defaultParameters() | SHG3::defaultParameters() | SHG3::parametersGeometryEstimation();
55  params("surfaceComponents", "All")( "gridstep", 1. )("r-radius" , 4.0);
56 
57  std::string filename = examplesPath + std::string("/samples/bunny-32.vol");
58  auto binary_image = SH3::makeBinaryImage(filename, params );
59  auto K = SH3::getKSpace( binary_image, params );
60  auto surface = SH3::makeDigitalSurface( binary_image, K, params );
61  SH3::Cell2Index c2i;
62  auto primalSurface = SH3::makePrimalSurfaceMesh(surface);
63  auto surfels = SH3::getSurfelRange( surface, params);
64  auto embedder = SH3::getSCellEmbedder( K );
65 
66 
67  //Need to convert the faces
68  std::vector<std::vector<SH3::SurfaceMesh::Vertex>> faces;
69  std::vector<RealPoint> positions;
70  for(auto face= 0 ; face < primalSurface->nbFaces(); ++face)
71  faces.push_back(primalSurface->incidentVertices( face ));
72  //Recasting to vector of vertices
73  positions = primalSurface->positions();
74 
75  auto surfmesh = SurfMesh(positions.begin(),
76  positions.end(),
77  faces.begin(),
78  faces.end());
79 
80 
81  trace.info()<<"Got "<<surfels.size()<<" surfels."<<std::endl;
82 
83  // Initialize polyscope
85 
86  auto iinormals = SHG3::getIINormalVectors(binary_image, surfels, params);
87  auto psMesh = polyscope::registerSurfaceMesh("input digital surface", positions, faces);
88  psMesh->addFaceVectorQuantity("normals", iinormals);
89 
90  Eigen::MatrixXd points(surfels.size(),3);
91  Eigen::MatrixXd normals(surfels.size(),3);
92  std::ofstream ofs ("bunny.pts", std::ofstream::out);
93  for(auto i=0; i< surfels.size(); ++i)
94  {
95  auto p = embedder(surfels[i]);
96  auto n = iinormals[i];
97  points(i,0) = p(0);
98  points(i,1) = p(1);
99  points(i,2) = p(2);
100  normals(i,0) = n(0);
101  normals(i,1) = n(1);
102  normals(i,2) = n(2);
103 
104  ofs<<p(0)<<" "<<p(1)<<" "<<p(2)<<" "<<n(0)<<" "<< n(1)<<" "<<n(2)<<std::endl;
105  }
106  ofs.close();
107  auto pc= polyscope::registerPointCloud("input boundary points", points);
108  pc->addVectorQuantity("normals", normals);
109 
110  //Winding number shape
111  WindingNumbersShape<Z3i::Space> wnshape(points,normals);
112 
113 
114  auto lower = binary_image->domain().lowerBound();
115  auto upper = binary_image->domain().upperBound();
116 
117  auto resample_h = [&](double h){
118 
119  RegularPointEmbedder<Z3i::Space> pointEmbedder;
120  pointEmbedder.init( h );
121  Z3i::Point lowerPoint = pointEmbedder.floor( lower );
122  Z3i::Point upperPoint = pointEmbedder.ceil( upper );
123  Z3i::Domain domain(lowerPoint,upperPoint);
124  trace.info() <<"Digital domain = "<<domain.size()<<" " <<domain<<std::endl;
125 
126  //Winding (batched)
127  size_t size = domain.size();
128  Eigen::MatrixXd queries(size,3);
129  auto cpt=0;
130  for(const auto &vox: domain)
131  {
132  Eigen::RowVector3<double> p(vox[0],vox[1],vox[2]);
133  p *= h;
134  queries.row(cpt) = p;
135  ++cpt;
136  }
137  trace.info()<<"Cpt= "<<cpt<<" size= "<<size<<std::endl;
138  auto orientations = wnshape.orientationBatch(queries);
139 
140  //Binary Predicate
141  Z3i::DigitalSet voxels(domain);
142  cpt=0;
143  for(const auto &voxel: domain)
144  {
145  if (orientations[cpt]==INSIDE)
146  voxels.insertNew(voxel);
147  ++cpt;
148  }
149  trace.info() <<"Number of voxels = "<<voxels.size()<<std::endl;
150 
151  //Digital surface
152  Z3i::KSpace kspace;
153  kspace.init(lowerPoint, upperPoint, true);
155  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
157  typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
158 
159  MySurfelAdjacency surfAdj( true ); // interior in all directions.
160  MySetOfSurfels theSetOfSurfels( kspace, surfAdj );
161  Surfaces<KSpace>::sMakeBoundary(theSetOfSurfels.surfelSet(),
162  kspace,
163  voxels,
164  lowerPoint,
165  upperPoint);
166  trace.info()<<"Surfel set size= "<<theSetOfSurfels.surfelSet().size()<<std::endl;
167 
168  //Polyscope visualization
169  auto surfPtr = CountedPtr<DigitalSurface< MySetOfSurfels >>(new MyDigitalSurface(theSetOfSurfels));
170  auto primalSurfaceReco = SH3::makePrimalSurfaceMesh(surfPtr);
171 
172  std::vector<RealPoint> positionsReco = primalSurfaceReco->positions();
173  //Fixing the embedding
174  std::for_each(std::begin(positionsReco), std::end(positionsReco), [&](RealPoint &p){p=p*h;});
175 
176  std::vector<std::vector<SH3::SurfaceMesh::Vertex>> facesReco;
177  for(auto face= 0 ; face < primalSurfaceReco->nbFaces(); ++face)
178  facesReco.push_back(primalSurfaceReco->incidentVertices( face ));
179  auto psMesh = polyscope::registerSurfaceMesh("Reconstruction "+std::to_string(h), positionsReco, facesReco);
180  };
181 
182  resample_h(1.0);
183  resample_h(2.0); //downscaling
184  resample_h(0.5); //upscaling
185 #if defined(NDEBUG)
186  resample_h(0.2); //upscaling
187  resample_h(0.2); //upscaling
188 #else
189  trace.warning() << "CMake Debug mode detected, limiting upscaling to 0.5.";
190 #endif
191  //resample_h(0.07); //extreme upscaling, 2M vertices
192 
193  // Set the callback function
194  polyscope::show();
195  return EXIT_SUCCESS;
196 }
Aim: Smart pointer based on reference counts.
Definition: CountedPtr.h:80
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
std::set< SCell > SurfelSet
Preferred type for defining a set of surfels (always signed cells).
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
Aim: A simple point embedder where grid steps are given for each axis. Note that the real point (0,...
Point floor(const RealPoint &p) const
Point ceil(const RealPoint &p) const
void init(typename RealVector::Component gridStep)
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as connected surfels....
Definition: SetOfSurfels.h:74
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
std::map< Cell, IdxVertex > Cell2Index
Definition: Shortcuts.h:189
static void sMakeBoundary(SCellSet &aBoundary, const KSpace &aKSpace, const PointPredicate &pp, const Point &aLowerBound, const Point &aUpperBound)
std::ostream & info()
std::ostream & warning()
SurfaceMesh< RealPoint, RealVector > SurfMesh
polyscope::SurfaceMesh * psMesh
SurfMesh surfmesh
CountedPtr< SH3::DigitalSurface > surface
CountedPtr< SH3::BinaryImage > binary_image
SHG3::RealVectors iinormals
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
MyDigitalSurface::SurfelSet SurfelSet
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:153
@ INSIDE
Definition: Common.h:141
Aim: Represents an embedded mesh as faces and a list of vertices. Vertices may be shared among faces ...
Definition: SurfaceMesh.h:92
Aim: model of a CEuclideanOrientedShape from an implicit function from an oriented point cloud....
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
Domain domain
Vector lower(const Vector &z, unsigned int k)
Vector upper(const Vector &z, unsigned int k)