36 #include "DGtal/base/Common.h"
37 #include "DGtal/helpers/StdDefs.h"
39 #include "DGtal/shapes/ShapeFactory.h"
40 #include "DGtal/shapes/Shapes.h"
41 #include "DGtal/topology/helpers/Surfaces.h"
44 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
45 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
46 #include "DGtal/images/ImageContainerBySTLVector.h"
47 #include "DGtal/images/ImageSelector.h"
48 #include "DGtal/io/readers/PointListReader.h"
49 #include "DGtal/io/readers/TableReader.h"
50 #include "DGtal/io/Color.h"
52 #include "DGtal/io/readers/GenericReader.h"
55 #include "DGtal/geometry/curves/FreemanChain.h"
58 #include "DGtal/geometry/curves/ArithmeticalDSSComputer.h"
59 #include "DGtal/geometry/curves/GreedySegmentation.h"
60 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
61 #include "DGtal/geometry/curves/FP.h"
62 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
63 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
64 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
66 #include "DGtal/io/boards/Board2D.h"
67 #include "DGtal/io/boards/CDrawableWithBoard2D.h"
71 using namespace DGtal;
152 int main(
int argc,
char** argv )
157 app.description(
"Display discrete contours. \n Basic example: \t displayContours [options] --input <fileName>");
158 std::string inputFileName;
159 std::string outputFileName {
"result.svg"};
160 std::string inputSDFileName;
161 std::string inputSFPFileName;
162 std::string processingName;
163 unsigned int indexPoint;
164 double pointSize {0.0};
165 double scaleVectorField {1.0};
166 bool fillContour {
false};
167 bool rotateVectorField {
false};
168 bool outputStreamEPS {
false};
169 bool outputStreamSVG {
false};
170 bool outputStreamFIG {
false};
171 bool noXFIGHeader {
false};
172 bool invertYaxis {
false};
173 double alphaBG {1.0};
174 double lineWidth {0.0};
176 unsigned int vectorFromAngle {0};
177 std::string displayVectorField =
"";
178 std::vector <unsigned int> vectorFieldIndex = {0,1};
179 std::string backgroundImage;
181 app.add_option(
"-i,--input,1", inputFileName,
"input FreemanChain file name" )
183 ->check(CLI::ExistingFile);
184 app.add_option(
"--outputFile,-o", outputFileName,
"save output file automatically according the file format extension.");
186 CLI::Option* optSDP = app.add_option(
"--SDP",inputSDFileName,
"Import a contour as a Sequence of Discrete Points (SDP format)")
187 ->check(CLI::ExistingFile);
188 app.add_option(
"--SFP",inputSFPFileName,
"mport a contour as a Sequence of Floating Points (SFP format)")
189 ->check(CLI::ExistingFile);
190 app.add_option(
"--drawContourPoint", pointSize,
"<size> display contour points as disk of radius <size>");
191 app.add_flag(
"--fillContour", fillContour,
"fill the contours with default color (gray)");
192 app.add_option(
"--lineWidth", lineWidth,
"Define the linewidth of the contour (SDP format)" );
193 auto indexPointOpt = app.add_option(
"--drawPointOfIndex,-f", indexPoint,
" Draw the contour point of index." );
194 app.add_option(
"--pointSize", pointSize,
"<size> Set the display point size of the point displayed by drawPointofIndex option (default 2.0) " );
195 app.add_option(
"--noXFIGHeader", noXFIGHeader,
"to exclude xfig header in the resulting output stream (no effect with option -outputFile).");
197 app.add_option(
"--withProcessing",processingName,
"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}" )
198 -> check(CLI::IsMember({
"MS",
"FP",
"MLP"}));
200 app.add_option(
"--displayVectorField,-v", displayVectorField,
"Add the display of a vector field represented by two floating coordinates. Each vector is displayed starting from the corresponding contour point coordinates.");
201 app.add_option(
"--scaleVectorField",scaleVectorField,
"set the scale of the vector field (default 1) (used with --displayVectorField).",
true);
202 app.add_option(
"--vectorFieldIndex", vectorFieldIndex ,
"specify the vector field index (by default 0,1) (used with --displayVectorField).",
true)
205 auto optVFAngke = app.add_option(
"--vectorFromAngle", vectorFromAngle,
"specify that the vectors are defined from an angle value represented at the given index (by default 0) (used with --displayVectorField).");
206 app.add_flag(
"--rotateVectorField", rotateVectorField,
"apply a CCW rotation of 90° (used with --displayVectorField). ");
207 app.add_flag(
"--outputStreamEPS",
" specify eps for output stream format.");
208 app.add_flag(
"--outputStreamSVG",
" specify svg for output stream format.");
209 app.add_flag(
"--outputStreamFIG",
" specify fig for output stream format.");
210 app.add_flag(
"--invertYaxis", invertYaxis,
" invertYaxis invert the Y axis for display contours (used only with --SDP)")
212 app.add_option(
"--backgroundImage", backgroundImage,
"backgroundImage <filename> : display image as background ")
213 ->check(CLI::ExistingFile);
214 app.add_option(
"--alphaBG", alphaBG,
"alphaBG <value> 0-1.0 to display the background image in transparency (default 1.0), (transparency works only if cairo is available)",
true);
215 app.add_option(
"--scale", scale,
"scale <value> 1: normal; >1 : larger ; <1 lower resolutions)",
true);
219 app.get_formatter()->column_width(40);
220 CLI11_PARSE(app, argc, argv);
225 trace.
info() << app.get_description() << std::endl;
226 trace.
error() <<
"You need at least add one input file using -i, --SDP, --SFP (see --help for more details)" << std::endl;
233 if(backgroundImage !=
"")
239 unsigned int width =
abs(ptSup[0]-ptInf[0]+1);
240 unsigned int height =
abs(ptSup[1]-ptInf[1]+1);
241 aBoard.
drawImage(backgroundImage, 0-0.5,height-0.5, width, height, -1, alphaBG);
244 if(inputFileName !=
""){
249 for(
unsigned int i=0; i<vectFc.size(); i++){
250 aBoard << vectFc.at(i) ;
251 if( indexPointOpt->count() != 0 ){
253 aBoard.
fillCircle((
double)(vectFc.at(i).getPoint(indexPoint)[0]),
254 (
double)(vectFc.at(i).getPoint(indexPoint)[1]), pointSize);
257 if(processingName !=
""){
258 std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1);
259 copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() );
261 if ( vPts.at(0) == vPts.at(vPts.size()-1) )
269 if (processingName ==
"DSS")
275 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
278 std::string className;
279 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
280 it != theDecomposition.end(); ++it )
282 DSS4::Primitive segment(it->primitive());
284 aBoard <<
SetMode( segment.className(),
"BoundingBox" );
285 className = segment.className() +
"/BoundingBox";
291 }
else if (processingName ==
"MS") {
298 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
301 std::string className;
302 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
303 it != theDecomposition.end(); ++it )
305 DSS4::Primitive segment(it->primitive());
306 aBoard <<
SetMode( segment.className(),
"BoundingBox" );
307 className = segment.className() +
"/BoundingBox";
313 }
else if (processingName ==
"FP")
316 FP theFP( vPts.begin(),vPts.end() );
321 }
else if (processingName ==
"MLP")
324 FP theFP( vPts.begin(),vPts.end() );
326 std::vector<FP::RealPoint> v( theFP.size() );
327 theFP.copyMLP( v.begin() );
330 std::vector<LibBoard::Point> polyline;
331 std::vector<FP::RealPoint>::const_iterator it = v.begin();
332 for ( ;it != v.end();++it)
345 }
else if (processingName ==
"MDCA")
350 curve.initFromPointsVector( vPts );
351 typedef Curve::IncidentPointsRange Range;
352 Range r = curve.getIncidentPointsRange();
353 typedef Range::ConstCirculator ConstCirculator;
358 Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() );
359 theSegmentation.setMode(
"Last");
361 Segmentation::SegmentComputerIterator it = theSegmentation.begin();
362 Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
366 for ( ; it != itEnd; ++it )
368 aBoard <<
SetMode(SegmentComputer().className(),
"") << (*it);
369 otherBoard <<
SetMode(SegmentComputer().className(),
"") << (*it);
379 if( inputSDFileName !=
"" || inputSFPFileName !=
"" )
381 std::vector<LibBoard::Point> contourPt;
382 if( inputSDFileName !=
"" )
385 for(
unsigned int j=0; j<contour.size(); j++)
388 (invertYaxis? (
double)(-contour.at(j)[1]+contour.at(0)[1]):(
double)(contour.at(j)[1])));
389 contourPt.push_back(pt);
397 if( inputSFPFileName !=
"" )
399 std::vector< PointVector<2,double> > contour =
401 for(
unsigned int j=0; j<contour.size(); j++)
404 (invertYaxis? (
double)(-contour.at(j)[1]+contour.at(0)[1]):(
double)(contour.at(j)[1])));
405 contourPt.push_back(pt);
424 if( indexPointOpt->count() != 0 )
426 aBoard.
fillCircle((
double)(contourPt.at(indexPoint).x), (
double)(contourPt.at(indexPoint).y), pointSize);
431 if(displayVectorField !=
"")
433 std::vector< PointVector<2,double> > vField;
434 if(optVFAngke->count() != 0)
438 for(
unsigned int i = 0; i < vAngles.size(); i++)
440 vField.push_back(
Z2i::RealPoint(cos(vAngles[i]),sin(vAngles[i])));
447 for(
unsigned int i = 0; i< contourPt.size(); i++)
449 vField[i] = vField[i].getNormalized();
450 auto p = contourPt[i];
451 if(!rotateVectorField)
453 aBoard.
drawArrow(p.x, p.y, p.x+vField[i][0]*scaleVectorField, p.y+vField[i][1]*scaleVectorField );
457 aBoard.
drawArrow(p.x, p.y, p.x-vField[i][1]*scaleVectorField, p.y+vField[i][0]*scaleVectorField );
466 if( outputFileName !=
"" )
468 std::string extension = outputFileName.substr(outputFileName.find_last_of(
".") + 1);
471 aBoard.
saveSVG(outputFileName.c_str());
475 if (extension==
"eps")
479 else if (extension==
"pdf")
483 else if (extension==
"png")
488 else if(extension==
"eps")
490 aBoard.
saveEPS(outputFileName.c_str());
492 else if(extension==
"fig")
502 else if (outputStreamFIG)
505 }
else if (outputStreamEPS)
int main(int argc, char **argv)
const Domain & domain() const
Board & setLineStyle(Shape::LineStyle style)
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Board & setPenColor(const DGtal::Color &color)
void drawPolyline(const std::vector< Point > &points, int depthValue=-1)
void fillCircle(double x, double y, double radius, int depthValue=-1)
void fillPolyline(const std::vector< Point > &points, int depthValue=-1)
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
Board & setFillColor(const DGtal::Color &color)
Board & setLineWidth(double width)
void saveCairo(const char *filename, CairoType type=CairoPNG, PageSize size=Board::BoundingBox, double margin=10.0) const
void drawImage(std::string filename, double x, double y, double width, double height, int depthValue=-1, double alpha=1.0)
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Trace trace(traceWriterTerm)
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 >())
static std::vector< TQuantity > getColumnElementsFromFile(const std::string &aFilename, unsigned int aPosition)