33 #include <boost/program_options/options_description.hpp>
34 #include <boost/program_options/parsers.hpp>
35 #include <boost/program_options/variables_map.hpp>
41 #include "DGtal/base/Common.h"
42 #include "DGtal/helpers/StdDefs.h"
44 #include "DGtal/shapes/ShapeFactory.h"
45 #include "DGtal/shapes/Shapes.h"
46 #include "DGtal/topology/helpers/Surfaces.h"
49 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
50 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
51 #include "DGtal/images/ImageContainerBySTLVector.h"
52 #include "DGtal/images/ImageSelector.h"
53 #include "DGtal/io/readers/PointListReader.h"
54 #include "DGtal/io/readers/TableReader.h"
55 #include "DGtal/io/Color.h"
57 #include "DGtal/io/readers/GenericReader.h"
61 #include "DGtal/geometry/curves/FreemanChain.h"
64 #include "DGtal/geometry/curves/ArithmeticalDSSComputer.h"
65 #include "DGtal/geometry/curves/GreedySegmentation.h"
66 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
67 #include "DGtal/geometry/curves/FP.h"
68 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
69 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
70 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
72 #include "DGtal/io/boards/Board2D.h"
73 #include "DGtal/io/boards/CDrawableWithBoard2D.h"
75 using namespace DGtal;
174 namespace po = boost::program_options;
177 int main(
int argc,
char** argv )
181 po::options_description general_opt(
"Allowed options are: ");
182 general_opt.add_options()
183 (
"help,h",
"display this message")
184 (
"input,i", po::value<std::string>(),
"input FreemanChain file name")
185 (
"SDP", po::value<std::string>(),
"Import a contour as a Sequence of Discrete Points (SDP format)")
186 (
"SFP", po::value<std::string>(),
"Import a contour as a Sequence of Floating Points (SFP format)")
187 (
"drawContourPoint", po::value<double>(),
"<size> display contour points as disk of radius <size>")
188 (
"fillContour",
"fill the contours with default color (gray)")
189 (
"lineWidth", po::value<double>()->default_value(1.0),
"Define the linewidth of the contour (SDP format)")
190 (
"drawPointOfIndex", po::value<int>(),
"<index> Draw the contour point of index <index> (default 0) ")
191 (
"pointSize", po::value<double>()->default_value(2.0),
"<size> Set the display point size of the point displayed by drawPointofIndex option (default 2.0) ")
192 (
"noXFIGHeader",
" to exclude xfig header in the resulting output stream (no effect with option -outputFile).")
193 (
"withProcessing", po::value<std::string>(),
"Processing (used only when the input is a Freeman chain (--input)):\n\t DSS segmentation {DSS}\n\t Maximal segments {MS}\n\t Faithful Polygon {FP}\n\t Minimum Length Polygon {MLP}")
194 (
"outputFile,o", po::value<std::string>(),
" <filename> save output file automatically according the file format extension.")
195 (
"displayVectorField,v", po::value<std::string>(),
"Add the display of a vector field represented by two floating coordinates. Each vector is displayed starting from the corresponding contour point coordinates.")
196 (
"scaleVectorField,v", po::value<double>()->default_value(1.0),
"set the scale of the vector field (default 1) (used with --displayVectorField).")
197 (
"vectorFieldIndex", po::value<std::vector <unsigned int> >()->multitoken(),
"specify the vector field index (by default 0,1) (used with --displayVectorField)." )
198 (
"vectorFromAngle", po::value<unsigned int>(),
"specify that the vectors are defined from an angle value represented at the given index (by default 0) (used with --displayVectorField)." )
199 (
"rotateVectorField",
"apply a CCW rotation of 90° (used with --displayVectorField). ")
200 (
"outputStreamEPS",
" specify eps for output stream format.")
201 (
"outputStreamSVG",
" specify svg for output stream format.")
202 (
"outputStreamFIG",
" specify fig for output stream format.")
203 (
"invertYaxis",
" invertYaxis invert the Y axis for display contours (used only with --SDP)")
205 (
"backgroundImage", po::value<std::string>(),
"backgroundImage <filename> : display image as background ")
206 (
"alphaBG", po::value<double>(),
"alphaBG <value> 0-1.0 to display the background image in transparency (default 1.0), (transparency works only if cairo is available)")
208 (
"scale", po::value<double>(),
"scale <value> 1: normal; >1 : larger ; <1 lower resolutions )");
213 po::variables_map vm;
215 po::store(po::parse_command_line(argc, argv, general_opt), vm);
216 }
catch(
const std::exception& ex){
218 trace.
info()<<
"Error checking program options: "<< ex.what()<< std::endl;
222 if(!parseOK||vm.count(
"help")||argc<=1 || (!(vm.count(
"input")) && !(vm.count(
"SDP")) && !(vm.count(
"SFP"))&&
223 !(vm.count(
"backgroundImage")) ) )
225 trace.
info()<<
"Display discrete contours. " <<std::endl <<
"Basic usage: "<<std::endl
226 <<
"\t displayContours [options] --input <fileName> "<<std::endl
227 << general_opt <<
"\n";
233 double lineWidth= vm[
"lineWidth"].as<
double>();
234 bool filled = vm.count(
"fillContour");
236 if(vm.count(
"scale")){
237 scale = vm[
"scale"].as<
double>();
248 if(vm.count(
"alphaBG")){
249 alpha = vm[
"alphaBG"].as<
double>();
252 if(vm.count(
"backgroundImage")){
253 std::string imageName = vm[
"backgroundImage"].as<std::string>();
258 unsigned int width =
abs(ptSup[0]-ptInf[0]+1);
259 unsigned int height =
abs(ptSup[1]-ptInf[1]+1);
261 aBoard.
drawImage(imageName, 0-0.5,height-0.5, width, height, -1, alpha );
267 if(vm.count(
"input")){
268 std::string fileName = vm[
"input"].as<std::string>();
273 for(
unsigned int i=0; i<vectFc.size(); i++){
274 aBoard << vectFc.at(i) ;
275 if(vm.count(
"drawPointOfIndex")){
276 int index = vm[
"drawPointOfIndex"].as<
int>();
277 double size = vm[
"pointSize"].as<
double>();
280 aBoard.
fillCircle((
double)(vectFc.at(i).getPoint(index)[0]), (
double)(vectFc.at(i).getPoint(index)[1]), size);
283 if(vm.count(
"withProcessing")){
284 std::string processingName = vm[
"withProcessing"].as<std::string>();
286 std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1);
287 copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() );
289 if ( vPts.at(0) == vPts.at(vPts.size()-1) ) {
292 }
else isClosed =
false;
294 if (processingName ==
"DSS") {
300 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
303 std::string className;
304 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
305 it != theDecomposition.end(); ++it )
307 DSS4::Primitive segment(it->primitive());
309 aBoard <<
SetMode( segment.className(),
"BoundingBox" );
310 className = segment.
className() +
"/BoundingBox";
316 }
else if (processingName ==
"MS") {
318 typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
323 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
326 std::string className;
327 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
328 it != theDecomposition.end(); ++it )
330 DSS4::Primitive segment(it->primitive());
332 aBoard <<
SetMode( segment.className(),
"BoundingBox" );
333 className = segment.
className() +
"/BoundingBox";
339 }
else if (processingName ==
"FP") {
342 FP theFP( vPts.begin(),vPts.end() );
348 }
else if (processingName ==
"MLP") {
350 typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP;
351 FP theFP( vPts.begin(),vPts.end() );
353 std::vector<FP::RealPoint> v( theFP.size() );
354 theFP.copyMLP( v.begin() );
357 std::vector<LibBoard::Point> polyline;
358 std::vector<FP::RealPoint>::const_iterator it = v.begin();
359 for ( ;it != v.end();++it) {
370 }
else if (processingName ==
"MDCA") {
374 curve.initFromPointsVector( vPts );
375 typedef Curve::IncidentPointsRange Range;
376 Range r = curve.getIncidentPointsRange();
377 typedef Range::ConstCirculator ConstCirculator;
382 Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() );
383 theSegmentation.
setMode(
"Last");
385 Segmentation::SegmentComputerIterator it = theSegmentation.begin();
386 Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
390 for ( ; it != itEnd; ++it ) {
391 aBoard <<
SetMode(SegmentComputer().className(),
"") << (*it);
392 otherBoard <<
SetMode(SegmentComputer().className(),
"") << (*it);
406 if(vm.count(
"SDP") || vm.count(
"SFP")){
407 bool drawPoints= vm.count(
"drawContourPoint");
408 bool invertYaxis = vm.count(
"invertYaxis");
409 double pointSize=1.0;
411 pointSize = vm[
"drawContourPoint"].as<
double>();
413 std::vector<LibBoard::Point> contourPt;
415 std::string fileName = vm[
"SDP"].as<std::string>();
417 for(
unsigned int j=0; j<contour.size(); j++){
419 (invertYaxis? (
double)(-contour.at(j)[1]+contour.at(0)[1]):(
double)(contour.at(j)[1])));
420 contourPt.push_back(pt);
428 std::string fileName = vm[
"SFP"].as<std::string>();
429 std::vector< PointVector<2,double> > contour =
431 for(
unsigned int j=0; j<contour.size(); j++){
433 (invertYaxis? (
double)(-contour.at(j)[1]+contour.at(0)[1]):(
double)(contour.at(j)[1])));
434 contourPt.push_back(pt);
452 if(vm.count(
"drawPointOfIndex")){
453 int index = vm[
"drawPointOfIndex"].as<
int>();
454 double size = vm[
"pointSize"].as<
double>();
455 aBoard.
fillCircle((
double)(contourPt.at(index).x), (
double)(contourPt.at(index).y), size);
460 if(vm.count(
"displayVectorField"))
462 bool rotate = vm.count(
"rotateVectorField");
463 double sv = vm[
"scaleVectorField"].as<
double>();
464 std::vector<unsigned int> vIndex = {0,1};
465 if(vm.count(
"vectorFieldIndex"))
467 vIndex = vm[
"vectorFieldIndex"].as<std::vector<unsigned int>>();
469 std::string vname = vm[
"displayVectorField"].as<std::string>();
470 std::vector< PointVector<2,double> > vField;
471 if(vm.count(
"vectorFromAngle"))
473 unsigned int aIndex = vm[
"vectorFromAngle"].as<
unsigned int>();
475 for(
unsigned int i = 0; i < vAngles.size(); i++)
477 vField.push_back(
Z2i::RealPoint(cos(vAngles[i]),sin(vAngles[i])));
484 for(
unsigned int i = 0; i< contourPt.size(); i++)
486 vField[i] = vField[i].getNormalized();
487 auto p = contourPt[i];
490 aBoard.
drawArrow(p.x, p.y, p.x+vField[i][0]*sv, p.y+vField[i][1]*sv );
494 aBoard.
drawArrow(p.x, p.y, p.x-vField[i][1]*sv, p.y+vField[i][0]*sv );
505 if(vm.count(
"outputFile")){
506 std::string outputFileName= vm[
"outputFile"].as<std::string>();
507 std::string extension = outputFileName.substr(outputFileName.find_last_of(
".") + 1);
509 if(extension==
"svg"){
510 aBoard.
saveSVG(outputFileName.c_str());
514 if (extension==
"eps"){
517 if (extension==
"pdf"){
520 if (extension==
"png"){
524 else if(extension==
"eps"){
525 aBoard.
saveEPS(outputFileName.c_str());
526 }
else if(extension==
"fig"){
531 if (vm.count(
"outputStreamSVG")){
534 if (vm.count(
"outputStreamFIG")){
537 if (vm.count(
"outputStreamEPS")){
void fillPolyline(const std::vector< Point > &points, int depthValue=-1)
static std::vector< TQuantity > getColumnElementsFromFile(const std::string &aFilename, unsigned int aPosition)
Board & setLineWidth(double width)
void drawPolyline(const std::vector< Point > &points, int depthValue=-1)
void drawImage(std::string filename, double x, double y, double width, double height, int depthValue=-1, double alpha=1.0)
void drawArrow(double x1, double y1, double x2, double y2, bool filled=true, int depthValue=-1)
void saveFIG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0, bool includeFIGHeader=true) const
void saveCairo(const char *filename, CairoType type=CairoPNG, PageSize size=Board::BoundingBox, double margin=10.0) const
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())
static std::vector< TPoint > getPointsFromFile(const std::string &filename, std::vector< unsigned int > aVectPosition=std::vector< unsigned int >())
void setMode(const std::string &aMode)
void fillCircle(double x, double y, double radius, int depthValue=-1)
Board & setLineStyle(Shape::LineStyle style)
Board & setFillColor(const DGtal::Color &color)
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Trace trace(traceWriterTerm)
std::string className() const
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Board & setPenColor(const DGtal::Color &color)
const Domain & domain() const