40 #include "DGtal/base/Common.h"
41 #include "DGtal/kernel/domains/HyperRectDomain.h"
43 #include "DGtal/shapes/ShapeFactory.h"
44 #include "DGtal/shapes/Shapes.h"
45 #include "DGtal/helpers/StdDefs.h"
48 #include "DGtal/io/colormaps/GrayscaleColorMap.h"
49 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
50 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
51 #include "DGtal/images/ImageContainerBySTLVector.h"
52 #include "DGtal/io/boards/Board2D.h"
54 #include "DGtal/shapes/GaussDigitizer.h"
55 #include "DGtal/geometry/curves/GridCurve.h"
56 #include "DGtal/geometry/curves/estimation/TrueLocalEstimatorOnPoints.h"
57 #include "DGtal/geometry/curves/estimation/TrueGlobalEstimatorOnPoints.h"
58 #include "DGtal/geometry/curves/estimation/ParametricShapeCurvatureFunctor.h"
59 #include "DGtal/geometry/curves/estimation/ParametricShapeTangentFunctor.h"
60 #include "DGtal/geometry/curves/estimation/ParametricShapeArcLengthFunctor.h"
62 #include "DGtal/topology/helpers/Surfaces.h"
65 using namespace DGtal;
146 std::vector<std::string> shapes2D;
147 std::vector<std::string> shapesDesc;
148 std::vector<std::string> shapesParam1;
149 std::vector<std::string> shapesParam2;
150 std::vector<std::string> shapesParam3;
151 std::vector<std::string> shapesParam4;
160 shapes2D.push_back(
"ball");
161 shapesDesc.push_back(
"Ball for the Euclidean metric.");
162 shapesParam1.push_back(
"--radius [-R]");
163 shapesParam2.push_back(
"");
164 shapesParam3.push_back(
"");
165 shapesParam4.push_back(
"");
167 shapes2D.push_back(
"square");
168 shapesDesc.push_back(
"square (no signature).");
169 shapesParam1.push_back(
"--width [-w]");
170 shapesParam2.push_back(
"");
171 shapesParam3.push_back(
"");
172 shapesParam4.push_back(
"");
174 shapes2D.push_back(
"lpball");
175 shapesDesc.push_back(
"Ball for the l_power metric (no signature).");
176 shapesParam1.push_back(
"--radius [-R],");
177 shapesParam2.push_back(
"--power [-p]");
178 shapesParam3.push_back(
"");
179 shapesParam4.push_back(
"");
181 shapes2D.push_back(
"flower");
182 shapesDesc.push_back(
"Flower with k petals with radius ranging from R+/-v.");
183 shapesParam1.push_back(
"--radius [-R],");
184 shapesParam2.push_back(
"--varsmallradius [-v],");
185 shapesParam3.push_back(
"--k [-k],");
186 shapesParam4.push_back(
"--phi");
188 shapes2D.push_back(
"ngon");
189 shapesDesc.push_back(
"Regular k-gon.");
190 shapesParam1.push_back(
"--radius [-R],");
191 shapesParam2.push_back(
"--k [-k],");
192 shapesParam3.push_back(
"--phi");
193 shapesParam4.push_back(
"");
195 shapes2D.push_back(
"accflower");
196 shapesDesc.push_back(
"Accelerated Flower with k petals.");
197 shapesParam1.push_back(
"--radius [-R],");
198 shapesParam2.push_back(
"--varsmallradius [-v],");
199 shapesParam3.push_back(
"--k [-k],");
200 shapesParam4.push_back(
"--phi");
202 shapes2D.push_back(
"ellipse");
203 shapesDesc.push_back(
"Ellipse.");
204 shapesParam1.push_back(
"--axis1 [-A],");
205 shapesParam2.push_back(
"--axis2 [-a],");
206 shapesParam3.push_back(
"--phi");
207 shapesParam4.push_back(
"");
217 for(
unsigned int i=0; i<shapes2D.size(); ++i)
219 << shapesDesc[i]<<std::endl
220 <<
"\t\tRequired parameter(s): "
221 << shapesParam1[i]<<
" "
222 << shapesParam2[i]<<
" "
223 << shapesParam3[i]<<
" "
224 << shapesParam4[i]<<std::endl;
236 unsigned int checkAndReturnIndex(
const std::string &shapeName)
240 while ((pos < shapes2D.size()) && (shapes2D[pos] != shapeName))
243 if (pos == shapes2D.size())
245 trace.
error() <<
"The specified shape has not found.";
265 template <
typename Shape,
typename Range,
typename Po
int,
typename Quantity>
267 estimateGeometry(Shape& s,
270 std::vector<Point>& points,
271 std::vector<Point>& tangents,
272 std::vector<Quantity>& curvatures) {
274 typedef typename Range::ConstIterator ConstIterator;
275 for (ConstIterator i = r.begin(); i != r.end(); ++i)
282 typedef typename Range::ConstCirculator ConstCirculator;
286 trueTangentEstimator;
287 trueTangentEstimator.
attach( s );
288 trueTangentEstimator.
eval( r.c(), r.c(), std::back_inserter(tangents), h );
292 trueCurvatureEstimator;
293 trueCurvatureEstimator.
attach( s );
294 trueCurvatureEstimator.
eval( r.c(), r.c(), std::back_inserter(curvatures), h );
297 template <
typename Space,
typename Shape>
302 const std::string & outputFormat,
304 const std::string & outputFileName )
307 typedef typename Space::Point
Point;
308 typedef typename Space::Vector
Vector;
309 typedef typename Space::RealPoint
RealPoint;
310 typedef typename Space::Integer
Integer;
315 typedef typename Range::ConstIterator ConstIteratorOnPoints;
322 dig.
init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h );
329 std::cerr <<
"[generateContour]"
330 <<
" error in creating KSpace." << std::endl;
339 std::vector<Point> points;
347 if ( outputFormat ==
"pts" )
349 for ( ConstIteratorOnPoints it = r.begin(), it_end = r.end();
353 std::cout << p[ 0 ] <<
" " << p[ 1 ] << std::endl;
356 else if ( outputFormat ==
"fc" )
358 ConstIteratorOnPoints it = r.
begin();
360 std::cout << p[ 0 ] <<
" " << p[ 1 ] <<
" ";
361 for ( ConstIteratorOnPoints it_end = r.end(); it != it_end; ++it )
365 if ( v[0 ]== 1 ) std::cout <<
'0';
366 if ( v[ 1 ] == 1 ) std::cout <<
'1';
367 if ( v[ 0 ] == -1 ) std::cout <<
'2';
368 if ( v[ 1 ] == -1 ) std::cout <<
'3';
372 Point p2= *(r.begin());
374 if ( v.norm1() == 1 )
376 if ( v[ 0 ] == 1 ) std::cout <<
'0';
377 if ( v[ 1 ] == 1 ) std::cout <<
'1';
378 if ( v[ 0 ] == -1 ) std::cout <<
'2';
379 if ( v[ 1 ] == -1 ) std::cout <<
'3';
381 std::cout << std::endl;
388 s << outputFileName <<
".geom";
389 std::ofstream outstream(s.str().c_str());
390 if (!outstream.is_open())
return false;
393 outstream <<
"# " << outputFileName << std::endl;
394 outstream <<
"# Pointel (x,y), Midpoint of the following linel (x',y')" << std::endl;
395 outstream <<
"# id x y tangentx tangenty curvaturexy"
396 <<
" x' y' tangentx' tangenty' curvaturex'y'" << std::endl;
398 std::vector<RealPoint> truePoints, truePoints2;
399 std::vector<RealPoint> trueTangents, trueTangents2;
400 std::vector<double> trueCurvatures, trueCurvatures2;
402 estimateGeometry<Shape, Range, RealPoint, double>
403 (aShape, h, r, truePoints, trueTangents, trueCurvatures);
405 estimateGeometry<Shape, MidPointsRange, RealPoint, double>
406 (aShape, h, gridcurve.
getMidPointsRange(), truePoints2, trueTangents2, trueCurvatures2);
409 unsigned int n = (
unsigned int)r.size();
410 for (
unsigned int i = 0; i < n; ++i )
412 outstream << std::setprecision( 15 ) << i
413 <<
" " << truePoints[ i ][ 0 ]
414 <<
" " << truePoints[ i ][ 1 ]
415 <<
" " << trueTangents[ i ][ 0 ]
416 <<
" " << trueTangents[ i ][ 1 ]
417 <<
" " << trueCurvatures[ i ]
418 <<
" " << truePoints2[ i ][ 0 ]
419 <<
" " << truePoints2[ i ][ 1 ]
420 <<
" " << trueTangents2[ i ][ 0 ]
421 <<
" " << trueTangents2[ i ][ 1 ]
422 <<
" " << trueCurvatures2[ i ]
434 std::cerr <<
"[generateContour]"
435 <<
" error in finding a bel." << std::endl;
446 void missingParam(std::string param)
448 trace.
error() <<
" Parameter: "<<param<<
" is required..";
455 int main(
int argc,
char** argv )
459 std::string shapeName;
460 std::string outputFileName;
461 std::string outputFormat {
"pts"};
464 double smallradius {5};
465 double varsmallradius {5};
466 double cx {0.0}, cy {0.0};
473 app.description(
"Generates multigrid contours of 2d digital shapes using DGtal library.\n Typical use example:\n \t contourGenerator --shape <shapeName> [requiredParam] [otherOptions]\n");
474 auto listOpt = app.add_flag(
"--list,-l",
"List all available shapes");
475 auto shapeNameOpt = app.add_option(
"--shape,-s", shapeName,
"Shape name");
476 auto radiusOpt = app.add_option(
"--radius,-R", radius,
"Radius of the shape" );
477 auto axis1Opt = app.add_option(
"--axis1,-A", axis1,
"Half big axis of the shape (ellipse)" );
478 auto axis2Opt = app.add_option(
"--axis2,-a", axis2,
"Half small axis of the shape (ellipse)" );
479 auto smallradiusOpt = app.add_option(
"--smallradius,-r", smallradius,
"Small radius of the shape (default 5)",
true);
480 auto varsmallradiusOpt = app.add_option(
"--varsmallradius,-v", varsmallradius,
"Variable small radius of the shape (default 5)",
true );
481 auto kOpt = app.add_option(
"-k", k,
"Number of branches or corners the shape (default 3)",
true );
482 auto phiOpt = app.add_option(
"--phi", phi,
"Phase of the shape (in radian, default 0.0)",
true );
483 auto widthOpt = app.add_option(
"--width,-w", width,
"Width of the shape (default 10.0)",
true );
484 auto powerOpt = app.add_option(
"--power,-p", power,
"Power of the metric (default 2.0)",
true );
485 app.add_option(
"--center_x,-x", cx,
"x-coordinate of the shape center (default 0.0)",
true );
486 app.add_option(
"--center_y,-y", cy,
"y-coordinate of the shape center (default 0.0)",
true );
487 app.add_option(
"--gridstep,-g", h,
"Gridstep for the digitization (default 1.0)",
true );
488 auto outputFormatOpt = app.add_option(
"--format,-f", outputFormat,
"Output format:\n\t List of pointel coordinates {pts}\n\t Freeman chaincode Vector {fc} (default pts)",
true );
489 auto outputFileNameOpt = app.add_option(
"--outputGeometry,-o", outputFileName,
"Base name of the file containing the shape geometry (points, tangents, curvature)" );
491 app.get_formatter()->column_width(40);
492 CLI11_PARSE(app, argc, argv);
498 if ( listOpt->count() > 0 )
504 if(shapeNameOpt->count()==0) missingParam(
"--shape");
505 bool withGeom =
true;
506 if (outputFileNameOpt->count()==0) withGeom =
false;
509 unsigned int id = checkAndReturnIndex(shapeName);
519 if (radiusOpt->count()==0) missingParam(
"--radius");
521 generateContour<Space>( ball, h, outputFormat, withGeom, outputFileName );
533 if (radiusOpt->count()==0) missingParam(
"--radius");
541 if (radiusOpt->count()==0) missingParam(
"--radius");
545 generateContour<Space>( flower, h, outputFormat, withGeom, outputFileName );
549 if (radiusOpt->count()==0) missingParam(
"--radius");
553 generateContour<Space>(
object, h, outputFormat, withGeom, outputFileName );
558 if (radiusOpt->count()==0) missingParam(
"--radius");
562 generateContour<Space>( accflower, h, outputFormat, withGeom, outputFileName );
566 if (axis1Opt->count()==0) missingParam(
"--axis1");
567 if (axis2Opt->count()==0) missingParam(
"--axis2");
570 generateContour<Space>( ellipse, h, outputFormat, withGeom, outputFileName );
int main(int argc, char **argv)
ConstIterator begin() const
void attach(const EuclideanShape &shape)
const Point & getUpperBound() const
void init(const RealPoint &xLow, const RealPoint &xUp, typename RealVector::Component gridStep)
const Point & getLowerBound() const
MidPointsRange getMidPointsRange() const
PointsRange getPointsRange() const
bool initFromVector(const std::vector< Point > &aVectorOfPoints)
typename Self::Domain Domain
typename Self::Point Point
bool init(const Point &lower, const Point &upper, bool isClosed)
static void track2DBoundaryPoints(std::vector< Point > &aVectorOfPoints, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
void attach(ParametricShape *aShapePtr)
Quantity eval(const ConstIterator &it) const
SpaceND< 2, Integer > Space
T power(const T &aVal, const unsigned int exponent)
Trace trace(traceWriterTerm)