DGtalTools  0.9.4
mesh2vol.cpp
1 
27 #include <iostream>
29 #include <fstream>
30 #include <chrono>
31 #include "DGtal/helpers/StdDefs.h"
32 #include "DGtal/shapes/MeshVoxelizer.h"
33 #include "DGtal/kernel/sets/CDigitalSet.h"
34 #include "DGtal/kernel/domains/HyperRectDomain.h"
35 #include "DGtal/io/readers/MeshReader.h"
36 #include "DGtal/io/Display3D.h"
37 #include "DGtal/io/writers/GenericWriter.h"
38 #include "DGtal/images/ImageContainerBySTLVector.h"
39 #include <boost/program_options/options_description.hpp>
40 #include <boost/program_options/parsers.hpp>
41 #include <boost/program_options/variables_map.hpp>
42 
43 using namespace std;
44 using namespace DGtal;
45 
47 namespace po = boost::program_options;
48 
77 template< unsigned int SEP >
78 void voxelizeAndExport(const std::string& inputFilename,
79  const std::string& outputFilename,
80  const unsigned int resolution,
81  const unsigned int margin)
82 {
83  using Domain = Z3i::Domain;
84  using PointR3 = Z3i::RealPoint;
85  using PointZ3 = Z3i::Point;
86 
87  trace.beginBlock("Preparing the mesh");
88  trace.info() << "Reading input file: " << inputFilename;
89  Mesh<PointR3> inputMesh;
90  MeshReader<PointR3>::importOFFFile(inputFilename.c_str(), inputMesh);
91  trace.info() << " [done]" << std::endl;
92  const std::pair<PointR3, PointR3> bbox = inputMesh.getBoundingBox();
93  trace.info()<< "Mesh bounding box: "<<bbox.first <<" "<<bbox.second<<std::endl;
94 
95  const double smax = (bbox.second - bbox.first).max();
96  const double factor = resolution / smax;
97  const PointR3 translate = -bbox.first;
98  trace.info() << "Scale = "<<factor<<" translate = "<<translate<<std::endl;
99  for(auto it = inputMesh.vertexBegin(), itend = inputMesh.vertexEnd();
100  it != itend; ++it)
101  {
102  //scale + translation
103  *it += translate;
104  *it *= factor;
105  }
106  trace.endBlock();
107 
108  trace.beginBlock("Voxelization");
109  trace.info() << "Voxelization " << SEP << "-separated ; " << resolution << "^3 ";
110  Domain aDomain(PointZ3().diagonal(-margin), PointZ3().diagonal(resolution+margin));
111 
112  //Digitization step
113  Z3i::DigitalSet mySet(aDomain);
114  MeshVoxelizer<Z3i::DigitalSet, SEP> aVoxelizer;
115  aVoxelizer.voxelize(mySet, inputMesh, 1.0);
116  trace.info() << " [done] " << std::endl;
117  trace.endBlock();
118 
119  trace.beginBlock("Exporting");
120  // Export the digital set to a vol file
121  trace.info()<<aDomain<<std::endl;
123  for(auto p: mySet)
124  image.setValue(p, 128);
125  image >> outputFilename.c_str();
126  trace.endBlock();
127 }
128 
129 int main( int argc, char** argv )
130 {
131  // parse command line ----------------------------------------------
132  po::options_description general_opt("\nAllowed options are");
133  general_opt.add_options()
134  ("help,h", "display this message")
135  ("input,i", po::value<std::string>(), "mesh file (.off) " )
136  ("output,o", po::value<std::string>(), "filename of ouput volumetric file (vol, pgm3d, ...).")
137  ("margin,m", po::value<unsigned int>()->default_value(0), "add volume margin around the mesh bounding box.")
138  ("separation,s", po::value<unsigned int>()->default_value(6), "voxelization 6-separated or 26-separated." )
139  ("resolution,r", po::value<unsigned int>(), "digitization domain size (e.g. 128). The mesh will be scaled such that its bounding box maps to [0,resolution)^3." );
140 
141  bool parseOK=true;
142  po::variables_map vm;
143  try {
144  po::store(po::parse_command_line(argc, argv, general_opt), vm);
145  } catch(const std::exception& ex) {
146  parseOK=false;
147  trace.info() << "Error checking program options: " << ex.what() << endl;
148  }
149 
150  po::notify(vm);
151 
152  if(!parseOK || vm.count("help") || argc < 1)
153  {
154  std::cout << "Usage: " << argv[0] << " -i [input]\n"
155  << "Convert a mesh file into a 26-separated or 6-separated volumetric voxelization in a given resolution grid."
156  << general_opt << "\n";
157  std::cout << "Example:\n"
158  << "mesh2vol -i ${DGtal}/examples/samples/tref.off -o output.vol --separation 26 --resolution 256 \n";
159  return -1;
160  }
161 
162  if( !vm.count("input") )
163  {
164  trace.error() << " Input filename is needed to be defined" << endl;
165  return -1;
166  }
167 
168  if( vm["separation"].as<unsigned int>() != 6 &&
169  vm["separation"].as<unsigned int>() != 26 )
170  {
171  trace.error() << " Separation should be 6 or 26" << endl;
172  return -1;
173  }
174  unsigned int margin = vm["margin"].as<unsigned int>();
175  unsigned int separation = vm["separation"].as<unsigned int>();
176  unsigned int resolution;
177  if (vm.count("resolution"))
178  resolution = vm["resolution"].as<unsigned int>();
179  else
180  {
181  trace.error()<<"Missing output parameter '--resolution'"<<std::endl;
182  return -1;
183  }
184 
185  string inputFilename = vm["input"].as<std::string>();
186  string outputFilename;
187 
188  if( vm.count("output") )
189  outputFilename = vm["output"].as<std::string>();
190  else
191  {
192  trace.error()<<"Missing output parameter '--output'"<<std::endl;
193  return -1;
194  }
195 
196 
197  if(separation == 6)
198  voxelizeAndExport<6>(inputFilename, outputFilename, resolution, margin);
199  else if(separation == 26)
200  voxelizeAndExport<26>(inputFilename, outputFilename, resolution, margin);
201 
202  return 0;
203 }
204 
void beginBlock(const std::string &keyword="")
ConstIterator vertexEnd() const
DGtal::LinearOperator< Calculus, dim, duality, dim, duality > diagonal(const DGtal::KForm< Calculus, dim, duality > &kform)
STL namespace.
double endBlock()
ConstIterator vertexBegin() const
Trace trace(traceWriterTerm)
std::ostream & info()
std::pair< TPoint, TPoint > getBoundingBox() const
std::ostream & error()
typename Self::Domain Domain