38 #include "DGtal/base/Common.h"
39 #include "DGtal/helpers/StdDefs.h"
42 #include "DGtal/io/writers/GenericWriter.h"
43 #include "DGtal/images/ImageSelector.h"
44 #include "DGtal/io/boards/Board2D.h"
47 #include "DGtal/io/readers/PointListReader.h"
49 using namespace DGtal;
101 std::pair<Z2i::Point, Z2i::Point > getBoundingBox(
const std::vector<Z2i::Point>& vecPts);
102 std::vector<Z2i::Point> GaussDigization(
const std::vector<Z2i::Point>& polygon);
104 int main(
int argc,
char** argv )
109 std::string inputFileName;
110 std::string outputFileName=
"result.pgm";
112 app.description(
"compute the set of integer points inside the input polyline.\n Basic example:\n \t 2dSimplePolygonDigitizer -i inputPolyline.sdp -o contourDisplay.pgm");
113 app.add_option(
"-i,--input,1", inputFileName,
"Input filename (freeman chain of sdp)." )
115 ->check(CLI::ExistingFile);
116 app.add_option(
"-o,--output,2", outputFileName,
"Output filename",
true);
118 app.get_formatter()->column_width(40);
119 CLI11_PARSE(app, argc, argv);
122 std::string inputExt = inputFileName.substr(inputFileName.find_last_of(
".")+1);
123 if(inputExt !=
"sdp"){
124 trace.
error() <<
"input file should be sdp file" << std::endl;
129 std::vector<Z2i::Point> gd = GaussDigization(poly);
131 std::string outputExt = outputFileName.substr(outputFileName.find_last_of(
".")+1);
132 std::string outputBaseName = outputFileName.substr(0, outputFileName.find_last_of(
"."));
134 if(outputExt ==
"pgm") {
136 std::pair<Z2i::Point, Z2i::Point> bb = getBoundingBox(gd);
141 for(std::vector<Z2i::Point>::const_iterator it=gd.begin(); it!=gd.end(); it++) {
143 image.setValue(p,255);
149 outputFileName = outputBaseName +
".svg";
152 for(std::vector<Z2i::Point>::const_iterator it=gd.begin(); it!=gd.end(); it++) {
157 for(
size_t it=0; it<poly.size()-1; it++) {
160 board.
drawLine(p1[0],p1[1],p2[0],p2[1]);
164 board.
drawLine(p1[0],p1[1],p2[0],p2[1]);
166 board.
saveSVG(outputFileName.c_str());
173 std::pair<Z2i::Point, Z2i::Point > getBoundingBox(
const std::vector<Z2i::Point>& vecPts) {
174 int minX = vecPts.at(0)[0];
175 int maxX = vecPts.at(0)[0];
176 int minY = vecPts.at(0)[1];
177 int maxY = vecPts.at(0)[1];
179 for(
size_t it=1; it<vecPts.size(); it++) {
180 int x = vecPts.at(it)[0];
181 int y = vecPts.at(it)[1];
182 if(minX > x) minX = x;
183 if(maxX < x) maxX = x;
184 if(minY > y) minY = y;
185 if(maxY < y) maxY = y;
189 return std::make_pair(tl,rb);
197 return v1 > v2 ? v1 : v2;
201 return v1 > v2 ? v2 : v1;
203 template<
typename TPo
int>
204 bool onSegment(TPoint p, TPoint q, TPoint r)
206 if (q[0] <= max(p[0], r[0]) && q[0] >= min(p[0], r[0]) && q[1] <= max(p[1], r[1]) && q[1] >= min(p[1], r[1]))
216 template<
typename TPo
int>
217 int orientation(TPoint p, TPoint q, TPoint r)
219 int val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
220 if (val == 0)
return 0;
221 return (val > 0)? 1: 2;
226 template<
typename TPo
int>
227 bool doIntersect(TPoint p1, TPoint q1, TPoint p2, TPoint q2)
231 int o1 = orientation(p1, q1, p2);
232 int o2 = orientation(p1, q1, q2);
233 int o3 = orientation(p2, q2, p1);
234 int o4 = orientation(p2, q2, q1);
237 if (o1 != o2 && o3 != o4)
242 if (o1 == 0 && onSegment(p1, p2, q1))
return true;
245 if (o2 == 0 && onSegment(p1, q2, q1))
return true;
248 if (o3 == 0 && onSegment(p2, p1, q2))
return true;
251 if (o4 == 0 && onSegment(p2, q1, q2))
return true;
257 template<
typename TPo
int>
258 TPoint findDirection(
const std::vector<TPoint>& polygon, TPoint p, TPoint d1, TPoint d2 )
265 for(
size_t it=0; it<polygon.size(); it++) {
267 if(polygon.at(it)==p)
272 if(orientation(p, polygon.at(it), d)==0) {
273 d[0] = (d[0] + d2[0])/2;
274 d[1] = (d[1] + d2[1])/2;
284 template<
typename TPo
int>
285 bool isInsidePolygon(
const std::vector<TPoint>& polygon, TPoint p)
287 int n = polygon.size();
289 if (n < 3)
return false;
293 TPoint extreme1 (p[0], INT_MAX/1e6);
294 TPoint extreme2 (INT_MAX/1e6, p[1]);
295 TPoint extreme = findDirection(polygon, p, extreme1, extreme2);
301 int count = 0, i = 0;
308 if (doIntersect(polygon[i], polygon[next], p, extreme))
313 if (orientation(polygon[i], p, polygon[next]) == 0)
314 return onSegment(polygon[i], p, polygon[next]);
326 std::vector<Z2i::Point> GaussDigization(
const std::vector<Z2i::Point>& polygon)
329 std::vector<TPoint> gd;
330 std::pair<TPoint, TPoint> bb = getBoundingBox(polygon);
331 int minx = int(bb.first[0])-1;
332 int miny = int(bb.first[1])-1;
333 int maxx = int(bb.second[0])+1;
334 int maxy = int(bb.second[1])+1;
335 for(
int x = minx; x<maxx; x++) {
336 for(
int y = miny; y<maxy; y++) {
338 bool ok = isInsidePolygon<TPoint>(polygon,p);
340 TPoint pi(p[0],p[1]);
int main(int argc, char **argv)
Board & setPenColor(const DGtal::Color &color)
void drawLine(double x1, double y1, double x2, double y2, int depthValue=-1)
Board & setLineWidth(double width)
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Trace trace(traceWriterTerm)
static bool exportPGM(const std::string &filename, const Image &aImage, const Functor &aFunctor=Functor(), bool saveASCII=false, bool topbotomOrder=true)
static std::vector< TPoint > getPointsFromFile(const std::string &filename, std::vector< unsigned int > aVectPosition=std::vector< unsigned int >())