Visual Servoing Platform  version 3.4.1 under development (2021-04-20)
vpImageDraw.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Drawing functions.
33  *
34  *****************************************************************************/
35 // Contains code from:
36 /*
37 * Simd Library (http://ermig1979.github.io/Simd).
38 *
39 * Copyright (c) 2011-2017 Yermalayeu Ihar.
40 *
41 * Permission is hereby granted, free of charge, to any person obtaining a copy
42 * of this software and associated documentation files (the "Software"), to deal
43 * in the Software without restriction, including without limitation the rights
44 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45 * copies of the Software, and to permit persons to whom the Software is
46 * furnished to do so, subject to the following conditions:
47 *
48 * The above copyright notice and this permission notice shall be included in
49 * all copies or substantial portions of the Software.
50 *
51 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
57 * SOFTWARE.
58 */
59 
60 #include <visp3/core/vpImageDraw.h>
61 #include <visp3/core/vpPoint.h>
62 #include <visp3/core/vpMeterPixelConversion.h>
63 
64 namespace
65 {
66 template<class Type> void DrawLine(vpImage<Type> & canvas, int x1, int y1, int x2, int y2, const Type & color, unsigned int width = 1)
67 {
68  const int w = static_cast<int>(canvas.getWidth()) - 1;
69  const int h = static_cast<int>(canvas.getHeight()) - 1;
70 
71  if (x1 < 0 || y1 < 0 || (x1 - w) > 0 || (y1 - h) > 0 || x2 < 0 || y2 < 0 || (x2 - w) > 0 || (y2 - h) > 0) {
72  if ((x1 < 0 && x2 < 0) || (y1 < 0 && y2 < 0) || ((x1 - w) > 0 && (x2 - w) > 0) || ((y1 - h) > 0 && (y2 -h) > 0)) {
73  return;
74  }
75 
76  if (y1 == y2) {
77  x1 = std::min<int>(std::max<int>(x1, 0), w);
78  x2 = std::min<int>(std::max<int>(x2, 0), w);
79  } else if (x1 == x2) {
80  y1 = std::min<int>(std::max<int>(y1, 0), h);
81  y2 = std::min<int>(std::max<int>(y2, 0), h);
82  } else {
83  int x0 = (x1*y2 - y1*x2) / (y2 - y1);
84  int y0 = (y1*x2 - x1*y2) / (x2 - x1);
85  int xh = (x1*y2 - y1*x2 + h*(x2 - x1)) / (y2 - y1);
86  int yw = (y1*x2 - x1*y2 + w*(y2 - y1)) / (x2 - x1);
87 
88  if (x1 < 0) {
89  x1 = 0;
90  y1 = y0;
91  }
92  if (x2 < 0) {
93  x2 = 0;
94  y2 = y0;
95  }
96  if (x1 > w) {
97  x1 = w;
98  y1 = yw;
99  }
100  if (x2 > w) {
101  x2 = w;
102  y2 = yw;
103  }
104  if ((y1 < 0 && y2 < 0) || (y1 > h && y2 > h)) {
105  return;
106  }
107 
108  if (y1 < 0) {
109  x1 = x0;
110  y1 = 0;
111  }
112  if (y2 < 0) {
113  x2 = x0;
114  y2 = 0;
115  }
116 
117  if (y1 > h) {
118  x1 = xh;
119  y1 = h;
120  }
121  if (y2 > h) {
122  x2 = xh;
123  y2 = h;
124  }
125  }
126  }
127 
128  const bool inverse = ((std::abs(y2 - y1) - std::abs(x2 - x1)) > 0);
129  if (inverse) {
130  std::swap(x1, y1);
131  std::swap(x2, y2);
132  }
133 
134  if (x1 > x2) {
135  std::swap(x1, x2);
136  std::swap(y1, y2);
137  }
138 
139  const double dx = x2 - x1;
140  const double dy = static_cast<double>(std::abs(y2 - y1));
141 
142  double error = dx / 2.0f;
143  const int ystep = (y1 < y2) ? 1 : -1;
144  int y0 = y1 - static_cast<int>(width) / 2;
145 
146  for (int x = x1; x <= x2; x++) {
147  for (int i = 0; i < static_cast<int>(width); i++) {
148  int y = y0 + i;
149  if (y >= 0) {
150  if (inverse) {
151  if (y < w) {
152  canvas[x][y] = color;
153  }
154  } else {
155  if (y < h) {
156  canvas[y][x] = color;
157  }
158  }
159  }
160 
161  }
162 
163  error -= dy;
164  if (error < 0) {
165  y0 += ystep;
166  error += dx;
167  }
168  }
169 }
170 
171 template<class Type> void DrawCircle(vpImage<Type> & canvas, const vpImagePoint & center, int radius, const Type & color, unsigned int width = 1)
172 {
173  const size_t n = 8 * std::max(static_cast<size_t>(1), static_cast<size_t>(::pow(radius, 0.5)));
174  double px = 0, py = 0, da = 2 * M_PI / n;
175  for (size_t i = 0; i <= n; i++) {
176  double a = i*da;
177  double cx = radius*::cos(a) + center.get_u();
178  double cy = radius*::sin(a) + center.get_v();
179  if (i > 0) {
180  DrawLine(canvas, static_cast<int>(cx), static_cast<int>(cy), static_cast<int>(px), static_cast<int>(py), color, width);
181  }
182  px = cx;
183  py = cy;
184  }
185 }
186 
187 template<class Type> void DrawFilledRectangle(vpImage<Type> & canvas, vpRect rect, const Type & color)
188 {
189  rect &= vpRect(0, 0, canvas.getWidth(), canvas.getHeight());
190  for (int row = static_cast<int>(rect.getTop()); row < static_cast<int>(rect.getBottom()); row++) {
191  Type * dst = canvas[row];
192  for (int col = static_cast<int>(rect.getLeft()); col < static_cast<int>(rect.getRight()); col++) {
193  dst[col] = color;
194  }
195  }
196 }
197 
198 template<class Type> void DrawPolygon(vpImage<Type> & canvas, const std::vector<vpImagePoint> & polygon,
199  const Type & color, unsigned int width = 1, bool closed = true)
200 {
201  if (closed) {
202  for (size_t i = 0; i < polygon.size(); i++) {
203  const vpImagePoint & p1 = (i ? polygon[i - 1] : polygon.back()), p2 = polygon[i];
204  DrawLine(canvas, static_cast<int>(p1.get_u()), static_cast<int>(p1.get_v()),
205  static_cast<int>(p2.get_u()), static_cast<int>(p2.get_v()), color, width);
206  }
207  }
208  else {
209  for (size_t i = 1; i < polygon.size(); i++) {
210  DrawLine(canvas, static_cast<int>(polygon[i-1].get_u()), static_cast<int>(polygon[i-1].get_v()),
211  static_cast<int>(polygon[i].get_u()), static_cast<int>(polygon[i].get_v()), color, width);
212  }
213  }
214 }
215 
216 template<class Type> void DrawRectangle(vpImage<Type> & canvas, const vpRect & rect, const Type & color, unsigned int width = 1)
217 {
218  DrawLine(canvas, static_cast<int>(rect.getLeft()), static_cast<int>(rect.getTop()),
219  static_cast<int>(rect.getRight()), static_cast<int>(rect.getTop()), color, width);
220  DrawLine(canvas, static_cast<int>(rect.getRight()), static_cast<int>(rect.getTop()),
221  static_cast<int>(rect.getRight()), static_cast<int>(rect.getBottom()), color, width);
222  DrawLine(canvas, static_cast<int>(rect.getRight()), static_cast<int>(rect.getBottom()),
223  static_cast<int>(rect.getLeft()), static_cast<int>(rect.getBottom()), color, width);
224  DrawLine(canvas, static_cast<int>(rect.getLeft()), static_cast<int>(rect.getBottom()),
225  static_cast<int>(rect.getLeft()), static_cast<int>(rect.getTop()), color, width);
226 }
227 }
228 
238  unsigned char color, unsigned int w, unsigned int h, unsigned int thickness)
239 {
240  double a = ip2.get_i() - ip1.get_i();
241  double b = ip2.get_j() - ip1.get_j();
242  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
243 
244  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
245  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
246  // DisplayCrossLarge(i1,j1,3,col) ;
247  } else {
248  a /= lg;
249  b /= lg;
250 
251  vpImagePoint ip3;
252  ip3.set_i(ip2.get_i() - w * a);
253  ip3.set_j(ip2.get_j() - w * b);
254 
255  vpImagePoint ip4;
256  ip4.set_i(ip3.get_i() - b * h);
257  ip4.set_j(ip3.get_j() + a * h);
258 
259  if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
260  drawLine(I, ip2, ip4, color, thickness);
261  }
262 
263  ip4.set_i(ip3.get_i() + b * h);
264  ip4.set_j(ip3.get_j() - a * h);
265 
266  if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
267  drawLine(I, ip2, ip4, color, thickness);
268  }
269 
270  drawLine(I, ip1, ip2, color, thickness);
271  }
272 }
273 
283  const vpColor &color, unsigned int w, unsigned int h, unsigned int thickness)
284 {
285  double a = ip2.get_i() - ip1.get_i();
286  double b = ip2.get_j() - ip1.get_j();
287  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
288 
289  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
290  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
291  // DisplayCrossLarge(i1,j1,3,col) ;
292  } else {
293  a /= lg;
294  b /= lg;
295 
296  vpImagePoint ip3;
297  ip3.set_i(ip2.get_i() - w * a);
298  ip3.set_j(ip2.get_j() - w * b);
299 
300  vpImagePoint ip4;
301  ip4.set_i(ip3.get_i() - b * h);
302  ip4.set_j(ip3.get_j() + a * h);
303 
304  if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
305  drawLine(I, ip2, ip4, color, thickness);
306  }
307 
308  ip4.set_i(ip3.get_i() + b * h);
309  ip4.set_j(ip3.get_j() - a * h);
310 
311  if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
312  drawLine(I, ip2, ip4, color, thickness);
313  }
314 
315  drawLine(I, ip1, ip2, color, thickness);
316  }
317 }
318 
328  unsigned int radius, unsigned char color, unsigned int thickness)
329 {
330  DrawCircle(I, center, static_cast<int>(radius), color, thickness);
331 }
332 
342  unsigned int radius, const vpColor &color, unsigned int thickness)
343 {
344  DrawCircle(I, center, static_cast<int>(radius), vpRGBa(color.R, color.G, color.B), thickness);
345 }
346 
355 void vpImageDraw::drawCross(vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned int size,
356  unsigned char color, unsigned int thickness)
357 {
358  vpImagePoint top, bottom, left, right;
359  top.set_i(ip.get_i() - size / 2);
360  top.set_j(ip.get_j());
361  bottom.set_i(ip.get_i() + size / 2);
362  bottom.set_j(ip.get_j());
363  left.set_i(ip.get_i());
364  left.set_j(ip.get_j() - size / 2);
365  right.set_i(ip.get_i());
366  right.set_j(ip.get_j() + size / 2);
367  drawLine(I, top, bottom, color, thickness);
368  drawLine(I, left, right, color, thickness);
369 }
370 
379 void vpImageDraw::drawCross(vpImage<vpRGBa> &I, const vpImagePoint &ip, unsigned int size,
380  const vpColor &color, unsigned int thickness)
381 {
382  vpImagePoint top, bottom, left, right;
383  top.set_i(ip.get_i() - size / 2);
384  top.set_j(ip.get_j());
385  bottom.set_i(ip.get_i() + size / 2);
386  bottom.set_j(ip.get_j());
387  left.set_i(ip.get_i());
388  left.set_j(ip.get_j() - size / 2);
389  right.set_i(ip.get_i());
390  right.set_j(ip.get_j() + size / 2);
391  drawLine(I, top, bottom, color, thickness);
392  drawLine(I, left, right, color, thickness);
393 }
394 
403  unsigned char color, unsigned int thickness)
404 {
405  vpImagePoint ip1_ = ip1;
406  vpImagePoint ip2_ = ip2;
407 
408  double size = 10;
409  double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
410  bool vertical_line = static_cast<int>(ip2_.get_j()) == static_cast<int>(ip1_.get_j());
411  if (vertical_line) {
412  if (ip2_.get_i() < ip1_.get_i()) {
413  std::swap(ip1_, ip2_);
414  }
415  } else if (ip2_.get_j() < ip1_.get_j()) {
416  std::swap(ip1_, ip2_);
417  }
418 
419  double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
420  double deltaj = size / length * diff_j;
421  double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
422  double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
423  double orig = ip1_.get_i() - slope * ip1_.get_j();
424 
425  if (vertical_line) {
426  for (unsigned int i = static_cast<unsigned int>(ip1_.get_i()); i < ip2_.get_i(); i += static_cast<unsigned int>(2 * deltai)) {
427  double j = ip1_.get_j();
428  drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
429  }
430  } else {
431  for (unsigned int j = static_cast<unsigned int>(ip1_.get_j()); j < ip2_.get_j(); j += static_cast<unsigned int>(2 * deltaj)) {
432  double i = slope * j + orig;
433  drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
434  }
435  }
436 }
437 
445 void vpImageDraw::drawDottedLine(vpImage<vpRGBa> &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness)
446 {
447  vpImagePoint ip1_ = ip1;
448  vpImagePoint ip2_ = ip2;
449 
450  double size = 10;
451  double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
452  bool vertical_line = static_cast<int>(ip2_.get_j()) == static_cast<int>(ip1_.get_j());
453  if (vertical_line) {
454  if (ip2_.get_i() < ip1_.get_i()) {
455  std::swap(ip1_, ip2_);
456  }
457  } else if (ip2_.get_j() < ip1_.get_j()) {
458  std::swap(ip1_, ip2_);
459  }
460 
461  double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
462  double deltaj = size / length * diff_j;
463  double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
464  double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
465  double orig = ip1_.get_i() - slope * ip1_.get_j();
466 
467  if (vertical_line) {
468  for (unsigned int i = static_cast<unsigned int>(ip1_.get_i()); i < ip2_.get_i(); i += static_cast<unsigned int>(2 * deltai)) {
469  double j = ip1_.get_j();
470  drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
471  }
472  } else {
473  for (unsigned int j = static_cast<unsigned int>(ip1_.get_j()); j < ip2_.get_j(); j += static_cast<unsigned int>(2 * deltaj)) {
474  double i = slope * j + orig;
475  drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
476  }
477  }
478 }
479 
516 void vpImageDraw::drawEllipse(vpImage<unsigned char> &I, const vpImagePoint &center, double coef1,
517  double coef2, double coef3, bool use_normalized_centered_moments, unsigned char color,
518  double smallalpha, double highalpha, unsigned int thickness)
519 {
520  double a = 0., b = 0., e = 0.;
521 
522  if (use_normalized_centered_moments) {
523  // Chaumette, Image Moments: A General and Useful Set of Features for Visual Servoing, TRO 2004, eq 24
524  // Similar code as in function vpMeEllipse::computeAbeFromNij() in vpMeEllipse.cpp
525  double n20_p = coef1;
526  double n11_p = coef2;
527  double n02_p = coef3;
528  double num = n20_p - n02_p;
529  double d = num * num + 4.0 * n11_p * n11_p; // always >= 0
530 
531  if (d <= std::numeric_limits<double>::epsilon()) { // circle
532  e = 0.0; // case n20 = n02 and n11 = 0 : circle, e undefined
533  a = b = 2.0*sqrt(n20_p);
534  }
535  else { // real ellipse
536  e = atan2(2.0*n11_p, num)/2.0; // e in [-Pi/2 ; Pi/2]
537  d = sqrt(d); // d in sqrt always >= 0
538  num = n20_p + n02_p;
539  a = sqrt(2.0*(num + d)); // term in sqrt always > 0
540  b = sqrt(2.0*(num - d)); // term in sqrt always > 0
541  }
542  } else {
543  a = coef1;
544  b = coef2;
545  e = coef3;
546  }
547 
548  // For all what follows similar code as in function vpMeEllipse::display() in vpMeEllipse.cpp
549 
550  // Approximation of the circumference of an ellipse:
551  // [Ramanujan, S., "Modular Equations and Approximations to ,"
552  // Quart. J. Pure. Appl. Math., vol. 45 (1913-1914), pp. 350-372]
553  double angle = highalpha - smallalpha;
554 
555  double t = (a - b) / (a + b);
556  t *= t; // t^2
557  double circumference = (angle/2.0) * (a + b) * (1.0 + 3.0 * t / (10.0 + sqrt(4.0 - 3.0 * t)));
558  unsigned int nbpoints = (unsigned int)(floor(circumference / 20));
559  if (nbpoints < 10) {
560  nbpoints = 10;
561  }
562  double incr = angle / nbpoints; // angle increment
563 
564  double u0 = center.get_u();
565  double v0 = center.get_v();
566  double cose = cos(e);
567  double sine = sin(e);
568 
569  double u = a * cos(smallalpha); // equation of an ellipse
570  double v = b * sin(smallalpha); // equation of an ellipse
571  angle = smallalpha;
572  // (i1,j1) are the coordinates on the origin centered ellipse ;
573  // a rotation by "e" and a translation by (xci,jc) are done
574  // to get the coordinates of the point on the shifted ellipse
575  vpImagePoint iP11;
576  iP11.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
577 
578  // display the arc of the ellipse by succesive small segments
579  for (unsigned int i = 0; i < nbpoints; i++) {
580  angle += incr;
581  // Two concentric circles method used
582  u = a * cos(angle);
583  v = b * sin(angle);
584  // to get the coordinates of the point on the shifted ellipse
585  vpImagePoint iP22;
586  iP22.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
587 
588  drawLine(I, iP11, iP22, color, thickness);
589 
590  iP11 = iP22;
591  }
592 }
593 
630 void vpImageDraw::drawEllipse(vpImage<vpRGBa> &I, const vpImagePoint &center, double coef1,
631  double coef2, double coef3, bool use_normalized_centered_moments, const vpColor &color,
632  double smallalpha, double highalpha, unsigned int thickness)
633 {
634  double a = 0., b = 0., e = 0.;
635 
636  if (use_normalized_centered_moments) {
637  // Chaumette, Image Moments: A General and Useful Set of Features for Visual Servoing, TRO 2004, eq 24
638  // Similar code as in function vpMeEllipse::computeAbeFromNij() in vpMeEllipse.cpp
639  double n20_p = coef1;
640  double n11_p = coef2;
641  double n02_p = coef3;
642  double num = n20_p - n02_p;
643  double d = num * num + 4.0 * n11_p * n11_p; // always >= 0
644 
645  if (d <= std::numeric_limits<double>::epsilon()) { // circle
646  e = 0.0; // case n20 = n02 and n11 = 0 : circle, e undefined
647  a = b = 2.0*sqrt(n20_p);
648  }
649  else { // real ellipse
650  e = atan2(2.0*n11_p, num)/2.0; // e in [-Pi/2 ; Pi/2]
651  d = sqrt(d); // d in sqrt always >= 0
652  num = n20_p + n02_p;
653  a = sqrt(2.0*(num + d)); // term in sqrt always > 0
654  b = sqrt(2.0*(num - d)); // term in sqrt always > 0
655  }
656  } else {
657  a = coef1;
658  b = coef2;
659  e = coef3;
660  }
661 
662  // For all what follows similar code as in function vpMeEllipse::display() in vpMeEllipse.cpp
663 
664  // Approximation of the circumference of an ellipse:
665  // [Ramanujan, S., "Modular Equations and Approximations to ,"
666  // Quart. J. Pure. Appl. Math., vol. 45 (1913-1914), pp. 350-372]
667  double angle = highalpha - smallalpha;
668 
669  double t = (a - b) / (a + b);
670  t *= t; // t^2
671  double circumference = (angle/2.0) * (a + b) * (1.0 + 3.0 * t / (10.0 + sqrt(4.0 - 3.0 * t)));
672  unsigned int nbpoints = (unsigned int)(floor(circumference / 20));
673  if (nbpoints < 10) {
674  nbpoints = 10;
675  }
676  double incr = angle / nbpoints; // angle increment
677 
678  double u0 = center.get_u();
679  double v0 = center.get_v();
680  double cose = cos(e);
681  double sine = sin(e);
682 
683  double u = a * cos(smallalpha); // equation of an ellipse
684  double v = b * sin(smallalpha); // equation of an ellipse
685  angle = smallalpha;
686  // (i1,j1) are the coordinates on the origin centered ellipse ;
687  // a rotation by "e" and a translation by (xci,jc) are done
688  // to get the coordinates of the point on the shifted ellipse
689  vpImagePoint iP11;
690  iP11.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
691 
692  // display the arc of the ellipse by succesive small segments
693  for (unsigned int i = 0; i < nbpoints; i++) {
694  angle += incr;
695  // Two concentric circles method used
696  u = a * cos(angle);
697  v = b * sin(angle);
698  // to get the coordinates of the point on the shifted ellipse
699  vpImagePoint iP22;
700  iP22.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
701 
702  drawLine(I, iP11, iP22, color, thickness);
703 
704  iP11 = iP22;
705  }
706 }
707 
724  double size, unsigned char color, unsigned int thickness, const vpImagePoint &offset)
725 {
726  vpPoint o(0.0, 0.0, 0.0);
727  vpPoint x(size, 0.0, 0.0);
728  vpPoint y(0.0, size, 0.0);
729  vpPoint z(0.0, 0.0, size);
730 
731  o.track(cMo);
732  x.track(cMo);
733  y.track(cMo);
734  z.track(cMo);
735 
736  vpImagePoint ipo, ip1;
737 
738  vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
739 
740  vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
741  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
742 
743  vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
744  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
745 
746  vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
747  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
748 }
749 
766  double size, const vpColor &color, unsigned int thickness, const vpImagePoint &offset)
767 {
768  vpPoint o(0.0, 0.0, 0.0);
769  vpPoint x(size, 0.0, 0.0);
770  vpPoint y(0.0, size, 0.0);
771  vpPoint z(0.0, 0.0, size);
772 
773  o.track(cMo);
774  x.track(cMo);
775  y.track(cMo);
776  z.track(cMo);
777 
778  vpImagePoint ipo, ip1;
779 
780  if (color == vpColor::none) {
781  vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
782 
783  vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
784  drawArrow(I, ipo + offset, ip1 + offset, vpColor::red, 4 * thickness, 2 * thickness, thickness);
785 
786  vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
787  drawArrow(I, ipo + offset, ip1 + offset, vpColor::green, 4 * thickness, 2 * thickness, thickness);
788 
789  vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
790  drawArrow(I, ipo + offset, ip1 + offset, vpColor::blue, 4 * thickness, 2 * thickness, thickness);
791  } else {
792  vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
793 
794  vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
795  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
796 
797  vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
798  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
799 
800  vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
801  drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
802  }
803 }
804 
813  unsigned char color, unsigned int thickness)
814 {
815  DrawLine(I, static_cast<int>(ip1.get_u()), static_cast<int>(ip1.get_v()),
816  static_cast<int>(ip2.get_u()), static_cast<int>(ip2.get_v()), color,
817  thickness);
818 }
819 
827 void vpImageDraw::drawLine(vpImage<vpRGBa> &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness)
828 {
829  DrawLine(I, static_cast<int>(ip1.get_u()), static_cast<int>(ip1.get_v()),
830  static_cast<int>(ip2.get_u()), static_cast<int>(ip2.get_v()), vpRGBa(color.R, color.G, color.B),
831  thickness);
832 }
833 
841 void vpImageDraw::drawPoint(vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned char color, unsigned int thickness)
842 {
843  drawRectangle(I, vpRect(ip, thickness, thickness), color, true);
844 }
845 
853 void vpImageDraw::drawPoint(vpImage<vpRGBa> &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
854 {
855  drawRectangle(I, vpRect(ip, thickness, thickness), color, true);
856 }
857 
866 void vpImageDraw::drawPolygon(vpImage<unsigned char> &I, const std::vector<vpImagePoint> &vip,
867  unsigned char color, unsigned int thickness, bool closed)
868 {
869  DrawPolygon(I, vip, color, thickness, closed);
870 }
871 
880 void vpImageDraw::drawPolygon(vpImage<vpRGBa> &I, const std::vector<vpImagePoint> &vip,
881  const vpColor &color, unsigned int thickness, bool closed)
882 {
883  DrawPolygon(I, vip, vpRGBa(color.R, color.G, color.B), thickness, closed);
884 }
885 
898 void vpImageDraw::drawRectangle(vpImage<unsigned char> &I, const vpRect &rectangle, unsigned char color, bool fill, unsigned int thickness)
899 {
900  if (fill) {
901  DrawFilledRectangle(I, rectangle, color);
902  } else {
903  DrawRectangle(I, rectangle, color, thickness);
904  }
905 }
906 
919 void vpImageDraw::drawRectangle(vpImage<vpRGBa> &I, const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
920 {
921  if (fill) {
922  DrawFilledRectangle(I, rectangle, vpRGBa(color.R, color.G, color.B));
923  } else {
924  DrawRectangle(I, rectangle, vpRGBa(color.R, color.G, color.B), thickness);
925  }
926 }
double get_i() const
Definition: vpImagePoint.h:203
double getTop() const
Definition: vpRect.h:193
static void drawRectangle(vpImage< unsigned char > &I, const vpRect &rectangle, unsigned char color, bool fill=false, unsigned int thickness=1)
Implementation of an homogeneous matrix and operations on such kind of matrices.
unsigned char B
Blue component.
Definition: vpRGBa.h:150
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static void drawCircle(vpImage< unsigned char > &I, const vpImagePoint &center, unsigned int radius, unsigned char color, unsigned int thickness=1)
void set_uv(double u, double v)
Definition: vpImagePoint.h:247
static void drawFrame(vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, unsigned char color, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0))
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
static void drawEllipse(vpImage< unsigned char > &I, const vpImagePoint &center, double coef1, double coef2, double coef3, bool use_normalized_centered_moments, unsigned char color, double smallalpha=0, double highalpha=2 *M_PI, unsigned int thickness=1)
static void drawArrow(vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, unsigned char color, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static const vpColor none
Definition: vpColor.h:229
void track(const vpHomogeneousMatrix &cMo)
static void drawDottedLine(vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, unsigned char color, unsigned int thickness=1)
unsigned char G
Green component.
Definition: vpRGBa.h:149
static const vpColor green
Definition: vpColor.h:220
double getRight() const
Definition: vpRect.h:180
Definition: vpRGBa.h:66
static const vpColor red
Definition: vpColor.h:217
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:81
double get_u() const
Definition: vpImagePoint.h:262
void set_i(double ii)
Definition: vpImagePoint.h:166
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
static double sqr(double x)
Definition: vpMath.h:116
static void drawPoint(vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned char color, unsigned int thickness=1)
double get_j() const
Definition: vpImagePoint.h:214
Generic class defining intrinsic camera parameters.
double getLeft() const
Definition: vpRect.h:174
void set_j(double jj)
Definition: vpImagePoint.h:177
unsigned int getHeight() const
Definition: vpImage.h:188
static void drawCross(vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, unsigned char color, unsigned int thickness=1)
unsigned char R
Red component.
Definition: vpRGBa.h:148
static void drawPolygon(vpImage< unsigned char > &I, const std::vector< vpImagePoint > &vip, unsigned char color, unsigned int thickness=1, bool closed=true)
Defines a rectangle in the plane.
Definition: vpRect.h:79
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
unsigned int getWidth() const
Definition: vpImage.h:246
double getBottom() const
Definition: vpRect.h:98
static void drawLine(vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, unsigned char color, unsigned int thickness=1)
Definition of the vpImage class member functions.
Definition: vpImage.h:126
vpColVector p
Definition: vpTracker.h:73
double get_v() const
Definition: vpImagePoint.h:273
static const vpColor blue
Definition: vpColor.h:223