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(
"");
221 trace.emphase()<<
"2D Shapes:"<<std::endl;
222 for(
unsigned int i=0; i<shapes2D.size(); ++i)
223 trace.info()<<
"\t"<<shapes2D[i]<<
"\t" 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.";
252 trace.info()<<std::endl;
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;
289 typedef ParametricShapeTangentFunctor< Shape > TangentFunctor;
290 TrueLocalEstimatorOnPoints< ConstCirculator, Shape, TangentFunctor >
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) );
296 typedef ParametricShapeCurvatureFunctor< Shape > CurvatureFunctor;
297 TrueLocalEstimatorOnPoints< ConstCirculator, Shape, CurvatureFunctor >
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;
319 typedef HyperRectDomain<Space> Domain;
320 typedef KhalimskySpaceND<Space::dimension,Integer> KSpace;
321 typedef typename KSpace::SCell SCell;
322 typedef typename GridCurve<KSpace>::PointsRange Range;
323 typedef typename Range::ConstIterator ConstIteratorOnPoints;
324 typedef typename GridCurve<KSpace>::MidPointsRange MidPointsRange;
327 GaussDigitizer<Space,Shape> dig;
328 dig.attach( aShape );
329 Vector vlow(-1,-1); Vector vup(1,1);
330 dig.init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h );
331 Domain domain = dig.getDomain();
334 bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
337 std::cerr <<
"[generateContour]" 338 <<
" error in creating KSpace." << std::endl;
343 SurfelAdjacency<KSpace::dimension> SAdj(
true );
344 SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
346 std::vector<Point> points;
347 Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
349 GridCurve<KSpace> gridcurve;
350 gridcurve.initFromVector( points );
352 Range r = gridcurve.getPointsRange();
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 ]
439 catch ( InputException e )
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..";
456 trace.info()<<std::endl;
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);
530 typedef Z2i::Space Space;
531 typedef Space::Point Point;
532 typedef Space::RealPoint RealPoint;
534 RealPoint center( vm[
"center_x"].as<double>(),
535 vm[
"center_y"].as<double>() );
536 double h = vm[
"gridstep"].as<
double>();
539 if (!(vm.count(
"radius"))) missingParam(
"--radius");
540 double radius = vm[
"radius"].as<
double>();
541 Ball2D<Space> ball(Z2i::Point(0,0), radius);
542 generateContour<Space>( ball, h, outputFormat, withGeom, outputFileName );
546 if (!(vm.count(
"width"))) missingParam(
"--width");
547 double width = vm[
"width"].as<
double>();
548 ImplicitHyperCube<Space> object(Z2i::Point(0,0), width/2);
549 trace.error()<<
"Not available.";
550 trace.info()<<std::endl;
554 if (!(vm.count(
"power"))) missingParam(
"--power");
555 if (!(vm.count(
"radius"))) missingParam(
"--radius");
556 double radius = vm[
"radius"].as<
double>();
557 double power = vm[
"power"].as<
double>();
558 ImplicitRoundedHyperCube<Space> ball(Z2i::Point(0,0), radius, power);
559 trace.error()<<
"Not available.";
560 trace.info()<<std::endl;
564 if (!(vm.count(
"varsmallradius"))) missingParam(
"--varsmallradius");
565 if (!(vm.count(
"radius"))) missingParam(
"--radius");
566 if (!(vm.count(
"k"))) missingParam(
"--k");
567 if (!(vm.count(
"phi"))) missingParam(
"--phi");
568 double radius = vm[
"radius"].as<
double>();
569 double varsmallradius = vm[
"varsmallradius"].as<
double>();
570 unsigned int k = vm[
"k"].as<
unsigned int>();
571 double phi = vm[
"phi"].as<
double>();
572 Flower2D<Space> flower( center, radius, varsmallradius, k, phi );
573 generateContour<Space>( flower, h, outputFormat, withGeom, outputFileName );
577 if (!(vm.count(
"radius"))) missingParam(
"--radius");
578 if (!(vm.count(
"k"))) missingParam(
"--k");
579 if (!(vm.count(
"phi"))) missingParam(
"--phi");
580 double radius = vm[
"radius"].as<
double>();
581 unsigned int k = vm[
"k"].as<
unsigned int>();
582 double phi = vm[
"phi"].as<
double>();
583 NGon2D<Space> object( center, radius, k, phi );
584 generateContour<Space>( object, h, outputFormat, withGeom, outputFileName );
588 if (!(vm.count(
"varsmallradius"))) missingParam(
"--varsmallradius");
589 if (!(vm.count(
"radius"))) missingParam(
"--radius");
590 if (!(vm.count(
"k"))) missingParam(
"--k");
591 if (!(vm.count(
"phi"))) missingParam(
"--phi");
592 double radius = vm[
"radius"].as<
double>();
593 double varsmallradius = vm[
"varsmallradius"].as<
double>();
594 unsigned int k = vm[
"k"].as<
unsigned int>();
595 double phi = vm[
"phi"].as<
double>();
596 AccFlower2D<Space> accflower( center, radius, varsmallradius, k, phi );
597 generateContour<Space>( accflower, h, outputFormat, withGeom, outputFileName );
601 if (!(vm.count(
"axis1"))) missingParam(
"--axis1");
602 if (!(vm.count(
"axis2"))) missingParam(
"--axis2");
603 if (!(vm.count(
"phi"))) missingParam(
"--phi");
604 double a1 = vm[
"axis1"].as<
double>();
605 double a2 = vm[
"axis2"].as<
double>();
606 double phi = vm[
"phi"].as<
double>();
607 Ellipse2D<Space> ellipse( center, a1, a2, phi );
608 generateContour<Space>( ellipse, h, outputFormat, withGeom, outputFileName );