38 #include <boost/program_options/options_description.hpp>
39 #include <boost/program_options/parsers.hpp>
40 #include <boost/program_options/variables_map.hpp>
42 #include "DGtal/base/Common.h"
43 #include "DGtal/kernel/domains/HyperRectDomain.h"
45 #include "DGtal/shapes/ShapeFactory.h"
46 #include "DGtal/shapes/Shapes.h"
47 #include "DGtal/helpers/StdDefs.h"
50 #include "DGtal/io/colormaps/GrayscaleColorMap.h"
51 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
52 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
53 #include "DGtal/images/ImageContainerBySTLVector.h"
54 #include "DGtal/io/boards/Board2D.h"
56 #include "DGtal/shapes/GaussDigitizer.h"
57 #include "DGtal/geometry/curves/GridCurve.h"
58 #include "DGtal/geometry/curves/estimation/TrueLocalEstimatorOnPoints.h"
59 #include "DGtal/geometry/curves/estimation/TrueGlobalEstimatorOnPoints.h"
60 #include "DGtal/geometry/curves/estimation/ParametricShapeCurvatureFunctor.h"
61 #include "DGtal/geometry/curves/estimation/ParametricShapeTangentFunctor.h"
62 #include "DGtal/geometry/curves/estimation/ParametricShapeArcLengthFunctor.h"
64 #include "DGtal/topology/helpers/Surfaces.h"
67 using namespace DGtal;
149 std::vector<std::string> shapes2D;
150 std::vector<std::string> shapesDesc;
151 std::vector<std::string> shapesParam1;
152 std::vector<std::string> shapesParam2;
153 std::vector<std::string> shapesParam3;
154 std::vector<std::string> shapesParam4;
163 shapes2D.push_back(
"ball");
164 shapesDesc.push_back(
"Ball for the Euclidean metric.");
165 shapesParam1.push_back(
"--radius [-R]");
166 shapesParam2.push_back(
"");
167 shapesParam3.push_back(
"");
168 shapesParam4.push_back(
"");
170 shapes2D.push_back(
"square");
171 shapesDesc.push_back(
"square (no signature).");
172 shapesParam1.push_back(
"--width [-w]");
173 shapesParam2.push_back(
"");
174 shapesParam3.push_back(
"");
175 shapesParam4.push_back(
"");
177 shapes2D.push_back(
"lpball");
178 shapesDesc.push_back(
"Ball for the l_power metric (no signature).");
179 shapesParam1.push_back(
"--radius [-R],");
180 shapesParam2.push_back(
"--power [-p]");
181 shapesParam3.push_back(
"");
182 shapesParam4.push_back(
"");
184 shapes2D.push_back(
"flower");
185 shapesDesc.push_back(
"Flower with k petals with radius ranging from R+/-v.");
186 shapesParam1.push_back(
"--radius [-R],");
187 shapesParam2.push_back(
"--varsmallradius [-v],");
188 shapesParam3.push_back(
"--k [-k],");
189 shapesParam4.push_back(
"--phi");
191 shapes2D.push_back(
"ngon");
192 shapesDesc.push_back(
"Regular k-gon.");
193 shapesParam1.push_back(
"--radius [-R],");
194 shapesParam2.push_back(
"--k [-k],");
195 shapesParam3.push_back(
"--phi");
196 shapesParam4.push_back(
"");
198 shapes2D.push_back(
"accflower");
199 shapesDesc.push_back(
"Accelerated Flower with k petals.");
200 shapesParam1.push_back(
"--radius [-R],");
201 shapesParam2.push_back(
"--varsmallradius [-v],");
202 shapesParam3.push_back(
"--k [-k],");
203 shapesParam4.push_back(
"--phi");
205 shapes2D.push_back(
"ellipse");
206 shapesDesc.push_back(
"Ellipse.");
207 shapesParam1.push_back(
"--axis1 [-A],");
208 shapesParam2.push_back(
"--axis2 [-a],");
209 shapesParam3.push_back(
"--phi");
210 shapesParam4.push_back(
"");
222 for(
unsigned int i=0; i<shapes2D.size(); ++i)
224 <<shapesDesc[i]<<std::endl
225 <<
"\t\tRequired parameter(s): "
226 << shapesParam1[i]<<
" "
227 << shapesParam2[i]<<
" "
228 << shapesParam3[i]<<
" "
229 << shapesParam4[i]<<std::endl;
242 unsigned int checkAndReturnIndex(
const std::string &shapeName)
246 while ((pos < shapes2D.size()) && (shapes2D[pos] != shapeName))
249 if (pos == shapes2D.size())
251 trace.
error() <<
"The specified shape has not found.";
271 template <
typename Shape,
typename Range,
typename Po
int,
typename Quantity>
273 estimateGeometry(Shape& s,
276 std::vector<Point>& points,
277 std::vector<Point>& tangents,
278 std::vector<Quantity>& curvatures) {
280 typedef typename Range::ConstIterator ConstIterator;
281 for (ConstIterator i = r.begin(); i != r.end(); ++i) {
287 typedef typename Range::ConstCirculator ConstCirculator;
291 trueTangentEstimator;
292 trueTangentEstimator.
attach(&s);
293 trueTangentEstimator.
init( h, r.c(), r.c());
294 trueTangentEstimator.
eval(r.c(), r.c(), std::back_inserter(tangents) );
298 trueCurvatureEstimator;
299 trueCurvatureEstimator.
attach(&s);
300 trueCurvatureEstimator.
init( h, r.c(), r.c());
301 trueCurvatureEstimator.
eval(r.c(), r.c(), std::back_inserter(curvatures) );
305 template <
typename Space,
typename Shape>
310 const std::string & outputFormat,
312 const std::string & outputFileName )
315 typedef typename Space::Point
Point;
316 typedef typename Space::Vector
Vector;
317 typedef typename Space::RealPoint
RealPoint;
318 typedef typename Space::Integer
Integer;
323 typedef typename Range::ConstIterator ConstIteratorOnPoints;
329 Vector vlow(-1,-1); Vector vup(1,1);
330 dig.
init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h );
337 std::cerr <<
"[generateContour]"
338 <<
" error in creating KSpace." << std::endl;
346 std::vector<Point> points;
354 if ( outputFormat ==
"pts" )
357 for ( ConstIteratorOnPoints it = r.begin(), it_end = r.end();
361 std::cout << p[ 0 ] <<
" " << p[ 1 ] << std::endl;
364 else if ( outputFormat ==
"fc" )
366 ConstIteratorOnPoints it = r.
begin();
368 std::cout << p[ 0 ] <<
" " << p[ 1 ] <<
" ";
369 for ( ConstIteratorOnPoints it_end = r.end(); it != it_end; ++it )
373 if ( v[0 ]== 1 ) std::cout <<
'0';
374 if ( v[ 1 ] == 1 ) std::cout <<
'1';
375 if ( v[ 0 ] == -1 ) std::cout <<
'2';
376 if ( v[ 1 ] == -1 ) std::cout <<
'3';
380 Point p2= *(r.begin());
382 if ( v.norm1() == 1 )
384 if ( v[ 0 ] == 1 ) std::cout <<
'0';
385 if ( v[ 1 ] == 1 ) std::cout <<
'1';
386 if ( v[ 0 ] == -1 ) std::cout <<
'2';
387 if ( v[ 1 ] == -1 ) std::cout <<
'3';
389 std::cout << std::endl;
396 s << outputFileName <<
".geom";
397 std::ofstream outstream(s.str().c_str());
398 if (!outstream.is_open())
return false;
400 outstream <<
"# " << outputFileName << std::endl;
401 outstream <<
"# Pointel (x,y), Midpoint of the following linel (x',y')" << std::endl;
402 outstream <<
"# id x y tangentx tangenty curvaturexy"
403 <<
" x' y' tangentx' tangenty' curvaturex'y'" << std::endl;
405 std::vector<RealPoint> truePoints, truePoints2;
406 std::vector<RealPoint> trueTangents, trueTangents2;
407 std::vector<double> trueCurvatures, trueCurvatures2;
409 estimateGeometry<Shape, Range, RealPoint, double>
410 (aShape, h, r, truePoints, trueTangents, trueCurvatures);
412 estimateGeometry<Shape, MidPointsRange, RealPoint, double>
413 (aShape, h, gridcurve.
getMidPointsRange(), truePoints2, trueTangents2, trueCurvatures2);
416 unsigned int n = (
unsigned int)r.size();
417 for (
unsigned int i = 0; i < n; ++i ) {
418 outstream << std::setprecision( 15 ) << i
419 <<
" " << truePoints[ i ][ 0 ]
420 <<
" " << truePoints[ i ][ 1 ]
421 <<
" " << trueTangents[ i ][ 0 ]
422 <<
" " << trueTangents[ i ][ 1 ]
423 <<
" " << trueCurvatures[ i ]
424 <<
" " << truePoints2[ i ][ 0 ]
425 <<
" " << truePoints2[ i ][ 1 ]
426 <<
" " << trueTangents2[ i ][ 0 ]
427 <<
" " << trueTangents2[ i ][ 1 ]
428 <<
" " << trueCurvatures2[ i ]
441 std::cerr <<
"[generateContour]"
442 <<
" error in finding a bel." << std::endl;
453 void missingParam(std::string param)
455 trace.
error() <<
" Parameter: "<<param<<
" is required..";
461 namespace po = boost::program_options;
463 int main(
int argc,
char** argv )
466 po::options_description general_opt(
"Allowed options are");
467 general_opt.add_options()
468 (
"help,h",
"display this message")
469 (
"list,l",
"List all available shapes")
470 (
"shape,s", po::value<std::string>(),
"Shape name")
471 (
"radius,R", po::value<double>(),
"Radius of the shape" )
472 (
"axis1,A", po::value<double>(),
"Half big axis of the shape (ellipse)" )
473 (
"axis2,a", po::value<double>(),
"Half small axis of the shape (ellipse)" )
474 (
"smallradius,r", po::value<double>()->default_value(5),
"Small radius of the shape" )
475 (
"varsmallradius,v", po::value<double>()->default_value(5),
"Variable small radius of the shape" )
476 (
"k,k", po::value<unsigned int>()->default_value(3),
"Number of branches or corners the shape" )
477 (
"phi", po::value<double>()->default_value(0.0),
"Phase of the shape (in radian)" )
478 (
"width,w", po::value<double>()->default_value(10.0),
"Width of the shape" )
479 (
"power,p", po::value<double>()->default_value(2.0),
"Power of the metric (double)" )
480 (
"center_x,x", po::value<double>()->default_value(0.0),
"x-coordinate of the shape center (double)" )
481 (
"center_y,y", po::value<double>()->default_value(0.0),
"y-coordinate of the shape center (double)" )
482 (
"gridstep,g", po::value<double>()->default_value(1.0),
"Gridstep for the digitization" )
483 (
"format,f", po::value<std::string>()->default_value(
"pts"),
"Output format:\n\t List of pointel coordinates {pts}\n\t Freman chaincode Vector {fc}" )
484 (
"outputGeometry,o", po::value<std::string>(),
"Base name of the file containing the shape geometry (points, tangents, curvature)" );
487 po::variables_map vm;
489 po::store(po::parse_command_line(argc, argv, general_opt), vm);
490 }
catch(
const std::exception& ex){
492 trace.
info()<<
"Error checking program options: "<< ex.what()<< std::endl;
496 if(!parseOK || vm.count(
"help")||argc<=1)
498 trace.
info()<<
"Generate contours of 2d digital shapes using DGtal library" <<std::endl
499 <<
"Basic usage: "<<std::endl
500 <<
"\tcontourGenerator --shape <shapeName> [requiredParam] [otherOptions]"<<std::endl
501 << general_opt <<
"\n";
508 if (vm.count(
"list"))
515 if (!(vm.count(
"shape"))) missingParam(
"--shape");
516 std::string shapeName = vm[
"shape"].as<std::string>();
518 bool withGeom =
true;
519 std::string outputFileName;
520 if (!(vm.count(
"outputGeometry"))) withGeom =
false;
521 else outputFileName = vm[
"outputGeometry"].as<std::string>();
523 if (!(vm.count(
"format"))) missingParam(
"--format");
524 std::string outputFormat = vm[
"format"].as<std::string>();
527 unsigned int id = checkAndReturnIndex(shapeName);
531 typedef Space::RealPoint RealPoint;
533 RealPoint center( vm[
"center_x"].as<double>(),
534 vm[
"center_y"].as<double>() );
535 double h = vm[
"gridstep"].as<
double>();
538 if (!(vm.count(
"radius"))) missingParam(
"--radius");
539 double radius = vm[
"radius"].as<
double>();
541 generateContour<Space>( ball, h, outputFormat, withGeom, outputFileName );
545 if (!(vm.count(
"width"))) missingParam(
"--width");
546 double width = vm[
"width"].as<
double>();
553 if (!(vm.count(
"power"))) missingParam(
"--power");
554 if (!(vm.count(
"radius"))) missingParam(
"--radius");
555 double radius = vm[
"radius"].as<
double>();
556 double power = vm[
"power"].as<
double>();
563 if (!(vm.count(
"varsmallradius"))) missingParam(
"--varsmallradius");
564 if (!(vm.count(
"radius"))) missingParam(
"--radius");
565 if (!(vm.count(
"k"))) missingParam(
"--k");
566 if (!(vm.count(
"phi"))) missingParam(
"--phi");
567 double radius = vm[
"radius"].as<
double>();
568 double varsmallradius = vm[
"varsmallradius"].as<
double>();
569 unsigned int k = vm[
"k"].as<
unsigned int>();
570 double phi = vm[
"phi"].as<
double>();
572 generateContour<Space>( flower, h, outputFormat, withGeom, outputFileName );
576 if (!(vm.count(
"radius"))) missingParam(
"--radius");
577 if (!(vm.count(
"k"))) missingParam(
"--k");
578 if (!(vm.count(
"phi"))) missingParam(
"--phi");
579 double radius = vm[
"radius"].as<
double>();
580 unsigned int k = vm[
"k"].as<
unsigned int>();
581 double phi = vm[
"phi"].as<
double>();
583 generateContour<Space>( object, h, outputFormat, withGeom, outputFileName );
587 if (!(vm.count(
"varsmallradius"))) missingParam(
"--varsmallradius");
588 if (!(vm.count(
"radius"))) missingParam(
"--radius");
589 if (!(vm.count(
"k"))) missingParam(
"--k");
590 if (!(vm.count(
"phi"))) missingParam(
"--phi");
591 double radius = vm[
"radius"].as<
double>();
592 double varsmallradius = vm[
"varsmallradius"].as<
double>();
593 unsigned int k = vm[
"k"].as<
unsigned int>();
594 double phi = vm[
"phi"].as<
double>();
596 generateContour<Space>( accflower, h, outputFormat, withGeom, outputFileName );
600 if (!(vm.count(
"axis1"))) missingParam(
"--axis1");
601 if (!(vm.count(
"axis2"))) missingParam(
"--axis2");
602 if (!(vm.count(
"phi"))) missingParam(
"--phi");
603 double a1 = vm[
"axis1"].as<
double>();
604 double a2 = vm[
"axis2"].as<
double>();
605 double phi = vm[
"phi"].as<
double>();
607 generateContour<Space>( ellipse, h, outputFormat, withGeom, outputFileName );
PointsRange getPointsRange() const
MidPointsRange getMidPointsRange() const
const Point & getUpperBound() const
SpaceND< 2, Integer > Space
Quantity eval(const ConstIterator &it) const
void attach(ParametricShape *aShapePtr)
T power(const T &aVal, const unsigned int exponent)
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
void attach(const EuclideanShape &shape)
bool initFromVector(const std::vector< Point > &aVectorOfPoints)
void init(const RealPoint &xLow, const RealPoint &xUp, typename RealVector::Component gridStep)
void init(const double h, const ConstIterator &itb, const ConstIterator &ite)
bool init(const Point &lower, const Point &upper, bool isClosed)
ConstIterator begin() const
Trace trace(traceWriterTerm)
const Point & getLowerBound() const
static void track2DBoundaryPoints(std::vector< Point > &aVectorOfPoints, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
typename Self::Point Point
typename Self::Domain Domain