Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpDisplayOpenCV.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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 * Image display.
33 *
34*****************************************************************************/
35
41#include <visp3/core/vpConfig.h>
42
43#if defined(HAVE_OPENCV_HIGHGUI)
44
45#include <cmath> // std::fabs
46#include <iostream>
47#include <limits> // numeric_limits
48#include <stdio.h>
49#include <stdlib.h>
50
51// Display stuff
52#include <visp3/core/vpDisplay.h>
53#include <visp3/core/vpImageTools.h>
54#include <visp3/core/vpIoTools.h>
55#include <visp3/core/vpMath.h>
56#include <visp3/gui/vpDisplayOpenCV.h>
57
58// debug / exception
59#include <visp3/core/vpDebug.h>
60#include <visp3/core/vpDisplayException.h>
61
62#include <opencv2/core/core_c.h> // for CV_FILLED versus cv::FILLED
63
64#if defined(HAVE_OPENCV_IMGPROC)
65#include <opencv2/imgproc/imgproc.hpp>
66#endif
67
68#ifndef CV_RGB
69#define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
70#endif
71
72#ifdef VISP_HAVE_X11
73#include <visp3/gui/vpDisplayX.h> // to get screen resolution
74#elif defined(_WIN32)
75#include <windows.h>
76#endif
77
78std::vector<std::string> vpDisplayOpenCV::m_listTitles = std::vector<std::string>();
79unsigned int vpDisplayOpenCV::m_nbWindows = 0;
80
103 : vpDisplay(),
104#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
105 m_background(NULL), col(NULL), cvcolor(), font(NULL),
106#else
107 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
108#endif
109 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
110 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
111 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
112 y_rbuttonup(0), rbuttonup(false)
113{
114 setScale(scaleType, I.getWidth(), I.getHeight());
115 init(I);
116}
117
141vpDisplayOpenCV::vpDisplayOpenCV(vpImage<unsigned char> &I, int x, int y, const std::string &title,
142 vpScaleType scaleType)
143 : vpDisplay(),
144#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
145 m_background(NULL), col(NULL), cvcolor(), font(NULL),
146#else
147 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
148#endif
149 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
150 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
151 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
152 y_rbuttonup(0), rbuttonup(false)
153{
154 setScale(scaleType, I.getWidth(), I.getHeight());
155 init(I, x, y, title);
156}
157
177 :
178#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
179 m_background(NULL), col(NULL), cvcolor(), font(NULL),
180#else
181 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
182#endif
183 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
184 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
185 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
186 y_rbuttonup(0), rbuttonup(false)
187{
188 setScale(scaleType, I.getWidth(), I.getHeight());
189 init(I);
190}
191
212vpDisplayOpenCV::vpDisplayOpenCV(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
213 :
214#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
215 m_background(NULL), col(NULL), cvcolor(), font(NULL),
216#else
217 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
218#endif
219 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
220 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
221 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
222 y_rbuttonup(0), rbuttonup(false)
223{
224 setScale(scaleType, I.getWidth(), I.getHeight());
225 init(I, x, y, title);
226}
227
250vpDisplayOpenCV::vpDisplayOpenCV(int x, int y, const std::string &title)
251 :
252#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
253 m_background(NULL), col(NULL), cvcolor(), font(NULL),
254#else
255 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
256#endif
257 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
258 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
259 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
260 y_rbuttonup(0), rbuttonup(false)
261{
264
265 if (!title.empty()) {
266 m_title = title;
267 } else {
268 std::ostringstream s;
269 s << m_nbWindows++;
270 m_title = std::string("Window ") + s.str();
271 }
272
273 bool isInList;
274 do {
275 isInList = false;
276 for (size_t i = 0; i < m_listTitles.size(); i++) {
277 if (m_listTitles[i] == m_title) {
278 std::ostringstream s;
279 s << m_nbWindows++;
280 m_title = std::string("Window ") + s.str();
281 isInList = true;
282 break;
283 }
284 }
285 } while (isInList);
286
287 m_listTitles.push_back(m_title);
288}
289
310 :
311#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
312 m_background(NULL), col(NULL), cvcolor(), font(NULL),
313#else
314 m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
315#endif
316 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
317 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
318 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
319 y_rbuttonup(0), rbuttonup(false)
320{
321}
322
327{
328 closeDisplay();
329#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
330 cvReleaseImage(&m_background);
331#endif
332}
333
342void vpDisplayOpenCV::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
343{
344 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
345 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
346 }
348 init(I.getWidth(), I.getHeight(), x, y, title);
349 I.display = this;
351}
352
362void vpDisplayOpenCV::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
363{
364 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
365 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
366 }
367
369 init(I.getWidth(), I.getHeight(), x, y, title);
370 I.display = this;
372}
373
384void vpDisplayOpenCV::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
385{
386 setScale(m_scaleType, w, h);
387
388 this->m_width = w / m_scale;
389 this->m_height = h / m_scale;
390
391 if (x != -1)
392 this->m_windowXPosition = x;
393 if (y != -1)
394 this->m_windowYPosition = y;
395#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
396 int flags = CV_WINDOW_AUTOSIZE;
397#else
398 int flags = cv::WINDOW_AUTOSIZE;
399#endif
400
401 if (m_title.empty()) {
402 if (!title.empty()) {
403 m_title = std::string(title);
404 } else {
405
406 std::ostringstream s;
407 s << m_nbWindows++;
408 m_title = std::string("Window ") + s.str();
409 }
410
411 bool isInList;
412 do {
413 isInList = false;
414 for (size_t i = 0; i < m_listTitles.size(); i++) {
415 if (m_listTitles[i] == m_title) {
416 std::ostringstream s;
417 s << m_nbWindows++;
418 m_title = std::string("Window ") + s.str();
419 isInList = true;
420 break;
421 }
422 }
423 } while (isInList);
424
425 m_listTitles.push_back(m_title);
426 }
427
428/* Create the window*/
429#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
430 if (cvNamedWindow(this->m_title.c_str(), flags) < 0) {
431 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV was not built with a display device"));
432 }
433#else
434 cv::namedWindow(this->m_title, flags);
435#endif
436#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
437 cvMoveWindow(this->m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
438#else
439 cv::moveWindow(this->m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
440#endif
441 move = false;
442 lbuttondown = false;
443 mbuttondown = false;
444 rbuttondown = false;
445 lbuttonup = false;
446 mbuttonup = false;
447 rbuttonup = false;
448#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
449 cvSetMouseCallback(this->m_title.c_str(), on_mouse, this);
450 col = new CvScalar[vpColor::id_unknown];
451#else
452 cv::setMouseCallback(this->m_title, on_mouse, this);
453 col = new cv::Scalar[vpColor::id_unknown];
454#endif
455
456 /* Create color */
457 vpColor pcolor; // Predefined colors
458 pcolor = vpColor::lightBlue;
459 col[vpColor::id_lightBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
460 pcolor = vpColor::blue;
461 col[vpColor::id_blue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
462 pcolor = vpColor::darkBlue;
463 col[vpColor::id_darkBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
464 pcolor = vpColor::lightRed;
465 col[vpColor::id_lightRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
466 pcolor = vpColor::red;
467 col[vpColor::id_red] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
468 pcolor = vpColor::darkRed;
469 col[vpColor::id_darkRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
470 pcolor = vpColor::lightGreen;
471 col[vpColor::id_lightGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
472 pcolor = vpColor::green;
473 col[vpColor::id_green] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
474 pcolor = vpColor::darkGreen;
475 col[vpColor::id_darkGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
476 pcolor = vpColor::yellow;
477 col[vpColor::id_yellow] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
478 pcolor = vpColor::cyan;
479 col[vpColor::id_cyan] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
480 pcolor = vpColor::orange;
481 col[vpColor::id_orange] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
482 pcolor = vpColor::purple;
483 col[vpColor::id_purple] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
484 pcolor = vpColor::white;
485 col[vpColor::id_white] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
486 pcolor = vpColor::black;
487 col[vpColor::id_black] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
488 pcolor = vpColor::lightGray;
489 col[vpColor::id_lightGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
490 pcolor = vpColor::gray;
491 col[vpColor::id_gray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
492 pcolor = vpColor::darkGray;
493 col[vpColor::id_darkGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
494
495#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
496 font = new CvFont;
497 cvInitFont(font, CV_FONT_HERSHEY_PLAIN, 0.70f, 0.70f);
498 CvSize fontSize;
499 int baseline;
500 cvGetTextSize("A", font, &fontSize, &baseline);
501#else
502 int thickness = 1;
503 cv::Size fontSize;
504 int baseline;
505 fontSize = cv::getTextSize("A", font, fontScale, thickness, &baseline);
506#endif
507
508 fontHeight = fontSize.height + baseline;
510}
511
527void vpDisplayOpenCV::setFont(const std::string & /* font */) { vpERROR_TRACE("Not yet implemented"); }
528
536void vpDisplayOpenCV::setTitle(const std::string & /* title */)
537{
538 // static bool warn_displayed = false;
539 // if (! warn_displayed) {
540 // vpTRACE("Not implemented");
541 // warn_displayed = true;
542 // }
543}
544
555{
557 this->m_windowXPosition = winx;
558 this->m_windowYPosition = winy;
559#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
560 cvMoveWindow(this->m_title.c_str(), winx, winy);
561#else
562 cv::moveWindow(this->m_title.c_str(), winx, winy);
563#endif
564 } else {
565 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
566 }
567}
580{
582#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
583 int depth = 8;
584 int channels = 3;
585 CvSize size = cvSize((int)this->m_width, (int)this->m_height);
586 if (m_background != NULL) {
587 if (m_background->nChannels != channels || m_background->depth != depth ||
588 m_background->height != (int)m_height || m_background->width != (int)m_width) {
589 if (m_background->nChannels != 0)
590 cvReleaseImage(&m_background);
591 m_background = cvCreateImage(size, depth, channels);
592 }
593 } else {
594 m_background = cvCreateImage(size, depth, channels);
595 }
596
597 if (m_scale == 1) {
598 for (unsigned int i = 0; i < m_height; i++) {
599 unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
600 for (unsigned int j = 0; j < m_width; j++) {
601 unsigned char val = I[i][j];
602 *(dst_24++) = val;
603 *(dst_24++) = val;
604 *(dst_24++) = val;
605 }
606 }
607 } else {
608 for (unsigned int i = 0; i < m_height; i++) {
609 unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
610 for (unsigned int j = 0; j < m_width; j++) {
611 unsigned char val = I[i * m_scale][j * m_scale];
612 *(dst_24++) = val;
613 *(dst_24++) = val;
614 *(dst_24++) = val;
615 }
616 }
617 }
618
619#else
620 int depth = CV_8U;
621 int channels = 3;
622 cv::Size size((int)m_width, (int)m_height);
623 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
624 m_background.cols != (int)m_width) {
625 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
626 }
627
628 if (m_scale == 1) {
629 for (unsigned int i = 0; i < m_height; i++) {
630 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
631 for (unsigned int j = 0; j < m_width; j++) {
632 unsigned char val = I[i][j];
633 *(dst_24++) = val;
634 *(dst_24++) = val;
635 *(dst_24++) = val;
636 }
637 }
638 } else {
639 for (unsigned int i = 0; i < m_height; i++) {
640 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
641 for (unsigned int j = 0; j < m_width; j++) {
642 unsigned char val = I[i * m_scale][j * m_scale];
643 *(dst_24++) = val;
644 *(dst_24++) = val;
645 *(dst_24++) = val;
646 }
647 }
648 }
649#endif
650
651 } else {
652 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
653 }
654}
655
672 unsigned int h)
673{
675#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
676 int depth = 8;
677 int channels = 3;
678 CvSize size = cvSize((int)this->m_width, (int)this->m_height);
679 if (m_background != NULL) {
680 if (m_background->nChannels != channels || m_background->depth != depth ||
681 m_background->height != (int)m_height || m_background->width != (int)m_width) {
682 if (m_background->nChannels != 0)
683 cvReleaseImage(&m_background);
684 m_background = cvCreateImage(size, depth, channels);
685 }
686 } else {
687 m_background = cvCreateImage(size, depth, channels);
688 }
689
690 if (m_scale == 1) {
691 unsigned int i_min = (unsigned int)iP.get_i();
692 unsigned int j_min = (unsigned int)iP.get_j();
693 unsigned int i_max = (std::min)(i_min + h, m_height);
694 unsigned int j_max = (std::min)(j_min + w, m_width);
695 for (unsigned int i = i_min; i < i_max; i++) {
696 unsigned char *dst_24 =
697 (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
698 for (unsigned int j = j_min; j < j_max; j++) {
699 unsigned char val = I[i][j];
700 *(dst_24++) = val;
701 *(dst_24++) = val;
702 *(dst_24++) = val;
703 }
704 }
705 } else {
706 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
707 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
708 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
709 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
710 for (int i = i_min; i < i_max; i++) {
711 unsigned char *dst_24 =
712 (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
713 for (int j = j_min; j < j_max; j++) {
714 unsigned char val = I[i * m_scale][j * m_scale];
715 *(dst_24++) = val;
716 *(dst_24++) = val;
717 *(dst_24++) = val;
718 }
719 }
720 }
721
722#else
723 int depth = CV_8U;
724 int channels = 3;
725 cv::Size size((int)m_width, (int)m_height);
726 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
727 m_background.cols != (int)m_width) {
728 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
729 }
730
731 if (m_scale == 1) {
732 unsigned int i_min = (unsigned int)iP.get_i();
733 unsigned int j_min = (unsigned int)iP.get_j();
734 unsigned int i_max = (std::min)(i_min + h, m_height);
735 unsigned int j_max = (std::min)(j_min + w, m_width);
736 for (unsigned int i = i_min; i < i_max; i++) {
737 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
738 for (unsigned int j = j_min; j < j_max; j++) {
739 unsigned char val = I[i][j];
740 *(dst_24++) = val;
741 *(dst_24++) = val;
742 *(dst_24++) = val;
743 }
744 }
745 } else {
746 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
747 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
748 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
749 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
750 for (int i = i_min; i < i_max; i++) {
751 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
752 for (int j = j_min; j < j_max; j++) {
753 unsigned char val = I[i * m_scale][j * m_scale];
754 *(dst_24++) = val;
755 *(dst_24++) = val;
756 *(dst_24++) = val;
757 }
758 }
759 }
760#endif
761 } else {
762 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
763 }
764}
765
778{
779
781#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
782 int depth = 8;
783 int channels = 3;
784 CvSize size = cvSize((int)this->m_width, (int)this->m_height);
785 if (m_background != NULL) {
786 if (m_background->nChannels != channels || m_background->depth != depth ||
787 m_background->height != (int)m_height || m_background->width != (int)m_width) {
788 if (m_background->nChannels != 0)
789 cvReleaseImage(&m_background);
790 m_background = cvCreateImage(size, depth, channels);
791 }
792 } else {
793 m_background = cvCreateImage(size, depth, channels);
794 }
795
796 if (m_scale == 1) {
797 for (unsigned int i = 0; i < m_height; i++) {
798 unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
799 for (unsigned int j = 0; j < m_width; j++) {
800 vpRGBa val = I[i][j];
801 *(dst_24++) = val.B;
802 *(dst_24++) = val.G;
803 *(dst_24++) = val.R;
804 }
805 }
806 } else {
807 for (unsigned int i = 0; i < m_height; i++) {
808 unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
809 for (unsigned int j = 0; j < m_width; j++) {
810 vpRGBa val = I[i * m_scale][j * m_scale];
811 *(dst_24++) = val.B;
812 *(dst_24++) = val.G;
813 *(dst_24++) = val.R;
814 }
815 }
816 }
817#else
818 int depth = CV_8U;
819 int channels = 3;
820 cv::Size size((int)this->m_width, (int)this->m_height);
821 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
822 m_background.cols != (int)m_width) {
823 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
824 }
825
826 if (m_scale == 1) {
827 for (unsigned int i = 0; i < m_height; i++) {
828 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
829 for (unsigned int j = 0; j < m_width; j++) {
830 vpRGBa val = I[i][j];
831 *(dst_24++) = val.B;
832 *(dst_24++) = val.G;
833 *(dst_24++) = val.R;
834 }
835 }
836 } else {
837 for (unsigned int i = 0; i < m_height; i++) {
838 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
839 for (unsigned int j = 0; j < m_width; j++) {
840 vpRGBa val = I[i * m_scale][j * m_scale];
841 *(dst_24++) = val.B;
842 *(dst_24++) = val.G;
843 *(dst_24++) = val.R;
844 }
845 }
846 }
847#endif
848 } else {
849 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
850 }
851}
852
868void vpDisplayOpenCV::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
869{
871#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
872 int depth = 8;
873 int channels = 3;
874 CvSize size = cvSize((int)this->m_width, (int)this->m_height);
875 if (m_background != NULL) {
876 if (m_background->nChannels != channels || m_background->depth != depth ||
877 m_background->height != (int)m_height || m_background->width != (int)m_width) {
878 if (m_background->nChannels != 0)
879 cvReleaseImage(&m_background);
880 m_background = cvCreateImage(size, depth, channels);
881 }
882 } else {
883 m_background = cvCreateImage(size, depth, channels);
884 }
885
886 if (m_scale == 1) {
887 unsigned int i_min = (unsigned int)iP.get_i();
888 unsigned int j_min = (unsigned int)iP.get_j();
889 unsigned int i_max = (std::min)(i_min + h, m_height);
890 unsigned int j_max = (std::min)(j_min + w, m_width);
891 for (unsigned int i = i_min; i < i_max; i++) {
892 unsigned char *dst_24 =
893 (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
894 for (unsigned int j = j_min; j < j_max; j++) {
895 vpRGBa val = I[i][j];
896 *(dst_24++) = val.B;
897 *(dst_24++) = val.G;
898 *(dst_24++) = val.R;
899 }
900 }
901 } else {
902 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
903 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
904 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
905 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
906 for (int i = i_min; i < i_max; i++) {
907 unsigned char *dst_24 =
908 (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
909 for (int j = j_min; j < j_max; j++) {
910 vpRGBa val = I[i * m_scale][j * m_scale];
911 *(dst_24++) = val.B;
912 *(dst_24++) = val.G;
913 *(dst_24++) = val.R;
914 }
915 }
916 }
917#else
918 int depth = CV_8U;
919 int channels = 3;
920 cv::Size size((int)this->m_width, (int)this->m_height);
921 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
922 m_background.cols != (int)m_width) {
923 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
924 }
925
926 if (m_scale == 1) {
927 unsigned int i_min = (unsigned int)iP.get_i();
928 unsigned int j_min = (unsigned int)iP.get_j();
929 unsigned int i_max = (std::min)(i_min + h, m_height);
930 unsigned int j_max = (std::min)(j_min + w, m_width);
931 for (unsigned int i = i_min; i < i_max; i++) {
932 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
933 for (unsigned int j = j_min; j < j_max; j++) {
934 vpRGBa val = I[i][j];
935 *(dst_24++) = val.B;
936 *(dst_24++) = val.G;
937 *(dst_24++) = val.R;
938 }
939 }
940 } else {
941 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
942 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
943 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
944 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
945 for (int i = i_min; i < i_max; i++) {
946 unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
947 for (int j = j_min; j < j_max; j++) {
948 vpRGBa val = I[i * m_scale][j * m_scale];
949 *(dst_24++) = val.B;
950 *(dst_24++) = val.G;
951 *(dst_24++) = val.R;
952 }
953 }
954 }
955#endif
956 } else {
957 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
958 }
959}
960
966void vpDisplayOpenCV::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
967
976{
977 if (col != NULL) {
978 delete[] col;
979 col = NULL;
980 }
981#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
982 if (font != NULL) {
983 delete font;
984 font = NULL;
985 }
986#endif
988#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
989 cvDestroyWindow(this->m_title.c_str());
990#else
991 cv::destroyWindow(this->m_title);
992#endif
993
994 for (size_t i = 0; i < m_listTitles.size(); i++) {
995 if (m_title == m_listTitles[i]) {
996 m_listTitles.erase(m_listTitles.begin() + (long int)i);
997 break;
998 }
999 }
1000
1001 m_title.clear();
1002
1004 }
1005}
1006
1013{
1015#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1016 cvShowImage(this->m_title.c_str(), m_background);
1017 cvWaitKey(5);
1018#else
1019 cv::imshow(this->m_title, m_background);
1020 cv::waitKey(5);
1021#endif
1022 } else {
1023 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1024 }
1025}
1026
1032void vpDisplayOpenCV::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1033 const unsigned int /*height*/)
1034{
1036#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1037 cvShowImage(this->m_title.c_str(), m_background);
1038 cvWaitKey(5);
1039#else
1040 cv::imshow(this->m_title.c_str(), m_background);
1041 cv::waitKey(5);
1042#endif
1043 } else {
1044 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1045 }
1046}
1047
1052{
1053 static bool warn_displayed = false;
1054 if (!warn_displayed) {
1055 vpTRACE("Not implemented");
1056 warn_displayed = true;
1057 }
1058}
1059
1067void vpDisplayOpenCV::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1068 unsigned int w, unsigned int h, unsigned int thickness)
1069{
1071 double a = ip2.get_i() - ip1.get_i();
1072 double b = ip2.get_j() - ip1.get_j();
1073 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1074
1075 // if ((a==0)&&(b==0))
1076 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
1077 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
1078 // DisplayCrossLarge(i1,j1,3,col) ;
1079 } else {
1080 a /= lg;
1081 b /= lg;
1082
1083 vpImagePoint ip3;
1084 ip3.set_i(ip2.get_i() - w * a);
1085 ip3.set_j(ip2.get_j() - w * b);
1086
1087 vpImagePoint ip4;
1088 ip4.set_i(ip3.get_i() - b * h);
1089 ip4.set_j(ip3.get_j() + a * h);
1090
1091 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1092 displayLine(ip2, ip4, color, thickness);
1093
1094 ip4.set_i(ip3.get_i() + b * h);
1095 ip4.set_j(ip3.get_j() - a * h);
1096
1097 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1098 displayLine(ip2, ip4, color, thickness);
1099
1100 displayLine(ip1, ip2, color, thickness);
1101 }
1102 } else {
1103 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1104 }
1105}
1106
1118void vpDisplayOpenCV::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
1119{
1121 if (color.id < vpColor::id_unknown) {
1122#if VISP_HAVE_OPENCV_VERSION < 0x020408
1123 cvPutText(m_background, text,
1124 cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)), font,
1125 col[color.id]);
1126#else
1127 cv::putText(m_background, text,
1128 cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
1129 font, fontScale, col[color.id]);
1130#endif
1131 } else {
1132 cvcolor = CV_RGB(color.R, color.G, color.B);
1133#if VISP_HAVE_OPENCV_VERSION < 0x020408
1134 cvPutText(m_background, text,
1135 cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)), font,
1136 cvcolor);
1137#else
1138 cv::putText(m_background, text,
1139 cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
1140 font, fontScale, cvcolor);
1141#endif
1142 }
1143 } else {
1144 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1145 }
1146}
1159void vpDisplayOpenCV::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1160 unsigned int thickness)
1161{
1163 int x = vpMath::round(center.get_u() / m_scale);
1164 int y = vpMath::round(center.get_v() / m_scale);
1165 int r = static_cast<int>(radius / m_scale);
1166 cv::Scalar cv_color;
1167 if (color.id < vpColor::id_unknown) {
1168 cv_color = col[color.id];
1169 } else {
1170 cv_color = CV_RGB(color.R, color.G, color.B);
1171 }
1172
1173 if (fill == false) {
1174 int cv_thickness = static_cast<int>(thickness);
1175#if VISP_HAVE_OPENCV_VERSION < 0x020408
1176 cvCircle(m_background, cvPoint(x, y), r, cv_color, cv_thickness);
1177#else
1178 cv::circle(m_background, cv::Point(x, y), r, cv_color, cv_thickness);
1179#endif
1180 } else {
1181#if VISP_HAVE_OPENCV_VERSION >= 0x030000
1182 int filled = cv::FILLED;
1183#else
1184 int filled = CV_FILLED;
1185#endif
1186#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1187 double opacity = static_cast<double>(color.A) / 255.0;
1188#if VISP_HAVE_OPENCV_VERSION < 0x020408
1189 overlay([x, y, r, cv_color, filled](cv::Mat image) { cvCircle(image, cvPoint(x, y), r, cv_color, filled); },
1190 opacity);
1191#else
1192 overlay([x, y, r, cv_color, filled](cv::Mat image) { cv::circle(image, cv::Point(x, y), r, cv_color, filled); },
1193 opacity);
1194#endif
1195#else
1196#if VISP_HAVE_OPENCV_VERSION < 0x020408
1197 cvCircle(m_background, cvPoint(x, y), r, cv_color, filled);
1198#else
1199 cv::circle(m_background, cv::Point(x, y), r, cv_color, filled);
1200#endif
1201#endif
1202 }
1203 } else {
1204 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1205 }
1206}
1207
1215void vpDisplayOpenCV::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color,
1216 unsigned int thickness)
1217{
1219 vpImagePoint top, bottom, left, right;
1220 top.set_i(ip.get_i() - size / 2);
1221 top.set_j(ip.get_j());
1222 bottom.set_i(ip.get_i() + size / 2);
1223 bottom.set_j(ip.get_j());
1224 left.set_i(ip.get_i());
1225 left.set_j(ip.get_j() - size / 2);
1226 right.set_i(ip.get_i());
1227 right.set_j(ip.get_j() + size / 2);
1228 displayLine(top, bottom, color, thickness);
1229 displayLine(left, right, color, thickness);
1230 } else {
1231 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1232 }
1233}
1234
1242void vpDisplayOpenCV::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1243 unsigned int thickness)
1244{
1246 vpImagePoint ip1_ = ip1;
1247 vpImagePoint ip2_ = ip2;
1248
1249 double size = 10. * m_scale;
1250 double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
1251 bool vertical_line = (int)ip2_.get_j() == (int)ip1_.get_j();
1252 if (vertical_line) {
1253 if (ip2_.get_i() < ip1_.get_i()) {
1254 std::swap(ip1_, ip2_);
1255 }
1256 } else if (ip2_.get_j() < ip1_.get_j()) {
1257 std::swap(ip1_, ip2_);
1258 }
1259
1260 double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
1261 double deltaj = size / length * diff_j;
1262 double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
1263 double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
1264 double orig = ip1_.get_i() - slope * ip1_.get_j();
1265
1266 if (vertical_line) {
1267 for (unsigned int i = (unsigned int)ip1_.get_i(); i < ip2_.get_i(); i += (unsigned int)(2 * deltai)) {
1268 double j = ip1_.get_j();
1269 displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
1270 }
1271 } else {
1272 for (unsigned int j = (unsigned int)ip1_.get_j(); j < ip2_.get_j(); j += (unsigned int)(2 * deltaj)) {
1273 double i = slope * j + orig;
1274 displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
1275 }
1276 }
1277 } else {
1278 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1279 }
1280}
1281
1288void vpDisplayOpenCV::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1289 unsigned int thickness)
1290{
1292 if (color.id < vpColor::id_unknown) {
1293#if VISP_HAVE_OPENCV_VERSION < 0x020408
1294 cvLine(m_background, cvPoint(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1295 cvPoint(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), col[color.id],
1296 (int)thickness);
1297#else
1298 cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1299 cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), col[color.id],
1300 (int)thickness);
1301#endif
1302 } else {
1303 cvcolor = CV_RGB(color.R, color.G, color.B);
1304#if VISP_HAVE_OPENCV_VERSION < 0x020408
1305 cvLine(m_background, cvPoint(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1306 cvPoint(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), cvcolor,
1307 (int)thickness);
1308#else
1309 cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1310 cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), cvcolor,
1311 (int)thickness);
1312#endif
1313 }
1314 } else {
1315 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1316 }
1317}
1318
1325void vpDisplayOpenCV::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1326{
1328 for (unsigned int i = 0; i < thickness; i++) {
1329 if (color.id < vpColor::id_unknown) {
1330#if VISP_HAVE_OPENCV_VERSION < 0x020408
1331 cvLine(m_background, cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1332 cvPoint(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1333 col[color.id], (int)thickness);
1334#else
1335 cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1336 cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1337 col[color.id], (int)thickness);
1338#endif
1339 } else {
1340 cvcolor = CV_RGB(color.R, color.G, color.B);
1341#if VISP_HAVE_OPENCV_VERSION < 0x020408
1342 cvLine(m_background, cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1343 cvPoint(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1344 cvcolor, (int)thickness);
1345#else
1346 cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1347 cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1348 cvcolor, (int)thickness);
1349#endif
1350 }
1351 }
1352 } else {
1353 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1354 }
1355}
1356
1372void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h,
1373 const vpColor &color, bool fill, unsigned int thickness)
1374{
1376 int left = vpMath::round(topLeft.get_u() / m_scale);
1377 int top = vpMath::round(topLeft.get_v() / m_scale);
1378 int right = vpMath::round((topLeft.get_u() + w) / m_scale);
1379 int bottom = vpMath::round((topLeft.get_v() + h) / m_scale);
1380 cv::Scalar cv_color;
1381 if (color.id < vpColor::id_unknown) {
1382 cv_color = col[color.id];
1383 } else {
1384 cv_color = CV_RGB(color.R, color.G, color.B);
1385 }
1386
1387 if (fill == false) {
1388 int cv_thickness = static_cast<int>(thickness);
1389#if VISP_HAVE_OPENCV_VERSION < 0x020408
1390 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, cv_thickness);
1391#else
1392 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1393#endif
1394 } else {
1395#if VISP_HAVE_OPENCV_VERSION >= 0x030000
1396 int filled = cv::FILLED;
1397#else
1398 int filled = CV_FILLED;
1399#endif
1400#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1401 double opacity = static_cast<double>(color.A) / 255.0;
1402#if VISP_HAVE_OPENCV_VERSION < 0x020408
1403 overlay([left, top, right, bottom, cv_color, filled](
1404 cv::Mat image) { cvRectangle(image, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled); },
1405 opacity);
1406#else
1407 overlay(
1408 [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1409 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1410 },
1411 opacity);
1412#endif
1413#else
1414#if VISP_HAVE_OPENCV_VERSION < 0x020408
1415 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled);
1416#else
1417 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1418#endif
1419#endif
1420 }
1421 } else {
1422 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1423 }
1424}
1439void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight,
1440 const vpColor &color, bool fill, unsigned int thickness)
1441{
1443 int left = vpMath::round(topLeft.get_u() / m_scale);
1444 int top = vpMath::round(topLeft.get_v() / m_scale);
1445 int right = vpMath::round(bottomRight.get_u() / m_scale);
1446 int bottom = vpMath::round(bottomRight.get_v() / m_scale);
1447 cv::Scalar cv_color;
1448 if (color.id < vpColor::id_unknown) {
1449 cv_color = col[color.id];
1450 } else {
1451 cv_color = CV_RGB(color.R, color.G, color.B);
1452 }
1453
1454 if (fill == false) {
1455 int cv_thickness = static_cast<int>(thickness);
1456#if VISP_HAVE_OPENCV_VERSION < 0x020408
1457 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, cv_thickness);
1458#else
1459 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1460#endif
1461 } else {
1462#if VISP_HAVE_OPENCV_VERSION >= 0x030000
1463 int filled = cv::FILLED;
1464#else
1465 int filled = CV_FILLED;
1466#endif
1467#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1468 double opacity = static_cast<double>(color.A) / 255.0;
1469#if VISP_HAVE_OPENCV_VERSION < 0x020408
1470 overlay([left, top, right, bottom, cv_color, filled](
1471 cv::Mat image) { cvRectangle(image, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled); },
1472 opacity);
1473#else
1474 overlay(
1475 [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1476 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1477 },
1478 opacity);
1479#endif
1480#else
1481#if VISP_HAVE_OPENCV_VERSION < 0x020408
1482 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled);
1483#else
1484 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1485#endif
1486#endif
1487 }
1488 } else {
1489 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1490 }
1491}
1492
1506void vpDisplayOpenCV::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1507{
1509 int left = vpMath::round(rectangle.getLeft() / m_scale);
1510 int top = vpMath::round(rectangle.getTop() / m_scale);
1511 int right = vpMath::round(rectangle.getRight() / m_scale);
1512 int bottom = vpMath::round(rectangle.getBottom() / m_scale);
1513 cv::Scalar cv_color;
1514 if (color.id < vpColor::id_unknown) {
1515 cv_color = col[color.id];
1516 } else {
1517 cv_color = CV_RGB(color.R, color.G, color.B);
1518 }
1519
1520 if (fill == false) {
1521 int cv_thickness = static_cast<int>(thickness);
1522#if VISP_HAVE_OPENCV_VERSION < 0x020408
1523 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, cv_thickness);
1524#else
1525 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1526#endif
1527 } else {
1528#if VISP_HAVE_OPENCV_VERSION >= 0x030000
1529 int filled = cv::FILLED;
1530#else
1531 int filled = CV_FILLED;
1532#endif
1533#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1534 double opacity = static_cast<double>(color.A) / 255.0;
1535#if VISP_HAVE_OPENCV_VERSION < 0x020408
1536 overlay([left, top, right, bottom, cv_color, filled](
1537 cv::Mat image) { cvRectangle(image, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled); },
1538 opacity);
1539#else
1540 overlay(
1541 [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1542 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1543 },
1544 opacity);
1545#endif
1546#else
1547#if VISP_HAVE_OPENCV_VERSION < 0x020408
1548 cvRectangle(m_background, cvPoint(left, top), cvPoint(right, bottom), cv_color, filled);
1549#else
1550 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1551#endif
1552#endif
1553 }
1554 } else {
1555 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1556 }
1557}
1558
1574bool vpDisplayOpenCV::getClick(bool blocking)
1575{
1576 bool ret = false;
1578 flushDisplay();
1579 if (blocking) {
1580 lbuttondown = false;
1581 mbuttondown = false;
1582 rbuttondown = false;
1583 }
1584 do {
1585 if (lbuttondown) {
1586 ret = true;
1587 lbuttondown = false;
1588 }
1589 if (mbuttondown) {
1590 ret = true;
1591 mbuttondown = false;
1592 }
1593 if (rbuttondown) {
1594 ret = true;
1595 rbuttondown = false;
1596 }
1597 if (blocking)
1598#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1599 cvWaitKey(10);
1600#else
1601 cv::waitKey(10);
1602#endif
1603 } while (ret == false && blocking == true);
1604 } else {
1605 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1606 }
1607 return ret;
1608}
1609
1626{
1627 bool ret = false;
1628
1630 flushDisplay();
1631
1632 double u, v;
1633
1634 if (blocking) {
1635 lbuttondown = false;
1636 mbuttondown = false;
1637 rbuttondown = false;
1638 }
1639 do {
1640 if (lbuttondown) {
1641 ret = true;
1642 u = (unsigned int)x_lbuttondown * m_scale;
1643 v = (unsigned int)y_lbuttondown * m_scale;
1644 ip.set_u(u);
1645 ip.set_v(v);
1646 lbuttondown = false;
1647 }
1648 if (mbuttondown) {
1649 ret = true;
1650 u = (unsigned int)x_mbuttondown * m_scale;
1651 v = (unsigned int)y_mbuttondown * m_scale;
1652 ip.set_u(u);
1653 ip.set_v(v);
1654 mbuttondown = false;
1655 }
1656 if (rbuttondown) {
1657 ret = true;
1658 u = (unsigned int)x_rbuttondown * m_scale;
1659 v = (unsigned int)y_rbuttondown * m_scale;
1660 ip.set_u(u);
1661 ip.set_v(v);
1662 rbuttondown = false;
1663 }
1664 if (blocking)
1665#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1666 cvWaitKey(10);
1667#else
1668 cv::waitKey(10);
1669#endif
1670 } while (ret == false && blocking == true);
1671 } else {
1672 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1673 }
1674 return ret;
1675}
1676
1696{
1697 bool ret = false;
1698
1700 // flushDisplay() ;
1701 double u, v;
1702 if (blocking) {
1703 lbuttondown = false;
1704 mbuttondown = false;
1705 rbuttondown = false;
1706 }
1707 do {
1708 if (lbuttondown) {
1709 ret = true;
1710 u = (unsigned int)x_lbuttondown * m_scale;
1711 v = (unsigned int)y_lbuttondown * m_scale;
1712 ip.set_u(u);
1713 ip.set_v(v);
1714 button = vpMouseButton::button1;
1715 lbuttondown = false;
1716 }
1717 if (mbuttondown) {
1718 ret = true;
1719 u = (unsigned int)x_mbuttondown * m_scale;
1720 v = (unsigned int)y_mbuttondown * m_scale;
1721 ip.set_u(u);
1722 ip.set_v(v);
1723 button = vpMouseButton::button2;
1724 mbuttondown = false;
1725 }
1726 if (rbuttondown) {
1727 ret = true;
1728 u = (unsigned int)x_rbuttondown * m_scale;
1729 v = (unsigned int)y_rbuttondown * m_scale;
1730 ip.set_u(u);
1731 ip.set_v(v);
1732 button = vpMouseButton::button3;
1733 rbuttondown = false;
1734 }
1735 if (blocking)
1736#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1737 cvWaitKey(10);
1738#else
1739 cv::waitKey(10);
1740#endif
1741 } while (ret == false && blocking == true);
1742 } else {
1743 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1744 }
1745 return ret;
1746}
1747
1770{
1771 bool ret = false;
1773 // flushDisplay() ;
1774 double u, v;
1775 if (blocking) {
1776 lbuttonup = false;
1777 mbuttonup = false;
1778 rbuttonup = false;
1779 }
1780 do {
1781 if (lbuttonup) {
1782 ret = true;
1783 u = (unsigned int)x_lbuttonup * m_scale;
1784 v = (unsigned int)y_lbuttonup * m_scale;
1785 ip.set_u(u);
1786 ip.set_v(v);
1787 button = vpMouseButton::button1;
1788 lbuttonup = false;
1789 }
1790 if (mbuttonup) {
1791 ret = true;
1792 u = (unsigned int)x_mbuttonup * m_scale;
1793 v = (unsigned int)y_mbuttonup * m_scale;
1794 ip.set_u(u);
1795 ip.set_v(v);
1796 button = vpMouseButton::button2;
1797 mbuttonup = false;
1798 }
1799 if (rbuttonup) {
1800 ret = true;
1801 u = (unsigned int)x_rbuttonup * m_scale;
1802 v = (unsigned int)y_rbuttonup * m_scale;
1803 ip.set_u(u);
1804 ip.set_v(v);
1805 button = vpMouseButton::button3;
1806 rbuttonup = false;
1807 }
1808 if (blocking)
1809#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1810 cvWaitKey(10);
1811#else
1812 cv::waitKey(10);
1813#endif
1814 } while (ret == false && blocking == true);
1815 } else {
1816 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1817 }
1818 return ret;
1819}
1820
1821/*
1822 Gets the displayed image (including the overlay plane)
1823 and returns an RGBa image.
1824*/
1826{
1827 vpImageConvert::convert(m_background, I);
1828 // should certainly be optimized.
1829}
1830
1831void vpDisplayOpenCV::on_mouse(int event, int x, int y, int /*flags*/, void *display)
1832{
1833 vpDisplayOpenCV *disp = static_cast<vpDisplayOpenCV *>(display);
1834 switch (event) {
1835#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1836 case CV_EVENT_MOUSEMOVE:
1837#else
1838 case cv::EVENT_MOUSEMOVE:
1839#endif
1840 {
1841 disp->move = true;
1842 disp->x_move = x;
1843 disp->y_move = y;
1844 break;
1845 }
1846#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1847 case CV_EVENT_LBUTTONDOWN:
1848#else
1849 case cv::EVENT_LBUTTONDOWN:
1850#endif
1851 {
1852 disp->lbuttondown = true;
1853 disp->x_lbuttondown = x;
1854 disp->y_lbuttondown = y;
1855 break;
1856 }
1857#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1858 case CV_EVENT_MBUTTONDOWN:
1859#else
1860 case cv::EVENT_MBUTTONDOWN:
1861#endif
1862 {
1863 disp->mbuttondown = true;
1864 disp->x_mbuttondown = x;
1865 disp->y_mbuttondown = y;
1866 break;
1867 }
1868#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1869 case CV_EVENT_RBUTTONDOWN:
1870#else
1871 case cv::EVENT_RBUTTONDOWN:
1872#endif
1873 {
1874 disp->rbuttondown = true;
1875 disp->x_rbuttondown = x;
1876 disp->y_rbuttondown = y;
1877 break;
1878 }
1879#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1880 case CV_EVENT_LBUTTONUP:
1881#else
1882 case cv::EVENT_LBUTTONUP:
1883#endif
1884 {
1885 disp->lbuttonup = true;
1886 disp->x_lbuttonup = x;
1887 disp->y_lbuttonup = y;
1888 break;
1889 }
1890#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1891 case CV_EVENT_MBUTTONUP:
1892#else
1893 case cv::EVENT_MBUTTONUP:
1894#endif
1895 {
1896 disp->mbuttonup = true;
1897 disp->x_mbuttonup = x;
1898 disp->y_mbuttonup = y;
1899 break;
1900 }
1901#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1902 case CV_EVENT_RBUTTONUP:
1903#else
1904 case cv::EVENT_RBUTTONUP:
1905#endif
1906 {
1907 disp->rbuttonup = true;
1908 disp->x_rbuttonup = x;
1909 disp->y_rbuttonup = y;
1910 break;
1911 }
1912
1913 default:
1914 break;
1915 }
1916}
1917
1934{
1936 int delay;
1937 flushDisplay();
1938 if (blocking)
1939 delay = 0;
1940 else
1941 delay = 10;
1942
1943#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1944 int key_pressed = cvWaitKey(delay);
1945#else
1946 int key_pressed = cv::waitKey(delay);
1947#endif
1948
1949 if (key_pressed == -1)
1950 return false;
1951 return true;
1952 } else {
1953 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1954 }
1955 // return false; // Never reached after throw()
1956}
1975bool vpDisplayOpenCV::getKeyboardEvent(std::string &key, bool blocking)
1976{
1978 int delay;
1979 flushDisplay();
1980 if (blocking)
1981 delay = 0;
1982 else
1983 delay = 10;
1984
1985#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1986 int key_pressed = cvWaitKey(delay);
1987#else
1988 int key_pressed = cv::waitKey(delay);
1989#endif
1990 if (key_pressed == -1)
1991 return false;
1992 else {
1993 // std::cout << "Key pressed: \"" << key_pressed << "\"" << std::endl;
1994 std::stringstream ss;
1995 ss << key_pressed;
1996 key = ss.str();
1997 }
1998 return true;
1999 } else {
2000 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2001 }
2002 // return false; // Never reached after throw()
2003}
2004
2016{
2017 bool ret = false;
2018
2020 // flushDisplay() ;
2021 if (move) {
2022 ret = true;
2023 double u = (unsigned int)x_move / m_scale;
2024 double v = (unsigned int)y_move / m_scale;
2025 ip.set_u(u);
2026 ip.set_v(v);
2027 move = false;
2028 }
2029 }
2030
2031 else {
2032 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2033 }
2034 return ret;
2035}
2036
2048{
2050 bool moved = getPointerMotionEvent(ip);
2051 if (!moved) {
2052 double u, v;
2053 u = (unsigned int)x_move / m_scale;
2054 v = (unsigned int)y_move / m_scale;
2055 ip.set_u(u);
2056 ip.set_v(v);
2057 }
2058 return false;
2059 } else {
2060 throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2061 }
2062}
2063
2068void vpDisplayOpenCV::getScreenSize(unsigned int &w, unsigned int &h)
2069{
2070 w = h = 0;
2071
2072#if defined(VISP_HAVE_X11)
2073 vpDisplayX d;
2074 d.getScreenSize(w, h);
2075#elif defined(VISP_HAVE_XRANDR)
2076 std::string command = "xrandr | grep '*'";
2077 FILE *fpipe = (FILE *)popen(command.c_str(), "r");
2078 char line[256];
2079 while (fgets(line, sizeof(line), fpipe)) {
2080 std::string str(line);
2081 std::size_t found = str.find("Failed");
2082
2083 if (found == std::string::npos) {
2084 std::vector<std::string> elm;
2085 elm = vpIoTools::splitChain(str, " ");
2086 for (size_t i = 0; i < elm.size(); i++) {
2087 if (!elm[i].empty()) {
2088 std::vector<std::string> resolution = vpIoTools::splitChain(elm[i], "x");
2089 if (resolution.size() == 2) {
2090 std::istringstream sswidth(resolution[0]), ssheight(resolution[1]);
2091 sswidth >> w;
2092 ssheight >> h;
2093 break;
2094 }
2095 }
2096 }
2097 }
2098 }
2099 pclose(fpipe);
2100#elif defined(_WIN32)
2101#if !defined(WINRT)
2102 w = GetSystemMetrics(SM_CXSCREEN);
2103 h = GetSystemMetrics(SM_CYSCREEN);
2104#else
2105 throw(vpException(vpException::functionNotImplementedError, "The function vpDisplayOpenCV::getScreenSize() is not "
2106 "implemented on winrt"));
2107#endif
2108#endif
2109}
2110
2115{
2116 unsigned int width, height;
2117 getScreenSize(width, height);
2118 return width;
2119}
2120
2125{
2126 unsigned int width, height;
2127 getScreenSize(width, height);
2128 return height;
2129}
2130
2131#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
2137void vpDisplayOpenCV::overlay(std::function<void(cv::Mat &)> overlay_function, double opacity)
2138{
2139 // Initialize overlay layer for transparency
2140 cv::Mat overlay;
2141 if (opacity < 1.0) {
2142 // Deep copy
2143 overlay = m_background.clone();
2144 } else {
2145 // Shallow copy
2146 overlay = m_background;
2147 }
2148
2149 overlay_function(overlay);
2150
2151 // Blend background and overlay
2152 if (opacity < 1.0) {
2153 cv::addWeighted(overlay, opacity, m_background, 1.0 - opacity, 0.0, m_background);
2154 }
2155}
2156#endif
2157
2158#elif !defined(VISP_BUILD_SHARED_LIBS)
2159// Work around to avoid warning: libvisp_core.a(vpDisplayOpenCV.cpp.o) has no
2160// symbols
2161void dummy_vpDisplayOpenCV(){};
2162#endif
Class to define RGB colors available for display functionalities.
Definition vpColor.h:152
static const vpColor white
Definition vpColor.h:206
vpColorIdentifier id
Definition vpColor.h:200
static const vpColor red
Definition vpColor.h:211
static const vpColor darkGray
Definition vpColor.h:209
static const vpColor black
Definition vpColor.h:205
static const vpColor cyan
Definition vpColor.h:220
static const vpColor orange
Definition vpColor.h:221
static const vpColor darkRed
Definition vpColor.h:212
static const vpColor blue
Definition vpColor.h:217
static const vpColor lightGray
Definition vpColor.h:207
static const vpColor lightBlue
Definition vpColor.h:216
static const vpColor darkGreen
Definition vpColor.h:215
static const vpColor darkBlue
Definition vpColor.h:218
static const vpColor purple
Definition vpColor.h:222
static const vpColor lightGreen
Definition vpColor.h:213
static const vpColor yellow
Definition vpColor.h:219
@ id_lightBlue
Definition vpColor.h:178
@ id_yellow
Definition vpColor.h:184
@ id_darkGray
Definition vpColor.h:164
@ id_green
Definition vpColor.h:174
@ id_darkRed
Definition vpColor.h:170
@ id_lightGray
Definition vpColor.h:160
@ id_red
Definition vpColor.h:168
@ id_lightRed
Definition vpColor.h:166
@ id_white
Definition vpColor.h:158
@ id_black
Definition vpColor.h:156
@ id_blue
Definition vpColor.h:180
@ id_darkGreen
Definition vpColor.h:176
@ id_gray
Definition vpColor.h:162
@ id_lightGreen
Definition vpColor.h:172
@ id_purple
Definition vpColor.h:190
@ id_orange
Definition vpColor.h:188
@ id_cyan
Definition vpColor.h:186
@ id_darkBlue
Definition vpColor.h:182
@ id_unknown
Definition vpColor.h:193
static const vpColor lightRed
Definition vpColor.h:210
static const vpColor green
Definition vpColor.h:214
static const vpColor gray
Definition vpColor.h:208
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void overlay(std::function< void(cv::Mat &)> overlay_function, double opacity)
void setWindowPosition(int winx, int winy)
void displayImage(const vpImage< unsigned char > &I)
unsigned int getScreenWidth()
void clearDisplay(const vpColor &color=vpColor::white)
bool getPointerMotionEvent(vpImagePoint &ip)
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
bool getKeyboardEvent(bool blocking=true)
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void setFont(const std::string &font)
void setTitle(const std::string &title)
bool getClick(bool blocking=true)
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
void getScreenSize(unsigned int &width, unsigned int &height)
bool getPointerPosition(vpImagePoint &ip)
unsigned int getScreenHeight()
static void on_mouse(int event, int x, int y, int flags, void *param)
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition vpDisplayX.h:132
void getScreenSize(unsigned int &width, unsigned int &height)
Class that defines generic functionalities for display.
Definition vpDisplay.h:173
unsigned int m_height
Definition vpDisplay.h:212
vpScaleType m_scaleType
Definition vpDisplay.h:215
unsigned int m_width
Definition vpDisplay.h:211
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition vpDisplay.h:208
std::string m_title
Definition vpDisplay.h:213
int m_windowYPosition
display position
Definition vpDisplay.h:210
unsigned int m_scale
Definition vpDisplay.h:214
bool m_displayHasBeenInitialized
display has been initialized
Definition vpDisplay.h:206
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ functionNotImplementedError
Function not implemented.
Definition vpException.h:78
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
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_u(double u)
void set_v(double v)
double get_i() const
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getHeight() const
Definition vpImage.h:184
vpDisplay * display
Definition vpImage.h:140
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
static double sqr(double x)
Definition vpMath.h:124
static int round(double x)
Definition vpMath.h:323
unsigned char B
Blue component.
Definition vpRGBa.h:140
unsigned char R
Red component.
Definition vpRGBa.h:138
unsigned char G
Green component.
Definition vpRGBa.h:139
unsigned char A
Additionnal component.
Definition vpRGBa.h:141
Defines a rectangle in the plane.
Definition vpRect.h:76
double getLeft() const
Definition vpRect.h:170
double getRight() const
Definition vpRect.h:176
double getBottom() const
Definition vpRect.h:94
double getTop() const
Definition vpRect.h:189
#define vpTRACE
Definition vpDebug.h:411
#define vpERROR_TRACE
Definition vpDebug.h:388