DGtalTools  1.3.beta
shapeGenerator.cpp
1 
29 #include <iostream>
31 #include <vector>
32 #include <string>
33 
34 #include "CLI11.hpp"
35 
36 #include "DGtal/base/Common.h"
37 
38 #include "DGtal/shapes/ShapeFactory.h"
39 #include "DGtal/shapes/Shapes.h"
40 #include "DGtal/helpers/StdDefs.h"
41 #include "DGtal/topology/helpers/Surfaces.h"
42 
43 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
44 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
45 #include "DGtal/images/ImageContainerBySTLVector.h"
46 
47 #include "DGtal/io/writers/PGMWriter.h"
48 #include "DGtal/io/writers/RawWriter.h"
49 #include "DGtal/io/writers/VolWriter.h"
50 #include "DGtal/io/boards/Board2D.h"
51 
52 
53 using namespace DGtal;
54 
55 
125 std::vector<std::string> shapes2D;
126 std::vector<std::string> shapesDesc;
127 std::vector<std::string> shapesParam1;
128 std::vector<std::string> shapesParam2;
129 std::vector<std::string> shapesParam3;
130 std::vector<std::string> shapesParam4;
131 
132 
137 void createList()
138 {
139  shapes2D.push_back("ball");
140  shapesDesc.push_back("Ball for the Euclidean metric.");
141  shapesParam1.push_back("--radius [-R]");
142  shapesParam2.push_back("");
143  shapesParam3.push_back("");
144  shapesParam4.push_back("");
145 
146  shapes2D.push_back("square");
147  shapesDesc.push_back("square (no signature).");
148  shapesParam1.push_back("--width [-w]");
149  shapesParam2.push_back("");
150  shapesParam3.push_back("");
151  shapesParam4.push_back("");
152 
153  shapes2D.push_back("lpball");
154  shapesDesc.push_back("Ball for the l_power metric (no signature).");
155  shapesParam1.push_back("--radius [-R],");
156  shapesParam2.push_back("--power [-p]");
157  shapesParam3.push_back("");
158  shapesParam4.push_back("");
159 
160  shapes2D.push_back("flower");
161  shapesDesc.push_back("Flower with k petals.");
162  shapesParam1.push_back("--radius [-R],");
163  shapesParam2.push_back("--varsmallradius [-v],");
164  shapesParam3.push_back("--k [-k],");
165  shapesParam4.push_back("--phi");
166 
167  shapes2D.push_back("ngon");
168  shapesDesc.push_back("Regular k-gon.");
169  shapesParam1.push_back("--radius [-R],");
170  shapesParam2.push_back("--k [-k],");
171  shapesParam3.push_back("--phi");
172  shapesParam4.push_back("");
173 
174  shapes2D.push_back("accflower");
175  shapesDesc.push_back("Accelerated Flower with k petals.");
176  shapesParam1.push_back("--radius [-R],");
177  shapesParam2.push_back("--varsmallradius [-v],");
178  shapesParam3.push_back("--k [-k],");
179  shapesParam4.push_back("--phi");
180 
181  shapes2D.push_back("ellipse");
182  shapesDesc.push_back("Ellipse.");
183  shapesParam1.push_back("--axis1 [-A],");
184  shapesParam2.push_back("--axis2 [-a],");
185  shapesParam3.push_back("--phi");
186  shapesParam4.push_back("");
187 
188 
189 }
190 
195 void displayList()
196 {
197  trace.emphase()<<"2D Shapes:"<<std::endl;
198  for(unsigned int i=0; i<shapes2D.size(); ++i)
199  trace.info()<<"\t"<<shapes2D[i]<<"\t"
200  <<shapesDesc[i]<<std::endl
201  <<"\t\tRequired parameter(s): "
202  << shapesParam1[i]<<" "
203  << shapesParam2[i]<<" "
204  << shapesParam3[i]<<" "
205  << shapesParam4[i]<<std::endl;
206 
207 }
208 
209 
218 unsigned int checkAndRetrunIndex(const std::string &shapeName)
219 {
220  unsigned int pos=0;
221 
222  while ((pos < shapes2D.size()) && (shapes2D[pos] != shapeName))
223  pos++;
224 
225  if (pos == shapes2D.size())
226  {
227  trace.error() << "The specified shape has not found.";
228  trace.info()<<std::endl;
229  exit(1);
230  }
231 
232  return pos;
233 }
234 
235 
243 template <typename Set, typename Image>
244 struct Exporter
245 {
246 
255  static
256  void save(const Set &aSet,
257  const std::string outputName,
258  const std::string outputFormat)
259  {
260 
261  Image image = ImageFromSet<Image>::template create<Set>(aSet, 255, true);
262 
263  if (outputFormat == "pgm")
264  PGMWriter<Image>::exportPGM(outputName+"."+outputFormat,image);
265  else
266  if (outputFormat == "raw")
267  RawWriter<Image>::exportRaw8(outputName+"."+outputFormat,image);
268  else
269  if (outputFormat == "svg")
270  {
271  Board2D board;
272  board << aSet;
273  board.saveSVG((outputName+"."+outputFormat).c_str());
274  }
275  else
276 #ifdef WITH_CAIRO
277  if (outputFormat == "pdf")
278  {
279  Board2D board;
280  board << aSet;
281  board.saveCairo((outputName+"."+outputFormat).c_str(), Board2D::CairoPDF);
282 
283  }
284  else
285  if (outputFormat == "png")
286  {
287  Board2D board;
288  board << aSet;
289  board.saveCairo((outputName+"."+outputFormat).c_str(), Board2D::CairoPNG);
290  }
291  else
292 #endif
293  {
294  trace.error()<< "Output format: "<<outputFormat<< " not recognized."<<std::endl;
295  exit(1);
296  }
297  }
298 
299 
300 
301 
302 
303 
312  template <typename Shape>
313  static
314  void exportSignature(const Shape & aShape, Set &aSet, const Z2i::Domain &aDomain)
315  {
316  trace.beginBlock("Extracting the boundary");
317  Z2i::KSpace ks;
318  bool space_ok = ks.init( aDomain.lowerBound(),aDomain.upperBound(), true );
319  SurfelAdjacency<2> sAdj( true );
320 
321  ASSERT(space_ok);
322  trace.info() << aSet << std::endl;
323  trace.info() << ks
324  << ( space_ok ? " Successfully instantiated" : " Error" )
325  << std::endl;
326 
327  std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels;
328  Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels,
329  ks, aSet, sAdj );
330  trace.endBlock();
331 
333  std::cout<<"## shapeGenerator signature export"<<std::endl;
334  std::cout<<"## shape: "<<aShape<<std::endl;
335  std::cout<<"## x\ty\tdx\tdy\tddx\tddy"<<std::endl;
336  for(unsigned int i=0; i<vectContoursBdryPointels.size(); i++)
337  for(unsigned int j=0 ; j< vectContoursBdryPointels.at(i).size() - 1; j++)
338  {
339  Z2i::Space::Point point = (vectContoursBdryPointels.at(i).at(j)
340  + vectContoursBdryPointels.at(i).at(j+1));
341  Z2i::Space::RealPoint midpoint (point[0]/2.0,point[1]/2.0);
342 
343  Z2i::Space::RealPoint xp,xpp;
344  double t = aShape.parameter(midpoint);
345  xp = aShape.xp( t );
346  xpp = aShape.xpp( t );
347 
348  std::cout<< midpoint[0]<<"\t"<<midpoint[1]<<"\t"
349  << xp[0]<<"\t"<<xp[1]<<"\t"
350  << xpp[0]<<"\t"<<xpp[1]<<std::endl;
351 
352  }
353 
354  }
355 };
356 
362 void missingParam(std::string param)
363 {
364  trace.error() <<" Parameter: "<<param<<" is required..";
365  trace.info()<<std::endl;
366  exit(1);
367 }
368 
370 
371 int main( int argc, char** argv )
372 {
373  // parse command line CLI ----------------------------------------------
374  CLI::App app;
375  std::string shapeName;
376  std::string outputName;
377  std::string outputFormat {"pgm"};
378  double radius;
379  double power {2.0};
380  double smallradius {5};
381  double varsmallradius {5};
382  unsigned int k {3};
383  double phi {0.0};
384  double width {10.0};
385  double axis1, axis2;
386 
387  app.description("Generates shapes using DGtal library.\n Typical use example:\n \t shapeGenerator [options] --shape <shapeName> --output <outputBasename>\n");
388  auto listOpt = app.add_flag("--list,-l","List all available shapes");
389  auto shapeNameOpt = app.add_option("--shape,-s", shapeName, "Shape name");
390  auto radiusOpt = app.add_option("--radius,-R", radius, "Radius of the shape" );
391  auto axis1Opt = app.add_option("--axis1,-A", axis1, "Half big axis of the shape (ellipse)" );
392  auto axis2Opt = app.add_option("--axis2,-a", axis2, "Half small axis of the shape (ellipse)" );
393  auto smallradiusOpt = app.add_option("--smallradius,-r", smallradius, "Small radius of the shape (default 5)", true);
394  auto varsmallradiusOpt = app.add_option("--varsmallradius,-v", varsmallradius, "Variable small radius of the shape (default 5)", true );
395  auto kOpt = app.add_option("-k", k, "Number of branches or corners the shape (default 3)", true );
396  auto phiOpt = app.add_option("--phi", phi, "Phase of the shape (in radian, default 0.0)", true );
397  auto widthOpt = app.add_option("--width,-w", width, "Width of the shape (default 10.0)", true );
398  auto powerOpt = app.add_option("--power,-p", power, "Power of the metric (default 2.0)", true );
399  auto outputNameOpt = app.add_option("--output,-o", outputName, "Basename of the output file");
400  auto signatureOpt = app.add_flag("--signature", "Display to the standard output the signature (normal, curvature) at each point of the specified shape contour (middle point of each contour linel)");
401  app.add_option("--format,-f", outputFormat, "Output format:\n\t Bitmap {pgm, raw}\n\t Vector {svg} (+ {png,pdf} if libCairo installed) (default pgm)" );
402 
403  app.get_formatter()->column_width(40);
404  CLI11_PARSE(app, argc, argv);
405  // END parse command line using CLI ----------------------------------------------
406 
407  //List creation
408  createList();
409 
410  if ( listOpt->count() > 0 )
411  {
412  displayList();
413  return 0;
414  }
415 
416  if(shapeNameOpt->count()==0) missingParam("--shape");
417  if(outputNameOpt->count()==0) missingParam("--output");
418 
419  //We check that the shape is known
420  unsigned int id = checkAndRetrunIndex(shapeName);
422 
423  if (id ==0)
424  {
425  if (radiusOpt->count()==0) missingParam("--radius");
426  Ball2D<Z2i::Space> ball(Z2i::Point(0,0), radius);
427  Z2i::Domain domain(ball.getLowerBound(), ball.getUpperBound());
428  Z2i::DigitalSet aSet(domain);
429 
431  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
432 
433  if (signatureOpt->count()>0)
434  Exporter<Z2i::DigitalSet,Image>::exportSignature(ball,aSet,domain);
435 
436  return 0;
437  }
438  else
439  if (id ==1)
440  {
441  //if (widthOpt->count()==0) missingParam("--width");
442  ImplicitHyperCube<Z2i::Space> object(Z2i::Point(0,0), width/2.0);
443  Z2i::Domain domain(object.getLowerBound(), object.getUpperBound());
444  Z2i::DigitalSet aSet(domain);
445 
447  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
448 
449  if (signatureOpt->count()>0)
450  {
451  trace.error()<< "No signature export for this shape.";
452  trace.info()<<std::endl;
453  }
454 
455  return 0;
456  }
457  else
458  if (id ==2)
459  {
460  //if (powerOpt->count()==0) missingParam("--power");
461  if (radiusOpt->count()==0) missingParam("--radius");
462  ImplicitRoundedHyperCube<Z2i::Space> ball(Z2i::Point(0,0), radius, power);
463  Z2i::Domain domain(ball.getLowerBound(), ball.getUpperBound());
464  Z2i::DigitalSet aSet(domain);
465 
467  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
468 
469  if (signatureOpt->count()>0)
470  {
471  trace.error()<< "No signature export for this shape.";
472  trace.info()<<std::endl;
473  }
474 
475  return 0;
476  }
477  else
478  if (id ==3)
479  {
480  //if (varsmallradiusOpt->count()==0) missingParam("--varsmallradius");
481  if (radiusOpt->count()==0) missingParam("--radius");
482  //if (kOpt->count()==0) missingParam("--k");
483  //if (phiOpt->count()==0) missingParam("--phi");
484  Flower2D<Z2i::Space> flower(Z2i::Point(0,0), radius, varsmallradius,k,phi);
485  Z2i::Domain domain(flower.getLowerBound(), flower.getUpperBound());
486  Z2i::DigitalSet aSet(domain);
487 
489  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
490 
491  if (signatureOpt->count()>0)
492  Exporter<Z2i::DigitalSet,Image>::exportSignature(flower,aSet,domain);
493 
494  return 0;
495  }
496  else
497  if (id ==4)
498  {
499  if (radiusOpt->count()==0) missingParam("--radius");
500  //if (kOpt->count()==0) missingParam("--k");
501  //if (phiOpt->count()==0) missingParam("--phi");
502  NGon2D<Z2i::Space> object(Z2i::Point(0,0), radius,k,phi);
503  Z2i::Domain domain(object.getLowerBound(), object.getUpperBound());
504  Z2i::DigitalSet aSet(domain);
505 
507  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
508 
509  if (signatureOpt->count()>0)
510  Exporter<Z2i::DigitalSet,Image>::exportSignature(object,aSet,domain);
511 
512  return 0;
513  }
514  else
515  if (id ==5)
516  {
517  //if (varsmallradiusOpt->count()==0) missingParam("--varsmallradius");
518  if (radiusOpt->count()==0) missingParam("--radius");
519  //if (kOpt->count()==0) missingParam("--k");
520  //if (phiOpt->count()==0) missingParam("--phi");
521  AccFlower2D<Z2i::Space> flower(Z2i::Point(0,0), radius, varsmallradius,k,phi);
522  Z2i::Domain domain(flower.getLowerBound(), flower.getUpperBound());
523  Z2i::DigitalSet aSet(domain);
524 
526  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
527 
528  if (signatureOpt->count()>0)
529  Exporter<Z2i::DigitalSet,Image>::exportSignature(flower,aSet,domain);
530 
531  return 0;
532  }
533  else
534  //if (id ==6)
535  {
536  if (axis1Opt->count()==0) missingParam("--axis1");
537  if (axis2Opt->count()==0) missingParam("--axis2");
538  //if (phiOpt->count()==0) missingParam("--phi");
539  Ellipse2D<Z2i::Space> ell(Z2i::Point(0,0), axis1, axis2,phi);
540  Z2i::Domain domain(ell.getLowerBound(), ell.getUpperBound());
541  Z2i::DigitalSet aSet(domain);
542 
544  Exporter<Z2i::DigitalSet,Image>::save(aSet,outputName,outputFormat);
545 
546  if (signatureOpt->count()>0)
547  Exporter<Z2i::DigitalSet,Image>::exportSignature(ell,aSet,domain);
548 
549  return 0;
550  }
551 }
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
int main(int argc, char **argv)
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()