DGtalTools  0.9.4
shapeGenerator.cpp
1 
29 #include <iostream>
31 #include <vector>
32 #include <string>
33 
34 #include <boost/program_options/options_description.hpp>
35 #include <boost/program_options/parsers.hpp>
36 #include <boost/program_options/variables_map.hpp>
37 
38 #include "DGtal/base/Common.h"
39 
40 #include "DGtal/shapes/ShapeFactory.h"
41 #include "DGtal/shapes/Shapes.h"
42 #include "DGtal/helpers/StdDefs.h"
43 #include "DGtal/topology/helpers/Surfaces.h"
44 
45 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
46 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
47 #include "DGtal/images/ImageContainerBySTLVector.h"
48 
49 #include "DGtal/io/writers/PGMWriter.h"
50 #include "DGtal/io/writers/RawWriter.h"
51 #include "DGtal/io/writers/VolWriter.h"
52 #include "DGtal/io/boards/Board2D.h"
53 
54 
55 using namespace DGtal;
56 
57 
131 std::vector<std::string> shapes2D;
132 std::vector<std::string> shapesDesc;
133 std::vector<std::string> shapesParam1;
134 std::vector<std::string> shapesParam2;
135 std::vector<std::string> shapesParam3;
136 std::vector<std::string> shapesParam4;
137 
138 
143 void createList()
144 {
145  shapes2D.push_back("ball");
146  shapesDesc.push_back("Ball for the Euclidean metric.");
147  shapesParam1.push_back("--radius [-R]");
148  shapesParam2.push_back("");
149  shapesParam3.push_back("");
150  shapesParam4.push_back("");
151 
152  shapes2D.push_back("square");
153  shapesDesc.push_back("square (no signature).");
154  shapesParam1.push_back("--width [-w]");
155  shapesParam2.push_back("");
156  shapesParam3.push_back("");
157  shapesParam4.push_back("");
158 
159  shapes2D.push_back("lpball");
160  shapesDesc.push_back("Ball for the l_power metric (no signature).");
161  shapesParam1.push_back("--radius [-R],");
162  shapesParam2.push_back("--power [-p]");
163  shapesParam3.push_back("");
164  shapesParam4.push_back("");
165 
166  shapes2D.push_back("flower");
167  shapesDesc.push_back("Flower with k petals.");
168  shapesParam1.push_back("--radius [-R],");
169  shapesParam2.push_back("--varsmallradius [-v],");
170  shapesParam3.push_back("--k [-k],");
171  shapesParam4.push_back("--phi");
172 
173  shapes2D.push_back("ngon");
174  shapesDesc.push_back("Regular k-gon.");
175  shapesParam1.push_back("--radius [-R],");
176  shapesParam2.push_back("--k [-k],");
177  shapesParam3.push_back("--phi");
178  shapesParam4.push_back("");
179 
180  shapes2D.push_back("accflower");
181  shapesDesc.push_back("Accelerated Flower with k petals.");
182  shapesParam1.push_back("--radius [-R],");
183  shapesParam2.push_back("--varsmallradius [-v],");
184  shapesParam3.push_back("--k [-k],");
185  shapesParam4.push_back("--phi");
186 
187  shapes2D.push_back("ellipse");
188  shapesDesc.push_back("Ellipse.");
189  shapesParam1.push_back("--axis1 [-A],");
190  shapesParam2.push_back("--axis2 [-a],");
191  shapesParam3.push_back("--phi");
192  shapesParam4.push_back("");
193 
194 
195 }
196 
201 void displayList()
202 {
203  trace.emphase()<<"2D Shapes:"<<std::endl;
204  for(unsigned int i=0; i<shapes2D.size(); ++i)
205  trace.info()<<"\t"<<shapes2D[i]<<"\t"
206  <<shapesDesc[i]<<std::endl
207  <<"\t\tRequired parameter(s): "
208  << shapesParam1[i]<<" "
209  << shapesParam2[i]<<" "
210  << shapesParam3[i]<<" "
211  << shapesParam4[i]<<std::endl;
212 
213 }
214 
215 
224 unsigned int checkAndRetrunIndex(const std::string &shapeName)
225 {
226  unsigned int pos=0;
227 
228  while ((pos < shapes2D.size()) && (shapes2D[pos] != shapeName))
229  pos++;
230 
231  if (pos == shapes2D.size())
232  {
233  trace.error() << "The specified shape has not found.";
234  trace.info()<<std::endl;
235  exit(1);
236  }
237 
238  return pos;
239 }
240 
241 
249 template <typename Set, typename Image>
250 struct Exporter
251 {
252 
261  static
262  void save(const Set &aSet,
263  const std::string outputName,
264  const std::string outputFormat)
265  {
266 
267  Image image = ImageFromSet<Image>::template create<Set>(aSet, 255, true);
268 
269  if (outputFormat == "pgm")
270  PGMWriter<Image>::exportPGM(outputName+"."+outputFormat,image);
271  else
272  if (outputFormat == "raw")
273  RawWriter<Image>::exportRaw8(outputName+"."+outputFormat,image);
274  else
275  if (outputFormat == "svg")
276  {
277  Board2D board;
278  board << aSet;
279  board.saveSVG((outputName+"."+outputFormat).c_str());
280  }
281  else
282 #ifdef WITH_CAIRO
283  if (outputFormat == "pdf")
284  {
285  Board2D board;
286  board << aSet;
287  board.saveCairo((outputName+"."+outputFormat).c_str(), Board2D::CairoPDF);
288 
289  }
290  else
291  if (outputFormat == "png")
292  {
293  Board2D board;
294  board << aSet;
295  board.saveCairo((outputName+"."+outputFormat).c_str(), Board2D::CairoPNG);
296  }
297  else
298 #endif
299  {
300  trace.error()<< "Output format: "<<outputFormat<< " not recognized."<<std::endl;
301  exit(1);
302  }
303  }
304 
305 
306 
307 
308 
309 
318  template <typename Shape>
319  static
320  void exportSignature(const Shape & aShape, Set &aSet, const Z2i::Domain &aDomain)
321  {
322  trace.beginBlock("Extracting the boundary");
323  Z2i::KSpace ks;
324  bool space_ok = ks.init( aDomain.lowerBound(),aDomain.upperBound(), true );
325  SurfelAdjacency<2> sAdj( true );
326 
327  ASSERT(space_ok);
328  trace.info() << aSet << std::endl;
329  trace.info() << ks
330  << ( space_ok ? " Successfully instantiated" : " Error" )
331  << std::endl;
332 
333  std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels;
334  Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels,
335  ks, aSet, sAdj );
336  trace.endBlock();
337 
339  std::cout<<"## shapeGenerator signature export"<<std::endl;
340  std::cout<<"## shape: "<<aShape<<std::endl;
341  std::cout<<"## x\ty\tdx\tdy\tddx\tddy"<<std::endl;
342  for(unsigned int i=0; i<vectContoursBdryPointels.size(); i++)
343  for(unsigned int j=0 ; j< vectContoursBdryPointels.at(i).size() - 1; j++)
344  {
345  Z2i::Space::Point point = (vectContoursBdryPointels.at(i).at(j)
346  + vectContoursBdryPointels.at(i).at(j+1));
347  Z2i::Space::RealPoint midpoint (point[0]/2.0,point[1]/2.0);
348 
349  Z2i::Space::RealPoint xp,xpp;
350  double t = aShape.parameter(midpoint);
351  xp = aShape.xp( t );
352  xpp = aShape.xpp( t );
353 
354  std::cout<< midpoint[0]<<"\t"<<midpoint[1]<<"\t"
355  << xp[0]<<"\t"<<xp[1]<<"\t"
356  << xpp[0]<<"\t"<<xpp[1]<<std::endl;
357 
358  }
359 
360  }
361 };
362 
368 void missingParam(std::string param)
369 {
370  trace.error() <<" Parameter: "<<param<<" is required..";
371  trace.info()<<std::endl;
372  exit(1);
373 }
374 
376 namespace po = boost::program_options;
377 
378 int main( int argc, char** argv )
379 {
380  // parse command line ----------------------------------------------
381  po::options_description general_opt("Allowed options are: ");
382  general_opt.add_options()
383  ("help,h", "display this message")
384  ("shape,s", po::value<std::string>(), "Shape name")
385  ("list,l", "List all available shapes")
386  ("radius,R", po::value<double>(), "Radius of the shape" )
387  ("axis1,A", po::value<double>(), "Half big axis of the shape (ellipse)" )
388  ("axis2,a", po::value<double>(), "Half small axis of the shape (ellipse)" )
389  ("smallradius,r", po::value<double>()->default_value(5), "Small radius of the shape" )
390  ("varsmallradius,v", po::value<double>()->default_value(5), "Variable small radius of the shape" )
391  ("k,k", po::value<unsigned int>()->default_value(3), "Number of branches or corners the shape" )
392  ("phi", po::value<double>()->default_value(0.0), "Phase of the shape (in radian)" )
393  ("width,w", po::value<double>()->default_value(10.0), "Width of the shape" )
394  ("power,p", po::value<double>()->default_value(2.0), "Power of the metric (double)" )
395  ("output,o", po::value<std::string>(), "Basename of the output file")
396  ("signature", "Display to the standard output the signature (normal, curvature) at each point of the specified shape contour (middle point of each contour linel)")
397  ("format,f", po::value<std::string>()->default_value("pgm"), "Output format:\n\t Bitmap {pgm, raw}\n\t Vector {svg} (+ {png,pdf} if libCairo installed)" );
398 
399  bool parseOK=true;
400  po::variables_map vm;
401  try{
402  po::store(po::parse_command_line(argc, argv, general_opt), vm);
403  }catch(const std::exception& ex){
404  parseOK=false;
405  trace.info()<< "Error checking program options: "<< ex.what()<< std::endl;
406  }
407 
408  po::notify(vm);
409  if(!parseOK || vm.count("help")||argc<=1)
410  {
411  trace.info()<< "Generate shapes using DGtal library" <<std::endl << "Basic usage: "<<std::endl
412  << "\tshapeGenerator [options] --shape <shapeName> --output <outputBasename>"<<std::endl
413  << general_opt << "\n";
414  return 0;
415  }
416 
417  //List creation
418  createList();
419 
420  if (vm.count("list"))
421  {
422  displayList();
423  return 0;
424  }
425 
426  //Parse options
427  if (!(vm.count("shape"))) missingParam("--shape");
428  std::string shapeName = vm["shape"].as<std::string>();
429 
430 
431  if (!(vm.count("output"))) missingParam("--output");
432  std::string outputName = vm["output"].as<std::string>();
433 
434  if (!(vm.count("format"))) missingParam("--format");
435  std::string outputFormat = vm["format"].as<std::string>();
436 
437  //We check that the shape is known
438  unsigned int id = checkAndRetrunIndex(shapeName);
440 
441  if (id ==0)
442  {
443  if (!(vm.count("radius"))) missingParam("--radius");
444  double radius = vm["radius"].as<double>();
445 
446  Ball2D<Z2i::Space> ball(Z2i::Point(0,0), radius);
447  Z2i::Domain domain(ball.getLowerBound(), ball.getUpperBound());
448  Z2i::DigitalSet aSet(domain);
449 
451  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
452 
453  if (vm.count("signature"))
454  Exporter<Z2i::DigitalSet,Image>::exportSignature(ball,aSet,domain);
455 
456  return 0;
457  }
458  else
459  if (id ==1)
460  {
461  if (!(vm.count("width"))) missingParam("--width");
462  double width = vm["width"].as<double>();
463 
464  ImplicitHyperCube<Z2i::Space> object(Z2i::Point(0,0), width/2.0);
465  Z2i::Domain domain(object.getLowerBound(), object.getUpperBound());
466  Z2i::DigitalSet aSet(domain);
467 
469  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
470 
471  if (vm.count("signature"))
472  {
473  trace.error()<< "No signature export for this shape.";
474  trace.info()<<std::endl;
475  }
476 
477  return 0;
478  }
479  else
480  if (id ==2)
481  {
482  if (!(vm.count("power"))) missingParam("--power");
483  if (!(vm.count("radius"))) missingParam("--radius");
484  double radius = vm["radius"].as<double>();
485  double power = vm["power"].as<double>();
486 
487  ImplicitRoundedHyperCube<Z2i::Space> ball(Z2i::Point(0,0), radius, power);
488  Z2i::Domain domain(ball.getLowerBound(), ball.getUpperBound());
489  Z2i::DigitalSet aSet(domain);
490 
492  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
493 
494  if (vm.count("signature"))
495  {
496  trace.error()<< "No signature export for this shape.";
497  trace.info()<<std::endl;
498  }
499 
500  return 0;
501  }
502  else
503  if (id ==3)
504  {
505  if (!(vm.count("varsmallradius"))) missingParam("--varsmallradius");
506  if (!(vm.count("radius"))) missingParam("--radius");
507  if (!(vm.count("k"))) missingParam("--k");
508  if (!(vm.count("phi"))) missingParam("--phi");
509  double radius = vm["radius"].as<double>();
510  double varsmallradius = vm["varsmallradius"].as<double>();
511  unsigned int k = vm["k"].as<unsigned int>();
512  double phi = vm["phi"].as<double>();
513 
514  Flower2D<Z2i::Space> flower(Z2i::Point(0,0), radius, varsmallradius,k,phi);
515  Z2i::Domain domain(flower.getLowerBound(), flower.getUpperBound());
516  Z2i::DigitalSet aSet(domain);
517 
519  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
520 
521  if (vm.count("signature"))
522  Exporter<Z2i::DigitalSet,Image>::exportSignature(flower,aSet,domain);
523 
524  return 0;
525  }
526  else
527  if (id ==4)
528  {
529  if (!(vm.count("radius"))) missingParam("--radius");
530  if (!(vm.count("k"))) missingParam("--k");
531  if (!(vm.count("phi"))) missingParam("--phi");
532  double radius = vm["radius"].as<double>();
533  unsigned int k = vm["k"].as<unsigned int>();
534  double phi = vm["phi"].as<double>();
535 
536  NGon2D<Z2i::Space> object(Z2i::Point(0,0), radius,k,phi);
537  Z2i::Domain domain(object.getLowerBound(), object.getUpperBound());
538  Z2i::DigitalSet aSet(domain);
539 
541  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
542 
543  if (vm.count("signature"))
544  Exporter<Z2i::DigitalSet,Image>::exportSignature(object,aSet,domain);
545 
546  return 0;
547  }
548  else
549  if (id ==5)
550  {
551  if (!(vm.count("varsmallradius"))) missingParam("--varsmallradius");
552  if (!(vm.count("radius"))) missingParam("--radius");
553  if (!(vm.count("k"))) missingParam("--k");
554  if (!(vm.count("phi"))) missingParam("--phi");
555  double radius = vm["radius"].as<double>();
556  double varsmallradius = vm["varsmallradius"].as<double>();
557  unsigned int k = vm["k"].as<unsigned int>();
558  double phi = vm["phi"].as<double>();
559 
560  AccFlower2D<Z2i::Space> flower(Z2i::Point(0,0), radius, varsmallradius,k,phi);
561  Z2i::Domain domain(flower.getLowerBound(), flower.getUpperBound());
562  Z2i::DigitalSet aSet(domain);
563 
565  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
566 
567  if (vm.count("signature"))
568  Exporter<Z2i::DigitalSet,Image>::exportSignature(flower,aSet,domain);
569 
570  return 0;
571  }
572  else
573  //if (id ==6)
574  {
575  if (!(vm.count("axis1"))) missingParam("--axis1");
576  if (!(vm.count("axis2"))) missingParam("--axis2");
577  if (!(vm.count("phi"))) missingParam("--phi");
578  double a1 = vm["axis1"].as<double>();
579  double a2 = vm["axis2"].as<double>();
580  double phi = vm["phi"].as<double>();
581 
582  Ellipse2D<Z2i::Space> ell(Z2i::Point(0,0), a1, a2,phi);
583  Z2i::Domain domain(ell.getLowerBound(), ell.getUpperBound());
584  Z2i::DigitalSet aSet(domain);
585 
587  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
588 
589  if (vm.count("signature"))
590  Exporter<Z2i::DigitalSet,Image>::exportSignature(ell,aSet,domain);
591 
592  return 0;
593  }
594 }
void beginBlock(const std::string &keyword="")
static void extractAllPointContours4C(std::vector< std::vector< Point > > &aVectPointContour2D, const KSpace &aKSpace, const PointPredicate &pp, const SurfelAdjacency< 2 > &aSAdj)
double endBlock()
T power(const T &aVal, const unsigned int exponent)
static void euclideanShaper(TDigitalSet &aSet, const TShapeFunctor &aFunctor, const double h=1.0)
static bool exportRaw8(const std::string &filename, const Image &aImage, const Functor &aFunctor=Functor())
void saveCairo(const char *filename, CairoType type=CairoPNG, PageSize size=Board::BoundingBox, double margin=10.0) const
std::ostream & emphase()
bool init(const Point &lower, const Point &upper, bool isClosed)
const Point & upperBound() const
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Trace trace(traceWriterTerm)
std::ostream & info()
static bool exportPGM(const std::string &filename, const Image &aImage, const Functor &aFunctor=Functor(), bool saveASCII=false, bool topbotomOrder=true)
const Point & lowerBound() const
std::ostream & error()