Visual Servoing Platform  version 3.6.1 under development (2025-03-16)
testPolygon.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Example which test the polygon.
32  */
33 
37 #include <visp3/core/vpConfig.h>
38 #include <visp3/core/vpImagePoint.h>
39 #include <visp3/core/vpPolygon.h>
40 #include <visp3/io/vpParseArgv.h>
41 
42 #include <visp3/core/vpDisplay.h>
43 #include <visp3/gui/vpDisplayGDI.h>
44 #include <visp3/gui/vpDisplayGTK.h>
45 #include <visp3/gui/vpDisplayX.h>
46 
47 #include <math.h>
48 
49 #include <iostream>
50 #include <string>
51 #include <vector>
52 
54 #define GETOPTARGS "cdm:h"
55 
56 void usage(const char *name, const char *badparam);
57 bool getOptions(int argc, const char **argv, bool &opt_display, bool &opt_click, int &method);
58 
67 void usage(const char *name, const char *badparam)
68 {
69  fprintf(stdout, "\n\
70 test the generic 2D polygons.\n\
71 \n\
72 SYNOPSIS\n\
73  %s [-c] [-d] [-h]\n\
74 ",
75 name);
76 
77  fprintf(stdout, "\n\
78 OPTIONS: \n\
79  -c \n\
80  Disable mouse click.\n\
81 \n\
82  -d \n\
83  Turn off display.\n\
84 \n\
85  -m \n\
86  Point in polygon test method.\n\
87 \n\
88  -h\n\
89  Print the help.\n\n");
90 
91  if (badparam) {
92  fprintf(stderr, "ERROR: \n");
93  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
94  }
95 }
96 
106 bool getOptions(int argc, const char **argv, bool &opt_display, bool &opt_click, int &method)
107 {
108 #ifdef ENABLE_VISP_NAMESPACE
109  using namespace VISP_NAMESPACE_NAME;
110 #endif
111  const char *optarg_;
112  int c;
113  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
114 
115  switch (c) {
116  case 'c':
117  opt_click = false;
118  break;
119  case 'd':
120  opt_display = false;
121  break;
122  case 'm':
123  method = atoi(optarg_);
124  break;
125  case 'h':
126  usage(argv[0], nullptr);
127  return false;
128  break;
129 
130  default:
131  usage(argv[0], optarg_);
132  return false;
133  break;
134  }
135  }
136 
137  if ((c == 1) || (c == -1)) {
138  // standalone param or error
139  usage(argv[0], nullptr);
140  std::cerr << "ERROR: " << std::endl;
141  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
142  return false;
143  }
144 
145  return true;
146 }
147 
148 /* --------------------------------------------------------------------------
149  */
150  /* MAIN FUNCTION */
151  /* --------------------------------------------------------------------------
152  */
153 
154 int main(int argc, const char **argv)
155 {
156 #ifdef ENABLE_VISP_NAMESPACE
157  using namespace VISP_NAMESPACE_NAME;
158 #endif
159  try {
160  bool opt_display = true;
161  bool opt_click = true;
163  vpImage<unsigned char> I(480, 640, 255);
164 
165  // Read the command line options
166  if (getOptions(argc, argv, opt_display, opt_click, method) == false) {
167  return EXIT_FAILURE;
168  }
169 
170  std::vector<vpImagePoint> vec1;
171  vec1.push_back(vpImagePoint(200, 200));
172  vec1.push_back(vpImagePoint(200, 400));
173  vec1.push_back(vpImagePoint(320, 400));
174  vec1.push_back(vpImagePoint(380, 300));
175  vec1.push_back(vpImagePoint(280, 280));
176  vpPolygon p1;
177  p1.buildFrom(vec1);
178 
179  std::vector<vpImagePoint> vec2;
180  vec2.push_back(vpImagePoint(20, 20));
181  vec2.push_back(vpImagePoint(100, 20));
182  vec2.push_back(vpImagePoint(100, 100));
183  vec2.push_back(vpImagePoint(20, 100));
184  vpPolygon p2(vec2);
185 
186  std::vector<vpImagePoint> vec3;
187  vpPolygon p3(vec3);
188 
189 #if defined(VISP_HAVE_X11)
190  vpDisplayX display;
191 #elif defined(VISP_HAVE_GTK)
192  vpDisplayGTK display;
193 #elif defined(VISP_HAVE_GDI)
194  vpDisplayGDI display;
195 #else
196  opt_display = false;
197 #endif
198 
199  std::cout << " Polygon 1 : " << std::endl;
200  std::cout << " area : " << p1.getArea() << std::endl;
201  std::cout << " center : " << p1.getCenter() << std::endl << std::endl;
202 
203  std::cout << " Polygon 2 : " << std::endl;
204  std::cout << " area : " << p2.getArea() << std::endl;
205  std::cout << " center : " << p2.getCenter() << std::endl << std::endl;
206 
207  std::cout << " Polygon 3 : " << std::endl;
208  std::cout << " area : " << p3.getArea() << std::endl;
209  std::cout << " center : " << p3.getCenter() << std::endl;
210 
211  if (opt_display) {
212 #if (defined VISP_HAVE_X11) || (defined VISP_HAVE_GTK) || (defined VISP_HAVE_GDI)
213  display.init(I, 10, 10, "Test vpPolygon");
214 #endif
216  p1.display(I, vpColor::green, 1);
218  p2.display(I, vpColor::red, 1);
219  vpDisplay::displayCross(I, p2.getCenter(), 5, vpColor::red);
220  p3.display(I, vpColor::blue, 1);
221  vpDisplay::displayCross(I, p3.getCenter(), 5, vpColor::lightBlue);
222  vpDisplay::displayText(I, vpImagePoint(10, 10), "Click to finish", vpColor::red);
223  vpDisplay::flush(I);
224 
225  if (opt_click)
227 
229  vpDisplay::displayText(I, vpImagePoint(10, 10), "Left click to add a point", vpColor::red);
230  vpDisplay::displayText(I, vpImagePoint(20, 10), "Right click to build the polygon", vpColor::red);
231  vpDisplay::flush(I);
232  if (opt_click) {
233  vpPolygon p4;
234  p4.initClick(I);
235  p4.display(I, vpColor::green, 1);
236  std::cout << std::endl;
237  std::cout << " Polygon 4 : " << std::endl;
238  std::cout << " area : " << p4.getArea() << std::endl;
239  std::cout << " center : " << p4.getCenter() << std::endl;
240  std::cout << "Click to continue." << std::endl;
241  vpDisplay::flush(I);
243 
244  vpRect bbox = p4.getBoundingBox();
245  for (unsigned int i = (unsigned int)floor(bbox.getTop()); i < (unsigned int)ceil(bbox.getBottom()); ++i) {
246  for (unsigned int j = (unsigned int)floor(bbox.getLeft()); j < (unsigned int)ceil(bbox.getRight()); ++j) {
247  if (p4.isInside(vpImagePoint(i, j), (vpPolygon::PointInPolygonMethod)method)) {
249  }
250  }
251  }
252  vpDisplay::flush(I);
253 
254  std::cout << "Click to continue." << std::endl;
256  for (unsigned int i = 0; i < I.getHeight(); ++i) {
257  for (unsigned int j = 0; j < I.getWidth(); ++j) {
260  }
261  }
262  }
263  vpDisplay::flush(I);
264 
265  std::cout << "Click to finish." << std::endl;
266 
268  vpDisplay::close(I);
269 
270  // Benchmark Point In Polygon test method
271  std::vector<vpImagePoint> corners = p4.getCorners();
272  std::cout << "Nb polygon corners=" << corners.size() << std::endl;
273 
274  vpPolygon polygon_benchmark(corners);
275  vpImage<unsigned char> I_segmentIntersection(480, 640, 0);
276  vpImage<unsigned char> I_rayCasting(480, 640, 0);
277 
278  double t_benchmark = vpTime::measureTimeMs();
279  for (unsigned int i = 0; i < I_segmentIntersection.getHeight(); i++) {
280  for (unsigned int j = 0; j < I_segmentIntersection.getWidth(); j++) {
281  if (polygon_benchmark.isInside(vpImagePoint(i, j), vpPolygon::PnPolySegmentIntersection)) {
282  I_segmentIntersection[i][j] = 255;
283  }
284  }
285  }
286  t_benchmark = vpTime::measureTimeMs() - t_benchmark;
287  std::cout << "PnPolySegmentIntersection: " << t_benchmark << " ms" << std::endl;
288 
289  t_benchmark = vpTime::measureTimeMs();
290  for (unsigned int i = 0; i < I_rayCasting.getHeight(); i++) {
291  for (unsigned int j = 0; j < I_rayCasting.getWidth(); j++) {
292  if (polygon_benchmark.isInside(vpImagePoint(i, j), vpPolygon::PnPolyRayCasting)) {
293  I_rayCasting[i][j] = 255;
294  }
295  }
296  }
297  t_benchmark = vpTime::measureTimeMs() - t_benchmark;
298  std::cout << "PnPolyRayCasting: " << t_benchmark << " ms" << std::endl;
299 
300 #if defined(VISP_HAVE_X11)
301  vpDisplayX display1, display2;
302 #elif defined(VISP_HAVE_GTK)
303  vpDisplayGTK display1, display2;
304 #elif defined(VISP_HAVE_GDI)
305  vpDisplayGDI display1, display2;
306 #endif
307 
308 #if (defined VISP_HAVE_X11) || (defined VISP_HAVE_GTK) || (defined VISP_HAVE_GDI)
309  display1.init(I_segmentIntersection, 10, 10, "Segment Intersection test");
310  display2.init(I_rayCasting, (int)I_segmentIntersection.getWidth() + 10, 10, "Ray Casting test");
311 #endif
312 
313  vpDisplay::display(I_segmentIntersection);
314  vpDisplay::display(I_rayCasting);
315  vpDisplay::displayText(I_rayCasting, 20, 20, "Click to quit.", vpColor::red);
316  vpDisplay::flush(I_segmentIntersection);
317  vpDisplay::flush(I_rayCasting);
318 
319  vpDisplay::getClick(I_rayCasting);
320  }
321  }
322 
323  return EXIT_SUCCESS;
324  }
325  catch (const vpException &e) {
326  std::cout << "Catch an exception: " << e << std::endl;
327  return EXIT_FAILURE;
328  }
329 }
static const vpColor red
Definition: vpColor.h:198
static const vpColor orange
Definition: vpColor.h:208
static const vpColor blue
Definition: vpColor.h:204
static const vpColor lightBlue
Definition: vpColor.h:203
static const vpColor green
Definition: vpColor.h:201
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:133
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:135
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") VP_OVERRIDE
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void close(vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
Defines a generic 2D polygon.
Definition: vpPolygon.h:103
const std::vector< vpImagePoint > & getCorners() const
Definition: vpPolygon.h:140
void display(const vpImage< unsigned char > &I, const vpColor &color, unsigned int thickness=1) const
Definition: vpPolygon.cpp:617
vpRect getBoundingBox() const
Definition: vpPolygon.h:164
vpPolygon & buildFrom(const std::vector< vpImagePoint > &corners, const bool &create_convex_hull=false)
Definition: vpPolygon.cpp:195
vpImagePoint getCenter() const
Definition: vpPolygon.h:156
double getArea() const
Definition: vpPolygon.h:148
PointInPolygonMethod
Definition: vpPolygon.h:106
@ PnPolyRayCasting
Definition: vpPolygon.h:108
@ PnPolySegmentIntersection
Definition: vpPolygon.h:107
void initClick(const vpImage< unsigned char > &I, unsigned int size=5, const vpColor &color=vpColor::red, unsigned int thickness=1)
Definition: vpPolygon.cpp:267
bool isInside(const vpImagePoint &iP, const PointInPolygonMethod &method=PnPolyRayCasting) const
Definition: vpPolygon.cpp:402
Defines a rectangle in the plane.
Definition: vpRect.h:79
double getLeft() const
Definition: vpRect.h:173
double getRight() const
Definition: vpRect.h:179
double getBottom() const
Definition: vpRect.h:97
double getTop() const
Definition: vpRect.h:192
VISP_EXPORT double measureTimeMs()