Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpImageDraw.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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 * Drawing functions.
32 */
33// Contains code from:
34/*
35 * Simd Library (http://ermig1979.github.io/Simd).
36 *
37 * Copyright (c) 2011-2017 Yermalayeu Ihar.
38 *
39 * Permission is hereby granted, free of charge, to any person obtaining a copy
40 * of this software and associated documentation files (the "Software"), to deal
41 * in the Software without restriction, including without limitation the rights
42 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43 * copies of the Software, and to permit persons to whom the Software is
44 * furnished to do so, subject to the following conditions:
45 *
46 * The above copyright notice and this permission notice shall be included in
47 * all copies or substantial portions of the Software.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55 * SOFTWARE.
56 */
57
58#include <visp3/core/vpImageDraw.h>
59#include <visp3/core/vpMeterPixelConversion.h>
60#include <visp3/core/vpPoint.h>
61
62namespace
63{
64#ifdef ENABLE_VISP_NAMESPACE
65using namespace VISP_NAMESPACE_NAME;
66#endif
67template <class Type>
68void DrawLine(vpImage<Type> &canvas, int x1, int y1, int x2, int y2, const Type &color, unsigned int width = 1)
69{
70 const int w = static_cast<int>(canvas.getWidth()) - 1;
71 const int h = static_cast<int>(canvas.getHeight()) - 1;
72
73 if (x1 < 0 || y1 < 0 || (x1 - w) > 0 || (y1 - h) > 0 || x2 < 0 || y2 < 0 || (x2 - w) > 0 || (y2 - h) > 0) {
74 if ((x1 < 0 && x2 < 0) || (y1 < 0 && y2 < 0) || ((x1 - w) > 0 && (x2 - w) > 0) || ((y1 - h) > 0 && (y2 - h) > 0)) {
75 return;
76 }
77
78 if (y1 == y2) {
79 x1 = std::min<int>(std::max<int>(x1, 0), w);
80 x2 = std::min<int>(std::max<int>(x2, 0), w);
81 }
82 else if (x1 == x2) {
83 y1 = std::min<int>(std::max<int>(y1, 0), h);
84 y2 = std::min<int>(std::max<int>(y2, 0), h);
85 }
86 else {
87 int x0 = (x1 * y2 - y1 * x2) / (y2 - y1);
88 int y0 = (y1 * x2 - x1 * y2) / (x2 - x1);
89 int xh = (x1 * y2 - y1 * x2 + h * (x2 - x1)) / (y2 - y1);
90 int yw = (y1 * x2 - x1 * y2 + w * (y2 - y1)) / (x2 - x1);
91
92 if (x1 < 0) {
93 x1 = 0;
94 y1 = y0;
95 }
96 if (x2 < 0) {
97 x2 = 0;
98 y2 = y0;
99 }
100 if (x1 > w) {
101 x1 = w;
102 y1 = yw;
103 }
104 if (x2 > w) {
105 x2 = w;
106 y2 = yw;
107 }
108 if ((y1 < 0 && y2 < 0) || (y1 > h && y2 > h)) {
109 return;
110 }
111
112 if (y1 < 0) {
113 x1 = x0;
114 y1 = 0;
115 }
116 if (y2 < 0) {
117 x2 = x0;
118 y2 = 0;
119 }
120
121 if (y1 > h) {
122 x1 = xh;
123 y1 = h;
124 }
125 if (y2 > h) {
126 x2 = xh;
127 y2 = h;
128 }
129 }
130 }
131
132 const bool inverse = ((std::abs(y2 - y1) - std::abs(x2 - x1)) > 0);
133 if (inverse) {
134 std::swap(x1, y1);
135 std::swap(x2, y2);
136 }
137
138 if (x1 > x2) {
139 std::swap(x1, x2);
140 std::swap(y1, y2);
141 }
142
143 const double dx = x2 - x1;
144 const double dy = static_cast<double>(std::abs(y2 - y1));
145
146 double error = dx / 2.0f;
147 const int ystep = (y1 < y2) ? 1 : -1;
148 int y0 = y1 - static_cast<int>(width) / 2;
149
150 for (int x = x1; x <= x2; x++) {
151 for (int i = 0; i < static_cast<int>(width); i++) {
152 int y = y0 + i;
153 if (y >= 0) {
154 if (inverse) {
155 if (y < w) {
156 canvas[x][y] = color;
157 }
158 }
159 else {
160 if (y < h) {
161 canvas[y][x] = color;
162 }
163 }
164 }
165 }
166
167 error -= dy;
168 if (error < 0) {
169 y0 += ystep;
170 error += dx;
171 }
172 }
173}
174
175template <class Type>
176void DrawCircle(vpImage<Type> &canvas, const vpImagePoint &center, int radius, const Type &color,
177 unsigned int width = 1)
178{
179 const size_t n = 8 * std::max(static_cast<size_t>(1), static_cast<size_t>(::pow(radius, 0.5)));
180 double px = 0, py = 0, da = 2 * M_PI / n;
181 for (size_t i = 0; i <= n; i++) {
182 double a = i * da;
183 double cx = radius * ::cos(a) + center.get_u();
184 double cy = radius * ::sin(a) + center.get_v();
185 if (i > 0) {
186 DrawLine(canvas, static_cast<int>(cx), static_cast<int>(cy), static_cast<int>(px), static_cast<int>(py), color,
187 width);
188 }
189 px = cx;
190 py = cy;
191 }
192}
193
194template <class Type> void DrawFilledRectangle(vpImage<Type> &canvas, vpRect rect, const Type &color)
195{
196 rect &= vpRect(0, 0, canvas.getWidth(), canvas.getHeight());
197 for (int row = static_cast<int>(rect.getTop()); row < static_cast<int>(rect.getBottom()); row++) {
198 Type *dst = canvas[row];
199 for (int col = static_cast<int>(rect.getLeft()); col < static_cast<int>(rect.getRight()); col++) {
200 dst[col] = color;
201 }
202 }
203}
204
205template <class Type>
206void DrawPolygon(vpImage<Type> &canvas, const std::vector<vpImagePoint> &polygon, const Type &color,
207 unsigned int width = 1, bool closed = true)
208{
209 if (closed) {
210 for (size_t i = 0; i < polygon.size(); i++) {
211 const vpImagePoint &p1 = (i ? polygon[i - 1] : polygon.back()), p2 = polygon[i];
212 DrawLine(canvas, static_cast<int>(p1.get_u()), static_cast<int>(p1.get_v()), static_cast<int>(p2.get_u()),
213 static_cast<int>(p2.get_v()), color, width);
214 }
215 }
216 else {
217 for (size_t i = 1; i < polygon.size(); i++) {
218 DrawLine(canvas, static_cast<int>(polygon[i - 1].get_u()), static_cast<int>(polygon[i - 1].get_v()),
219 static_cast<int>(polygon[i].get_u()), static_cast<int>(polygon[i].get_v()), color, width);
220 }
221 }
222}
223
224template <class Type>
225void DrawRectangle(vpImage<Type> &canvas, const vpRect &rect, const Type &color, unsigned int width = 1)
226{
227 DrawLine(canvas, static_cast<int>(rect.getLeft()), static_cast<int>(rect.getTop()), static_cast<int>(rect.getRight()),
228 static_cast<int>(rect.getTop()), color, width);
229 DrawLine(canvas, static_cast<int>(rect.getRight()), static_cast<int>(rect.getTop()),
230 static_cast<int>(rect.getRight()), static_cast<int>(rect.getBottom()), color, width);
231 DrawLine(canvas, static_cast<int>(rect.getRight()), static_cast<int>(rect.getBottom()),
232 static_cast<int>(rect.getLeft()), static_cast<int>(rect.getBottom()), color, width);
233 DrawLine(canvas, static_cast<int>(rect.getLeft()), static_cast<int>(rect.getBottom()),
234 static_cast<int>(rect.getLeft()), static_cast<int>(rect.getTop()), color, width);
235}
236} // namespace
237
250 unsigned char color, unsigned int w, unsigned int h, unsigned int thickness)
251{
252 double a = ip2.get_i() - ip1.get_i();
253 double b = ip2.get_j() - ip1.get_j();
254 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
255
256 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
257 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
258 // DisplayCrossLarge(i1,j1,3,col) ;
259 }
260 else {
261 a /= lg;
262 b /= lg;
263
264 vpImagePoint ip3;
265 ip3.set_i(ip2.get_i() - w * a);
266 ip3.set_j(ip2.get_j() - w * b);
267
268 vpImagePoint ip4;
269 ip4.set_i(ip3.get_i() - b * h);
270 ip4.set_j(ip3.get_j() + a * h);
271
272 if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
273 drawLine(I, ip2, ip4, color, thickness);
274 }
275
276 ip4.set_i(ip3.get_i() + b * h);
277 ip4.set_j(ip3.get_j() - a * h);
278
279 if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
280 drawLine(I, ip2, ip4, color, thickness);
281 }
282
283 drawLine(I, ip1, ip2, color, thickness);
284 }
285}
286
297void vpImageDraw::drawArrow(vpImage<vpRGBa> &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
298 unsigned int w, unsigned int h, unsigned int thickness)
299{
300 double a = ip2.get_i() - ip1.get_i();
301 double b = ip2.get_j() - ip1.get_j();
302 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
303
304 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
305 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
306 // DisplayCrossLarge(i1,j1,3,col) ;
307 }
308 else {
309 a /= lg;
310 b /= lg;
311
312 vpImagePoint ip3;
313 ip3.set_i(ip2.get_i() - w * a);
314 ip3.set_j(ip2.get_j() - w * b);
315
316 vpImagePoint ip4;
317 ip4.set_i(ip3.get_i() - b * h);
318 ip4.set_j(ip3.get_j() + a * h);
319
320 if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
321 drawLine(I, ip2, ip4, color, thickness);
322 }
323
324 ip4.set_i(ip3.get_i() + b * h);
325 ip4.set_j(ip3.get_j() - a * h);
326
327 if (lg > 2 * vpImagePoint::distance(ip2, ip4)) {
328 drawLine(I, ip2, ip4, color, thickness);
329 }
330
331 drawLine(I, ip1, ip2, color, thickness);
332 }
333}
334
343 unsigned char color, unsigned int thickness)
344{
345 DrawCircle(I, circle.getCenter(), static_cast<int>(circle.getRadius()), color, thickness);
346}
347
356void vpImageDraw::drawCircle(vpImage<unsigned char> &I, const vpImagePoint &center, unsigned int radius,
357 unsigned char color, unsigned int thickness)
358{
359 DrawCircle(I, center, static_cast<int>(radius), color, thickness);
360}
361
370 unsigned int thickness)
371{
372 DrawCircle(I, circle.getCenter(), static_cast<int>(circle.getRadius()), vpRGBa(color.R, color.G, color.B), thickness);
373}
374
383void vpImageDraw::drawCircle(vpImage<vpRGBa> &I, const vpImagePoint &center, unsigned int radius, const vpColor &color,
384 unsigned int thickness)
385{
386 DrawCircle(I, center, static_cast<int>(radius), vpRGBa(color.R, color.G, color.B), thickness);
387}
388
397void vpImageDraw::drawCross(vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned int size, unsigned char color,
398 unsigned int thickness)
399{
400 vpImagePoint top, bottom, left, right;
401 top.set_i(ip.get_i() - size / 2);
402 top.set_j(ip.get_j());
403 bottom.set_i(ip.get_i() + size / 2);
404 bottom.set_j(ip.get_j());
405 left.set_i(ip.get_i());
406 left.set_j(ip.get_j() - size / 2);
407 right.set_i(ip.get_i());
408 right.set_j(ip.get_j() + size / 2);
409 drawLine(I, top, bottom, color, thickness);
410 drawLine(I, left, right, color, thickness);
411}
412
421void vpImageDraw::drawCross(vpImage<vpRGBa> &I, const vpImagePoint &ip, unsigned int size, const vpColor &color,
422 unsigned int thickness)
423{
424 vpImagePoint top, bottom, left, right;
425 top.set_i(ip.get_i() - size / 2);
426 top.set_j(ip.get_j());
427 bottom.set_i(ip.get_i() + size / 2);
428 bottom.set_j(ip.get_j());
429 left.set_i(ip.get_i());
430 left.set_j(ip.get_j() - size / 2);
431 right.set_i(ip.get_i());
432 right.set_j(ip.get_j() + size / 2);
433 drawLine(I, top, bottom, color, thickness);
434 drawLine(I, left, right, color, thickness);
435}
436
446 unsigned char color, unsigned int thickness)
447{
448 vpImagePoint ip1_ = ip1;
449 vpImagePoint ip2_ = ip2;
450
451 double size = 10;
452 double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
453 bool vertical_line = static_cast<int>(ip2_.get_j()) == static_cast<int>(ip1_.get_j());
454 if (vertical_line) {
455 if (ip2_.get_i() < ip1_.get_i()) {
456 std::swap(ip1_, ip2_);
457 }
458 }
459 else if (ip2_.get_j() < ip1_.get_j()) {
460 std::swap(ip1_, ip2_);
461 }
462
463 double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
464 double deltaj = size / length * diff_j;
465 double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
466 double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
467 double orig = ip1_.get_i() - slope * ip1_.get_j();
468
469 if (vertical_line) {
470 for (unsigned int i = static_cast<unsigned int>(ip1_.get_i()); i < ip2_.get_i();
471 i += static_cast<unsigned int>(2 * deltai)) {
472 double j = ip1_.get_j();
473 drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
474 }
475 }
476 else {
477 for (unsigned int j = static_cast<unsigned int>(ip1_.get_j()); j < ip2_.get_j();
478 j += static_cast<unsigned int>(2 * deltaj)) {
479 double i = slope * j + orig;
480 drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
481 }
482 }
483}
484
494 const vpColor &color, unsigned int thickness)
495{
496 vpImagePoint ip1_ = ip1;
497 vpImagePoint ip2_ = ip2;
498
499 double size = 10;
500 double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
501 bool vertical_line = static_cast<int>(ip2_.get_j()) == static_cast<int>(ip1_.get_j());
502 if (vertical_line) {
503 if (ip2_.get_i() < ip1_.get_i()) {
504 std::swap(ip1_, ip2_);
505 }
506 }
507 else if (ip2_.get_j() < ip1_.get_j()) {
508 std::swap(ip1_, ip2_);
509 }
510
511 double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
512 double deltaj = size / length * diff_j;
513 double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
514 double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
515 double orig = ip1_.get_i() - slope * ip1_.get_j();
516
517 if (vertical_line) {
518 for (unsigned int i = static_cast<unsigned int>(ip1_.get_i()); i < ip2_.get_i();
519 i += static_cast<unsigned int>(2 * deltai)) {
520 double j = ip1_.get_j();
521 drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
522 }
523 }
524 else {
525 for (unsigned int j = static_cast<unsigned int>(ip1_.get_j()); j < ip2_.get_j();
526 j += static_cast<unsigned int>(2 * deltaj)) {
527 double i = slope * j + orig;
528 drawLine(I, vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
529 }
530 }
531}
532
578void vpImageDraw::drawEllipse(vpImage<unsigned char> &I, const vpImagePoint &center, double coef1, double coef2,
579 double coef3, bool use_normalized_centered_moments, unsigned char color,
580 double smallalpha, double highalpha, unsigned int thickness)
581{
582 double a = 0., b = 0., e = 0.;
583
584 if (use_normalized_centered_moments) {
585 // Chaumette, Image Moments: A General and Useful Set of Features for Visual Servoing, TRO 2004, eq 24
586 // Similar code as in function vpMeEllipse::computeAbeFromNij() in vpMeEllipse.cpp
587 double n20_p = coef1;
588 double n11_p = coef2;
589 double n02_p = coef3;
590 double num = n20_p - n02_p;
591 double d = num * num + 4.0 * n11_p * n11_p; // always >= 0
592
593 if (d <= std::numeric_limits<double>::epsilon()) { // circle
594 e = 0.0; // case n20 = n02 and n11 = 0 : circle, e undefined
595 a = b = 2.0 * sqrt(n20_p);
596 }
597 else { // real ellipse
598 e = atan2(2.0 * n11_p, num) / 2.0; // e in [-Pi/2 ; Pi/2]
599 d = sqrt(d); // d in sqrt always >= 0
600 num = n20_p + n02_p;
601 a = sqrt(2.0 * (num + d)); // term in sqrt always > 0
602 b = sqrt(2.0 * (num - d)); // term in sqrt always > 0
603 }
604 }
605 else {
606 a = coef1;
607 b = coef2;
608 e = coef3;
609 }
610
611 // For all what follows similar code as in function vpMeEllipse::display() in vpMeEllipse.cpp
612
613 // Approximation of the circumference of an ellipse:
614 // [Ramanujan, S., "Modular Equations and Approximations to ,"
615 // Quart. J. Pure. Appl. Math., vol. 45 (1913-1914), pp. 350-372]
616 double angle = highalpha - smallalpha;
617
618 double t = (a - b) / (a + b);
619 t *= t; // t^2
620 double circumference = (angle / 2.0) * (a + b) * (1.0 + 3.0 * t / (10.0 + sqrt(4.0 - 3.0 * t)));
621 unsigned int nbpoints = static_cast<unsigned int>(floor(circumference / 20));
622 if (nbpoints < 10) {
623 nbpoints = 10;
624 }
625 double incr = angle / nbpoints; // angle increment
626
627 double u0 = center.get_u();
628 double v0 = center.get_v();
629 double cose = cos(e);
630 double sine = sin(e);
631
632 double u = a * cos(smallalpha); // equation of an ellipse
633 double v = b * sin(smallalpha); // equation of an ellipse
634 angle = smallalpha;
635 // (i1,j1) are the coordinates on the origin centered ellipse ;
636 // a rotation by "e" and a translation by (xci,jc) are done
637 // to get the coordinates of the point on the shifted ellipse
638 vpImagePoint iP11;
639 iP11.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
640
641 // display the arc of the ellipse by successive small segments
642 for (unsigned int i = 0; i < nbpoints; i++) {
643 angle += incr;
644 // Two concentric circles method used
645 u = a * cos(angle);
646 v = b * sin(angle);
647 // to get the coordinates of the point on the shifted ellipse
648 vpImagePoint iP22;
649 iP22.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
650
651 drawLine(I, iP11, iP22, color, thickness);
652
653 iP11 = iP22;
654 }
655}
656
702void vpImageDraw::drawEllipse(vpImage<vpRGBa> &I, const vpImagePoint &center, double coef1, double coef2, double coef3,
703 bool use_normalized_centered_moments, const vpColor &color, double smallalpha,
704 double highalpha, unsigned int thickness)
705{
706 double a = 0., b = 0., e = 0.;
707
708 if (use_normalized_centered_moments) {
709 // Chaumette, Image Moments: A General and Useful Set of Features for Visual Servoing, TRO 2004, eq 24
710 // Similar code as in function vpMeEllipse::computeAbeFromNij() in vpMeEllipse.cpp
711 double n20_p = coef1;
712 double n11_p = coef2;
713 double n02_p = coef3;
714 double num = n20_p - n02_p;
715 double d = num * num + 4.0 * n11_p * n11_p; // always >= 0
716
717 if (d <= std::numeric_limits<double>::epsilon()) { // circle
718 e = 0.0; // case n20 = n02 and n11 = 0 : circle, e undefined
719 a = b = 2.0 * sqrt(n20_p);
720 }
721 else { // real ellipse
722 e = atan2(2.0 * n11_p, num) / 2.0; // e in [-Pi/2 ; Pi/2]
723 d = sqrt(d); // d in sqrt always >= 0
724 num = n20_p + n02_p;
725 a = sqrt(2.0 * (num + d)); // term in sqrt always > 0
726 b = sqrt(2.0 * (num - d)); // term in sqrt always > 0
727 }
728 }
729 else {
730 a = coef1;
731 b = coef2;
732 e = coef3;
733 }
734
735 // For all what follows similar code as in function vpMeEllipse::display() in vpMeEllipse.cpp
736
737 // Approximation of the circumference of an ellipse:
738 // [Ramanujan, S., "Modular Equations and Approximations to ,"
739 // Quart. J. Pure. Appl. Math., vol. 45 (1913-1914), pp. 350-372]
740 double angle = highalpha - smallalpha;
741
742 double t = (a - b) / (a + b);
743 t *= t; // t^2
744 double circumference = (angle / 2.0) * (a + b) * (1.0 + 3.0 * t / (10.0 + sqrt(4.0 - 3.0 * t)));
745 unsigned int nbpoints = static_cast<unsigned int>(floor(circumference / 20));
746 if (nbpoints < 10) {
747 nbpoints = 10;
748 }
749 double incr = angle / nbpoints; // angle increment
750
751 double u0 = center.get_u();
752 double v0 = center.get_v();
753 double cose = cos(e);
754 double sine = sin(e);
755
756 double u = a * cos(smallalpha); // equation of an ellipse
757 double v = b * sin(smallalpha); // equation of an ellipse
758 angle = smallalpha;
759 // (i1,j1) are the coordinates on the origin centered ellipse ;
760 // a rotation by "e" and a translation by (xci,jc) are done
761 // to get the coordinates of the point on the shifted ellipse
762 vpImagePoint iP11;
763 iP11.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
764
765 // display the arc of the ellipse by successive small segments
766 for (unsigned int i = 0; i < nbpoints; i++) {
767 angle += incr;
768 // Two concentric circles method used
769 u = a * cos(angle);
770 v = b * sin(angle);
771 // to get the coordinates of the point on the shifted ellipse
772 vpImagePoint iP22;
773 iP22.set_uv(u0 + cose * u - sine * v, v0 + sine * u + cose * v);
774
775 drawLine(I, iP11, iP22, color, thickness);
776
777 iP11 = iP22;
778 }
779}
780
797 double size, unsigned char color, unsigned int thickness, const vpImagePoint &offset)
798{
799 vpPoint o(0.0, 0.0, 0.0);
800 vpPoint x(size, 0.0, 0.0);
801 vpPoint y(0.0, size, 0.0);
802 vpPoint z(0.0, 0.0, size);
803
804 o.track(cMo);
805 x.track(cMo);
806 y.track(cMo);
807 z.track(cMo);
808
809 vpImagePoint ipo, ip1;
810
811 vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
812
813 vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
814 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
815
816 vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
817 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
818
819 vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
820 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
821}
822
839 double size, const vpColor &color, unsigned int thickness, const vpImagePoint &offset)
840{
841 vpPoint o(0.0, 0.0, 0.0);
842 vpPoint x(size, 0.0, 0.0);
843 vpPoint y(0.0, size, 0.0);
844 vpPoint z(0.0, 0.0, size);
845
846 o.track(cMo);
847 x.track(cMo);
848 y.track(cMo);
849 z.track(cMo);
850
851 vpImagePoint ipo, ip1;
852
853 if (color == vpColor::none) {
854 vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
855
856 vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
857 drawArrow(I, ipo + offset, ip1 + offset, vpColor::red, 4 * thickness, 2 * thickness, thickness);
858
859 vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
860 drawArrow(I, ipo + offset, ip1 + offset, vpColor::green, 4 * thickness, 2 * thickness, thickness);
861
862 vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
863 drawArrow(I, ipo + offset, ip1 + offset, vpColor::blue, 4 * thickness, 2 * thickness, thickness);
864 }
865 else {
866 vpMeterPixelConversion::convertPoint(cam, o.p[0], o.p[1], ipo);
867
868 vpMeterPixelConversion::convertPoint(cam, x.p[0], x.p[1], ip1);
869 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
870
871 vpMeterPixelConversion::convertPoint(cam, y.p[0], y.p[1], ip1);
872 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
873
874 vpMeterPixelConversion::convertPoint(cam, z.p[0], z.p[1], ip1);
875 drawArrow(I, ipo + offset, ip1 + offset, color, 4 * thickness, 2 * thickness, thickness);
876 }
877}
878
888 unsigned char color, unsigned int thickness)
889{
890 DrawLine(I, static_cast<int>(ip1.get_u()), static_cast<int>(ip1.get_v()), static_cast<int>(ip2.get_u()),
891 static_cast<int>(ip2.get_v()), color, thickness);
892}
893
902void vpImageDraw::drawLine(vpImage<vpRGBa> &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
903 unsigned int thickness)
904{
905 DrawLine(I, static_cast<int>(ip1.get_u()), static_cast<int>(ip1.get_v()), static_cast<int>(ip2.get_u()),
906 static_cast<int>(ip2.get_v()), vpRGBa(color.R, color.G, color.B), thickness);
907}
908
916void vpImageDraw::drawPoint(vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned char color,
917 unsigned int thickness)
918{
919 drawRectangle(I, vpRect(ip, thickness, thickness), color, true);
920}
921
929void vpImageDraw::drawPoint(vpImage<vpRGBa> &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
930{
931 drawRectangle(I, vpRect(ip, thickness, thickness), color, true);
932}
933
942void vpImageDraw::drawPolygon(vpImage<unsigned char> &I, const std::vector<vpImagePoint> &vip, unsigned char color,
943 unsigned int thickness, bool closed)
944{
945 DrawPolygon(I, vip, color, thickness, closed);
946}
947
956void vpImageDraw::drawPolygon(vpImage<vpRGBa> &I, const std::vector<vpImagePoint> &vip, const vpColor &color,
957 unsigned int thickness, bool closed)
958{
959 DrawPolygon(I, vip, vpRGBa(color.R, color.G, color.B), thickness, closed);
960}
961
974void vpImageDraw::drawRectangle(vpImage<unsigned char> &I, const vpRect &rectangle, unsigned char color, bool fill,
975 unsigned int thickness)
976{
977 if (fill) {
978 DrawFilledRectangle(I, rectangle, color);
979 }
980 else {
981 DrawRectangle(I, rectangle, color, thickness);
982 }
983}
984
997void vpImageDraw::drawRectangle(vpImage<vpRGBa> &I, const vpRect &rectangle, const vpColor &color, bool fill,
998 unsigned int thickness)
999{
1000 if (fill) {
1001 DrawFilledRectangle(I, rectangle, vpRGBa(color.R, color.G, color.B));
1002 }
1003 else {
1004 DrawRectangle(I, rectangle, vpRGBa(color.R, color.G, color.B), thickness);
1005 }
1006}
1007END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static const vpColor red
Definition vpColor.h:198
static const vpColor none
Definition vpColor.h:210
static const vpColor blue
Definition vpColor.h:204
static const vpColor green
Definition vpColor.h:201
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines a 2D circle in an image.
float getRadius() const
vpImagePoint getCenter() const
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 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 drawRectangle(vpImage< unsigned char > &I, const vpRect &rectangle, unsigned char color, bool fill=false, unsigned int thickness=1)
static void drawCircle(vpImage< unsigned char > &I, const vpImageCircle &circle, unsigned char color, unsigned int thickness=1)
static void drawLine(vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, unsigned char color, unsigned int thickness=1)
static void drawPoint(vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned char color, unsigned int thickness=1)
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))
static void drawPolygon(vpImage< unsigned char > &I, const std::vector< vpImagePoint > &vip, unsigned char color, unsigned int thickness=1, bool closed=true)
static void drawCross(vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, unsigned char color, unsigned int thickness=1)
static void drawDottedLine(vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, unsigned char color, unsigned int thickness=1)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_j(double jj)
double get_j() const
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
double get_u() const
void set_uv(double u, double v)
double get_i() const
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getHeight() const
Definition vpImage.h:181
static double sqr(double x)
Definition vpMath.h:203
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition vpPoint.h:79
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
vpColVector p
Definition vpTracker.h:69