Visual Servoing Platform  version 3.6.1 under development (2024-04-26)
vpPlotGraph.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  * Define a graph for the vpPlot class.
33  *
34 *****************************************************************************/
35 #define FLUSH_ON_PLOT
36 
37 #include <visp3/core/vpConfig.h>
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
39 
40 #include <visp3/core/vpMath.h>
41 #include <visp3/core/vpMeterPixelConversion.h>
42 #include <visp3/core/vpPixelMeterConversion.h>
43 #include <visp3/gui/vpPlotGraph.h>
44 
45 #include <visp3/gui/vpDisplayD3D.h>
46 #include <visp3/gui/vpDisplayGDI.h>
47 #include <visp3/gui/vpDisplayGTK.h>
48 #include <visp3/gui/vpDisplayOpenCV.h>
49 #include <visp3/gui/vpDisplayX.h>
50 
51 #include <cmath> // std::fabs
52 #include <limits> // numeric_limits
53 #include <sstream>
54 
55 #if defined(VISP_HAVE_DISPLAY)
56 
57 int laFonctionSansNom(double delta);
58 void getGrid3DPoint(double pente, vpImagePoint &iPunit, vpImagePoint &ip1, vpImagePoint &ip2, vpImagePoint &ip3);
59 
60 vpPlotGraph::vpPlotGraph()
61  : xorg(0.), yorg(0.), zoomx(1.), zoomy(1.), xmax(10), ymax(10), xmin(0), ymin(-10), xdelt(1), ydelt(1), gridx(true),
62  gridy(true), gridColor(), curveNbr(1), curveList(nullptr), scaleInitialized(false), firstPoint(true), nbDivisionx(10),
63  nbDivisiony(10), topLeft(), width(0), height(0), graphZone(), dTopLeft(), dWidth(0), dHeight(0), dGraphZone(),
64  dTopLeft3D(), dGraphZone3D(), cam(), cMo(), cMf(), w_xval(0), w_xsize(0), w_yval(0), w_ysize(0), w_zval(0),
65  w_zsize(0), ptXorg(0), ptYorg(0), ptZorg(0), zoomx_3D(1.), zoomy_3D(1.), zoomz_3D(1.), nbDivisionz(10), zorg(1.),
66  zoomz(1.), zmax(10), zmin(-10), zdelt(1), old_iPr(), old_iPz(), blockedr(false), blockedz(false), blocked(false),
67  epsi(5), epsj(6), dispUnit(false), dispTitle(false), dispLegend(false), gridThickness(1)
68 {
69  gridColor.setColor(200, 200, 200);
70 
71  old_iPr = vpImagePoint(-1, -1);
72  old_iPz = vpImagePoint(-1, -1);
73 
74  gridThickness = 1;
75 }
76 
77 vpPlotGraph::~vpPlotGraph()
78 {
79  if (curveList != nullptr) {
80  delete[] curveList;
81  curveList = nullptr;
82  }
83 }
84 
85 void vpPlotGraph::initGraph(unsigned int nbCurve)
86 {
87  curveList = new vpPlotCurve[nbCurve];
88  curveNbr = nbCurve;
89 
91 
92  for (unsigned int i = 0; i < curveNbr; ++i) {
93  (curveList + i)->color = colors[i % 6];
94  (curveList + i)->curveStyle = vpPlotCurve::line;
95  (curveList + i)->pointListx.clear();
96  (curveList + i)->pointListy.clear();
97  (curveList + i)->legend.clear();
98  }
99 }
100 
101 void vpPlotGraph::initSize(vpImagePoint top_left, unsigned int w, unsigned int h, unsigned int margei,
102  unsigned int margej)
103 {
104  this->topLeft = top_left;
105  this->width = w;
106  this->height = h;
107  graphZone.setTopLeft(topLeft);
108  graphZone.setWidth(width);
109  graphZone.setHeight(height);
110 
111  this->dTopLeft = vpImagePoint(topLeft.get_i() + margei, topLeft.get_j() + margej);
112  this->dWidth = width - margej - 10;
113  this->dHeight = height - 2 * margei;
114  dGraphZone.setTopLeft(dTopLeft);
115  dGraphZone.setWidth(dWidth + 1);
116  dGraphZone.setHeight(dHeight + 1);
117 
118  this->dTopLeft3D = vpImagePoint(topLeft.get_i() + margei, topLeft.get_j() + 10);
119  dGraphZone3D.setTopLeft(dTopLeft3D);
120  dGraphZone3D.setWidth(dWidth + 1);
121  dGraphZone3D.setHeight(dHeight + 1);
122 
123  if (this->dWidth > this->dHeight) {
124  w_ysize = 1.0;
125  w_xsize = this->dWidth / this->dHeight;
126  w_zsize = w_xsize;
127 
128  w_yval = w_ysize / 2.0;
129  w_xval = w_xsize / 2.0;
130  w_zval = w_zsize / 2.0;
131  }
132  else if (this->dWidth == this->dHeight) {
133  w_ysize = 1.0;
134  w_xsize = 1.0;
135  w_zsize = 1.0;
136 
137  w_yval = 0.5;
138  w_xval = 0.5;
139  w_zval = 0.5;
140  }
141  else if (this->dWidth < this->dHeight) {
142  w_xsize = 1.0;
143  w_ysize = this->dHeight / this->dWidth;
144  w_zsize = w_ysize;
145 
146  w_yval = w_ysize / 2.0;
147  w_xval = w_xsize / 2.0;
148  w_zval = w_zsize / 2.0;
149  }
150 
151  cam.initPersProjWithoutDistortion(1000, 1000, this->dWidth / 2.0, this->dHeight / 2.0);
152 
153  findPose();
154 
155  cMf.buildFrom(0, 0, cMo[2][3], 0, 0, 0);
156 }
157 
158 void vpPlotGraph::findPose()
159 {
160  vpPoint point_[4];
161  point_[0].setWorldCoordinates(-w_xval, -w_yval, -w_zval);
162  point_[1].setWorldCoordinates(w_xval, -w_yval, -w_zval);
163  point_[2].setWorldCoordinates(w_xval, w_yval, -w_zval);
164  point_[3].setWorldCoordinates(-w_xval, w_yval, -w_zval);
165 
166  vpImagePoint iP[4];
167  iP[0].set_ij(0, 0);
168  iP[1].set_ij(0, dWidth - 1);
169  iP[2].set_ij(dHeight - 1, dWidth - 1);
170  iP[3].set_ij(dHeight - 1, 0);
171 
172  double x = 0, y = 0;
173 
174  // Instead of pose computation we use an approximation
175  double Z = 0;
176  for (unsigned int i = 0; i < 4; ++i) {
177  vpPixelMeterConversion::convertPoint(cam, iP[i], x, y);
178  Z = vpMath::maximum(Z, point_[i].get_oX() / x);
179  Z = vpMath::maximum(Z, point_[i].get_oY() / y);
180  }
181  cMo[2][3] = Z;
182 }
183 
184 void vpPlotGraph::computeGraphParameters()
185 {
186  zoomx = dWidth / (xmax - xmin);
187  zoomy = dHeight / (ymax - ymin);
188  xorg = dTopLeft.get_j() - (xmin * zoomx);
189  yorg = dTopLeft.get_i() + (ymax * zoomy);
190 }
191 
192 void vpPlotGraph::setCurveColor(unsigned int curveNum, const vpColor &color) { (curveList + curveNum)->color = color; }
193 
194 void vpPlotGraph::setTitle(const std::string &title_)
195 {
196  title = title_;
197  dispTitle = true;
198 }
199 
200 void vpPlotGraph::setUnitX(const std::string &unit_x)
201 {
202  unitx = unit_x;
203  dispUnit = true;
204 }
205 
206 void vpPlotGraph::setUnitY(const std::string &unit_y)
207 {
208  unity = unit_y;
209  dispUnit = true;
210 }
211 
212 void vpPlotGraph::setUnitZ(const std::string &unit_z)
213 {
214  unitz = unit_z;
215  dispUnit = true;
216 }
217 
218 void vpPlotGraph::setLegend(unsigned int curveNum, const std::string &newlegend)
219 {
220  (curveList + curveNum)->legend = newlegend;
221  dispLegend = true;
222 }
223 
224 void vpPlotGraph::setCurveThickness(unsigned int curveNum, unsigned int thickness)
225 {
226  (curveList + curveNum)->thickness = thickness;
227 }
228 
229 int laFonctionSansNom(double delta)
230 {
231  double d = delta;
232  int power = 0;
233  if (d < 1) {
234  while (d < 1) {
235  d = d * 10;
236  power++;
237  }
238  power--;
239  return power;
240  }
241 
242  if (d >= 10) {
243  while (d > 10) {
244  d = d / 10;
245  power--;
246  }
247  power--;
248  return power;
249  }
250 
251  return 0;
252 }
253 
254 void vpPlotGraph::displayGrid(vpImage<unsigned char> &I)
255 {
256  computeGraphParameters();
257 
258  xdelt = (xmax - xmin) / nbDivisionx;
259  ydelt = (ymax - ymin) / nbDivisiony;
260 
261  double t;
262  int power;
263 
264  power = laFonctionSansNom(xdelt);
265  for (t = xmin; t <= xmax; t = t + xdelt) {
266  double x = xorg + (zoomx * t);
267  if (gridy)
268  vpDisplay::displayDotLine(I, vpImagePoint(dTopLeft.get_i(), x), vpImagePoint(dTopLeft.get_i() + dHeight, x),
269  gridColor, gridThickness);
270  else
271  vpDisplay::displayDotLine(I, vpImagePoint(yorg, x), vpImagePoint(yorg - 3, x), vpColor::black, gridThickness);
272 
273  if (t + xdelt <= xmax + 1e-10) {
274  double ttemp;
275  if (power != 0)
276  ttemp = t * pow(10.0, power);
277  else
278  ttemp = t;
279  std::stringstream valeur;
280  valeur.precision(3);
281  valeur << ttemp;
282 #if defined(VISP_HAVE_X11)
283  vpDisplay::displayText(I, vpImagePoint(yorg + 3 * epsi, x), valeur.str(), vpColor::black);
284 #elif defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || defined(VISP_HAVE_GTK)
285  vpDisplay::displayText(I, vpImagePoint(yorg + epsi, x), valeur.str(), vpColor::black);
286 #endif
287  }
288  }
289  if (power != 0) {
290  std::stringstream ss;
291  ss << "x10e";
292  ss << -power;
293 #if defined(VISP_HAVE_X11)
294  vpDisplay::displayText(I, vpImagePoint(yorg + 4 * epsi, dTopLeft.get_j() + dWidth - 6 * epsj), ss.str(),
296 #elif defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || defined(VISP_HAVE_GTK)
297  vpDisplay::displayText(I, vpImagePoint(yorg + 4 * epsi, dTopLeft.get_j() + dWidth - 10 * epsj), ss.str(),
299 #endif
300  }
301 
302  power = laFonctionSansNom(ydelt);
303  for (t = ymin; t <= ymax; t = t + ydelt) {
304  double y = yorg - (zoomy * t);
305  if (gridx)
306  vpDisplay::displayDotLine(I, vpImagePoint(y, dTopLeft.get_j()), vpImagePoint(y, dTopLeft.get_j() + dWidth),
307  gridColor, gridThickness);
308  else
309  vpDisplay::displayDotLine(I, vpImagePoint(y, xorg), vpImagePoint(y, xorg + 3), vpColor::black, gridThickness);
310 
311  double ttemp;
312  if (power != 0)
313  ttemp = t * pow(10.0, power);
314  else
315  ttemp = t;
316 
317  std::stringstream valeur;
318  valeur.precision(3);
319  valeur << ttemp;
320 #if defined(VISP_HAVE_X11)
321  vpDisplay::displayText(I, vpImagePoint(y + epsi, topLeft.get_j() + epsj), valeur.str(), vpColor::black);
322 #elif defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || defined(VISP_HAVE_GTK)
323  vpDisplay::displayText(I, vpImagePoint(y - epsi, topLeft.get_j() + epsj), valeur.str(), vpColor::black);
324 #endif
325  }
326  if (power != 0) {
327  std::stringstream ss;
328  ss << "x10e";
329  ss << -power;
330 #if defined(VISP_HAVE_X11)
331  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i() - 3 * epsi, dTopLeft.get_j() - 6 * epsj), ss.str(),
333 #elif defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || defined(VISP_HAVE_GTK)
334  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i() - 3 * epsi, dTopLeft.get_j() - 6 * epsj), ss.str(),
336 #endif
337  }
338 
339  // Ligne horizontal
340  vpDisplay::displayArrow(I, vpImagePoint(yorg, dTopLeft.get_j()), vpImagePoint(yorg, dTopLeft.get_j() + dWidth),
341  vpColor::black, 4 * gridThickness, 2 * gridThickness, gridThickness);
342  // Ligne verticale
343  vpDisplay::displayArrow(I, vpImagePoint(dTopLeft.get_i() + dHeight, xorg), vpImagePoint(dTopLeft.get_i(), xorg),
344  vpColor::black, 4 * gridThickness, 2 * gridThickness, gridThickness);
345 
346  if (dispUnit)
347  displayUnit(I);
348  if (dispTitle)
349  displayTitle(I);
350  if (dispLegend)
351  displayLegend(I);
352 
353  // vpDisplay::flushROI(I,graphZone);
354 }
355 
356 void vpPlotGraph::displayUnit(vpImage<unsigned char> &
357 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || \
358  defined(VISP_HAVE_GTK)
359  I
360 #endif
361 )
362 {
363  unsigned int offsetx = vpMath::minimum<unsigned int>((unsigned int)unitx.size(), dWidth);
364 
365 #if defined(VISP_HAVE_X11)
366  vpDisplay::displayText(I, vpImagePoint(yorg - 2 * epsi, dTopLeft.get_j() + dWidth - offsetx * epsj), unitx.c_str(),
368  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i(), dTopLeft.get_j() + epsj), unity.c_str(), vpColor::black);
369 #elif defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_D3D9) || defined(VISP_HAVE_GTK)
370  vpDisplay::displayText(I, vpImagePoint(yorg - 5 * epsi, dTopLeft.get_j() + dWidth - offsetx * epsj), unitx.c_str(),
372  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i(), dTopLeft.get_j() + epsj), unity.c_str(), vpColor::black);
373 #endif
374 }
375 
376 void vpPlotGraph::displayTitle(vpImage<unsigned char> &I)
377 {
378  double size = (double)title.size();
379  size = size / 2.0;
380  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i() - 3 * epsi, dTopLeft.get_j() + dWidth / 2.0 - 4 * size),
381  title, vpColor::black);
382 }
383 
384 void vpPlotGraph::displayLegend(vpImage<unsigned char> &I)
385 {
386  size_t offsetj = 0;
387  for (unsigned int i = 0; i < curveNbr; ++i) {
388  size_t offset = epsj * (curveList + i)->legend.size();
389  offsetj = vpMath::maximum(offset, offsetj);
390  }
391  if (offsetj > dWidth)
392  offsetj = dWidth;
393 
394  for (unsigned int i = 0; i < curveNbr; ++i) {
395  vpDisplay::displayText(I, vpImagePoint(dTopLeft.get_i() + i * 5 * epsi, dTopLeft.get_j() + dWidth - offsetj),
396  (curveList + i)->legend.c_str(), (curveList + i)->color);
397  }
398 }
399 
400 void vpPlotGraph::rescalex(unsigned int side, double extremity)
401 {
402  switch (side) {
403  case 0:
404  xmin = (3 * extremity - xmax) / 2;
405  break;
406  case 1:
407  xmax = (3 * extremity - xmin) / 2;
408  break;
409  }
410 
411  xdelt = (xmax - xmin) / (double)nbDivisionx;
412 }
413 
414 void vpPlotGraph::rescaley(unsigned int side, double extremity)
415 {
416  switch (side) {
417  case 0:
418  ymin = (3 * extremity - ymax) / 2;
419  break;
420  case 1:
421  ymax = (3 * extremity - ymin) / 2;
422  break;
423  }
424 
425  ydelt = (ymax - ymin) / (double)nbDivisiony;
426 }
427 
428 void vpPlotGraph::initScale(vpImage<unsigned char> &I, double x_min, double x_max, int nbDivx, double y_min,
429  double y_max, int nbDivy, bool gx, bool gy)
430 {
431  this->xmin = x_min;
432  this->xmax = x_max;
433  this->ymin = y_min;
434  this->ymax = y_max;
435  this->gridx = gx;
436  this->gridy = gy;
437  this->nbDivisionx = nbDivx;
438  this->nbDivisiony = nbDivy;
439  computeGraphParameters();
440  clearGraphZone(I);
441  displayGrid(I);
442  vpDisplay::flushROI(I, graphZone);
443  scaleInitialized = true;
444 }
445 
446 void vpPlotGraph::initScale(vpImage<unsigned char> &I, double x_min, double x_max, int nbDivx, double y_min,
447  double y_max, int nbDivy, double z_min, double z_max, int nbDivz, bool gx, bool gy)
448 {
449  this->xmin = x_min;
450  this->xmax = x_max;
451  this->ymin = y_min;
452  this->ymax = y_max;
453  this->zmin = z_min;
454  this->zmax = z_max;
455  this->gridx = gx;
456  this->gridy = gy;
457  this->nbDivisionx = nbDivx;
458  this->nbDivisiony = nbDivy;
459  this->nbDivisionz = nbDivz;
460  computeGraphParameters();
461  clearGraphZone(I);
462  displayGrid(I);
463  vpDisplay::flushROI(I, graphZone);
464  scaleInitialized = true;
465 }
466 
467 void vpPlotGraph::plot(vpImage<unsigned char> &I, unsigned int curveNb, double x, double y)
468 {
469  if (!scaleInitialized) {
470  if (x < 0) {
471  xmax = 0;
472  rescalex(0, x);
473  }
474  if (x > 0) {
475  xmin = 0;
476  rescalex(1, x);
477  }
478  if (y < 0) {
479  ymax = 0;
480  rescaley(0, y);
481  }
482  if (y > 0) {
483  ymin = 0;
484  rescaley(1, y);
485  }
486  scaleInitialized = true;
487  computeGraphParameters();
488  clearGraphZone(I);
489  displayGrid(I);
490  // if (y == 0)
491  if (std::fabs(y) <= std::numeric_limits<double>::epsilon())
492  scaleInitialized = false;
493  }
494 
495  if (firstPoint) {
496  // clearGraphZone(I);
497  // displayGrid(I);
498  // vpDisplay::flushROI(I,graphZone);
499  replot(I);
500  firstPoint = false;
501  }
502 
503  double i = yorg - (zoomy * y);
504  double j = xorg + (zoomx * x);
505 
506  vpImagePoint iP(i, j);
507 
508  if (!iP.inRectangle(dGraphZone)) {
509  if (x > xmax)
510  rescalex(1, x);
511  else if (x < xmin)
512  rescalex(0, x);
513 
514  if (y > ymax)
515  rescaley(1, y);
516  else if (y < ymin)
517  rescaley(0, y);
518 
519  computeGraphParameters();
520 
521  replot(I);
522  i = yorg - (zoomy * y);
523  j = xorg + (zoomx * x);
524 
525  iP.set_ij(i, j);
526  }
527 
528  (curveList + curveNb)->plotPoint(I, iP, x, y);
529 #if (!defined VISP_HAVE_X11 && defined FLUSH_ON_PLOT)
530  vpDisplay::flushROI(I, graphZone);
531  // vpDisplay::flush(I);
532 #endif
533 }
534 
535 void vpPlotGraph::replot(vpImage<unsigned char> &I)
536 {
537  clearGraphZone(I);
538  displayGrid(I);
539  for (unsigned int i = 0; i < curveNbr; ++i)
540  (curveList + i)->plotList(I, xorg, yorg, zoomx, zoomy);
541  vpDisplay::flushROI(I, graphZone);
542 }
543 
544 void vpPlotGraph::clearGraphZone(vpImage<unsigned char> &I) { vpDisplay::displayROI(I, graphZone); }
545 
546 bool vpPlotGraph::getPixelValue(vpImage<unsigned char> &I, vpImagePoint &iP)
547 {
548  if (iP.inRectangle(dGraphZone)) {
549  double x = (iP.get_j() - xorg) / zoomx;
550  double y = (yorg - iP.get_i()) / zoomy;
551 
552  vpDisplay::displayROI(I, vpRect(vpImagePoint(topLeft.get_i() + height - 20, topLeft.get_j()), width - 1, 19));
553  std::stringstream ss_x;
554  ss_x << " x: ";
555  ss_x << x;
556  vpDisplay::displayText(I, vpImagePoint(topLeft.get_i() + height - 2, topLeft.get_j() + 5 * epsj), ss_x.str(),
558  std::stringstream ss_y;
559  ss_y << " y: ";
560  ss_y << y;
561  vpDisplay::displayText(I, vpImagePoint(topLeft.get_i() + height - 2, topLeft.get_j() + width / 2.0), ss_x.str(),
563  // vpDisplay::flush(I);
564  vpDisplay::flushROI(I, vpRect(vpImagePoint(topLeft.get_i() + height - 20, topLeft.get_j()), width - 1, 19));
565  return true;
566  }
567  return false;
568 }
569 
570 void vpPlotGraph::resetPointList(unsigned int curveNum)
571 {
572  (curveList + curveNum)->pointListx.clear();
573  (curveList + curveNum)->pointListy.clear();
574  (curveList + curveNum)->pointListz.clear();
575  (curveList + curveNum)->nbPoint = 0;
576  firstPoint = true;
577 }
578 
579 /************************************************************************************************/
580 
581 bool vpPlotGraph::check3Dline(vpImagePoint &iP1, vpImagePoint &iP2)
582 {
583  bool iP1In = iP1.inRectangle(dGraphZone3D);
584  bool iP2In = iP2.inRectangle(dGraphZone3D);
585 
586  if (!iP1In || !iP2In) {
587  double dTopLeft_i = dTopLeft3D.get_i();
588  double dTopLeft_j = dTopLeft3D.get_j();
589  double dBottomRight_i = dTopLeft_i + dHeight;
590  double dBottomRight_j = dTopLeft_j + dWidth;
591 
592  // Cas vertical
593  if (vpImagePoint::distance(iP1, iP2) < 9)
594  return false;
595  if (fabs(iP2.get_j() - iP1.get_j()) <= 2) {
596  if (!iP1In && !iP2In) {
597  if (iP1.get_i() < dTopLeft_i && iP2.get_i() < dTopLeft_i)
598  return false;
599  if (iP1.get_i() > dBottomRight_i && iP2.get_i() > dBottomRight_i)
600  return false;
601  if (iP1.get_j() < dTopLeft_j || iP1.get_j() > dBottomRight_j)
602  return false;
603  if (iP1.get_i() < dTopLeft_i)
604  iP1.set_i(dTopLeft_i);
605  else
606  iP1.set_i(dBottomRight_i);
607  if (iP2.get_i() < dTopLeft_i)
608  iP2.set_i(dTopLeft_i);
609  else
610  iP2.set_i(dBottomRight_i);
611  }
612  else if (!iP1In) {
613  if (iP1.get_j() < dTopLeft_j)
614  iP1.set_j(dTopLeft_j);
615  if (iP1.get_j() > dBottomRight_j)
616  iP1.set_j(dBottomRight_j);
617  if (iP1.get_i() < dTopLeft_i)
618  iP1.set_i(dTopLeft_i);
619  if (iP1.get_i() > dBottomRight_i)
620  iP1.set_i(dBottomRight_i);
621  return true;
622  }
623  else if (!iP2In) {
624  if (iP2.get_j() < dTopLeft_j)
625  iP2.set_j(dTopLeft_j);
626  if (iP2.get_j() > dBottomRight_j)
627  iP2.set_j(dBottomRight_j);
628  if (iP2.get_i() < dTopLeft_i)
629  iP2.set_i(dTopLeft_i);
630  if (iP2.get_i() > dBottomRight_i)
631  iP2.set_i(dBottomRight_i);
632  return true;
633  }
634  }
635  // cas horizontal
636  else if (fabs(iP2.get_i() - iP1.get_i()) <= 2) {
637  if (!iP1In && !iP2In) {
638  if (iP1.get_j() < dTopLeft_j && iP2.get_j() < dTopLeft_j)
639  return false;
640  if (iP1.get_j() > dBottomRight_j && iP2.get_j() > dBottomRight_j)
641  return false;
642  if (iP1.get_i() < dTopLeft_i || iP1.get_i() > dBottomRight_i)
643  return false;
644  if (iP1.get_j() < dTopLeft_j)
645  iP1.set_j(dTopLeft_j);
646  else
647  iP1.set_j(dBottomRight_j);
648  if (iP2.get_j() < dTopLeft_j)
649  iP2.set_j(dTopLeft_j);
650  else
651  iP2.set_j(dBottomRight_j);
652  }
653  else if (!iP1In) {
654  if (iP1.get_j() < dTopLeft_j)
655  iP1.set_j(dTopLeft_j);
656  if (iP1.get_j() > dBottomRight_j)
657  iP1.set_j(dBottomRight_j);
658  if (iP1.get_i() < dTopLeft_i)
659  iP1.set_i(dTopLeft_i);
660  if (iP1.get_i() > dBottomRight_i)
661  iP1.set_i(dBottomRight_i);
662  return true;
663  }
664  else if (!iP2In) {
665  if (iP2.get_j() < dTopLeft_j)
666  iP2.set_j(dTopLeft_j);
667  if (iP2.get_j() > dBottomRight_j)
668  iP2.set_j(dBottomRight_j);
669  if (iP2.get_i() < dTopLeft_i)
670  iP2.set_i(dTopLeft_i);
671  if (iP2.get_i() > dBottomRight_i)
672  iP2.set_i(dBottomRight_i);
673  return true;
674  }
675  }
676 
677  double a = (iP2.get_i() - iP1.get_i()) / (iP2.get_j() - iP1.get_j());
678  double b = iP1.get_i() - a * iP1.get_j();
679 
680  // test horizontal
681  double jtop = (dTopLeft_i - b) / a;
682  double jlow = (dBottomRight_i - b) / a;
683  // test vertical
684  double ileft = dTopLeft_j * a + b;
685  double iright = (dBottomRight_j)*a + b;
686 
687  vpImagePoint iP[2];
688  int n = 0;
689 
690  if (jtop >= dTopLeft_j && jtop <= dBottomRight_j) {
691  iP[n].set_ij(dTopLeft_i, jtop);
692  n++;
693  }
694  if (jlow >= dTopLeft_j && jlow <= dBottomRight_j) {
695  iP[n].set_ij(dBottomRight_i, jlow);
696  n++;
697  }
698  if (ileft >= dTopLeft_i && ileft <= dBottomRight_i && n < 2) {
699  iP[n].set_ij(ileft, dTopLeft_j);
700  n++;
701  }
702  if (iright >= dTopLeft_i && iright <= dBottomRight_i && n < 2) {
703  iP[n].set_ij(iright, dBottomRight_j);
704  n++;
705  }
706 
707  if (n < 2)
708  return false;
709 
710  if (!iP1In && !iP2In) {
711  if (fabs(a) < 1) {
712  if (vpMath::sign(iP1.get_j() - iP[0].get_j()) == vpMath::sign(iP2.get_j() - iP[0].get_j()))
713  return false;
714  int sign = vpMath::sign(iP1.get_j() - iP2.get_j());
715  if (sign == vpMath::sign(iP[0].get_j() - iP[1].get_j())) {
716  iP1 = iP[0];
717  iP2 = iP[1];
718  }
719  else {
720  iP1 = iP[1];
721  iP2 = iP[0];
722  }
723  }
724  else {
725  if (vpMath::sign(iP1.get_i() - iP[0].get_i()) == vpMath::sign(iP2.get_i() - iP[0].get_i()))
726  return false;
727  int sign = vpMath::sign(iP1.get_i() - iP2.get_i());
728  if (sign == vpMath::sign(iP[0].get_i() - iP[1].get_i())) {
729  iP1 = iP[0];
730  iP2 = iP[1];
731  }
732  else {
733  iP1 = iP[1];
734  iP2 = iP[0];
735  }
736  }
737  }
738  else if (!iP1In) {
739  vpImagePoint iPtemp = iP1;
740  if (fabs(a) < 1) {
741  int sign = vpMath::sign(iP1.get_j() - iP2.get_j());
742  if (fabs(iP[0].get_j() - iP2.get_j()) > 5) {
743  if (sign == vpMath::sign(iP[0].get_j() - iP2.get_j()))
744  iP1 = iP[0];
745  else
746  iP1 = iP[1];
747  }
748  else {
749  if (sign == vpMath::sign(iP[1].get_j() - iP2.get_j()))
750  iP1 = iP[1];
751  else
752  iP1 = iP[0];
753  }
754  }
755  else {
756  int sign = vpMath::sign(iP1.get_i() - iP2.get_i());
757  if (fabs(iP[0].get_i() - iP2.get_i()) > 5) {
758  if (sign == vpMath::sign(iP[0].get_i() - iP2.get_i()))
759  iP1 = iP[0];
760  else
761  iP1 = iP[1];
762  }
763  else {
764  if (sign == vpMath::sign(iP[1].get_i() - iP2.get_i()))
765  iP1 = iP[1];
766  else
767  iP1 = iP[0];
768  }
769  }
770  if (vpImagePoint::distance(iP1, iP2) < 9) {
771  iP1 = iPtemp;
772  return false;
773  }
774  }
775  else if (!iP2In) {
776  vpImagePoint iPtemp = iP2;
777  if (fabs(a) < 1) {
778  int sign = vpMath::sign(iP2.get_j() - iP1.get_j());
779  if (fabs(iP[0].get_j() - iP1.get_j()) > 5) {
780  if (sign == vpMath::sign(iP[0].get_j() - iP1.get_j()))
781  iP2 = iP[0];
782  else
783  iP2 = iP[1];
784  }
785  else {
786  if (sign == vpMath::sign(iP[1].get_j() - iP1.get_j()))
787  iP2 = iP[1];
788  else
789  iP2 = iP[0];
790  }
791  }
792  else {
793  int sign = vpMath::sign(iP2.get_i() - iP1.get_i());
794  if (fabs(iP[0].get_i() - iP1.get_i()) > 5) {
795  if (sign == vpMath::sign(iP[0].get_i() - iP1.get_i()))
796  iP2 = iP[0];
797  else
798  iP2 = iP[1];
799  }
800  else {
801  if (sign == vpMath::sign(iP[1].get_i() - iP1.get_i()))
802  iP2 = iP[1];
803  else
804  iP2 = iP[0];
805  }
806  }
807  if (vpImagePoint::distance(iP1, iP2) < 9) {
808  iP2 = iPtemp;
809  return false;
810  }
811  }
812  }
813  return true;
814 }
815 
816 bool vpPlotGraph::check3Dpoint(vpImagePoint &iP)
817 {
818  if (!iP.inRectangle(dGraphZone3D)) {
819  if (iP.get_i() < dTopLeft3D.get_i())
820  iP.set_i(dTopLeft3D.get_i());
821  else if (iP.get_i() > dTopLeft3D.get_i() + dHeight)
822  iP.set_i(dTopLeft3D.get_i() + dHeight - 1);
823  if (iP.get_j() < dTopLeft3D.get_j())
824  iP.set_j(dTopLeft3D.get_j());
825  else if (iP.get_j() > dTopLeft3D.get_j() + dWidth)
826  iP.set_j(dTopLeft3D.get_j() + dWidth - 1);
827  return false;
828  }
829  return true;
830 }
831 
832 void vpPlotGraph::computeGraphParameters3D()
833 {
834  zoomx_3D = w_xsize / (xmax - xmin);
835  zoomy_3D = w_ysize / (ymax - ymin);
836  zoomz_3D = w_zsize / (zmax - zmin);
837  ptXorg = w_xval - zoomx_3D * xmax;
838  ptYorg = w_yval + zoomy_3D * ymin;
839  ptZorg = w_zval - zoomz_3D * zmax;
840 }
841 
842 void getGrid3DPoint(double pente, vpImagePoint &iPunit, vpImagePoint &ip1, vpImagePoint &ip2, vpImagePoint &ip3)
843 {
844  if (pente <= 1) {
845  ip1 = iPunit - vpImagePoint(3, 0);
846  ip2 = iPunit + vpImagePoint(3, 0);
847  ip3 = iPunit - vpImagePoint(6, 6);
848  }
849  else {
850  ip1 = iPunit - vpImagePoint(0, 3);
851  ip2 = iPunit + vpImagePoint(0, 3);
852  ip3 = iPunit + vpImagePoint(6, 6);
853  }
854 }
855 
856 void vpPlotGraph::displayGrid3D(vpImage<unsigned char> &I)
857 {
858  computeGraphParameters3D();
859 
860  xdelt = (xmax - xmin) / nbDivisionx;
861  ydelt = (ymax - ymin) / nbDivisiony;
862  zdelt = (zmax - zmin) / nbDivisionz;
863 
864  vpPoint pt[6];
865  pt[0].setWorldCoordinates(-w_xval, ptYorg, ptZorg);
866  pt[1].setWorldCoordinates(w_xval, ptYorg, ptZorg);
867  pt[2].setWorldCoordinates(ptXorg, -w_yval, ptZorg);
868  pt[3].setWorldCoordinates(ptXorg, w_yval, ptZorg);
869  pt[4].setWorldCoordinates(ptXorg, ptYorg, -w_zval);
870  pt[5].setWorldCoordinates(ptXorg, ptYorg, w_zval);
871 
872  vpImagePoint iP[6];
873  for (unsigned int i = 0; i < 6; ++i) {
874  pt[i].track(cMo);
875  double u = 0.0, v = 0.0;
876  vpMeterPixelConversion::convertPoint(cam, pt[i].get_x(), pt[i].get_y(), u, v);
877  iP[i].set_uv(u, v);
878  iP[i] = iP[i] + dTopLeft3D;
879  }
880 
881  int power;
882  double t;
883  vpPoint ptunit;
884  vpImagePoint iPunit;
885  double pente;
886  vpImagePoint ip1;
887  vpImagePoint ip2;
888  vpImagePoint ip3;
889  vpImagePoint ip4;
890 
891  power = laFonctionSansNom(xdelt);
892  ptunit.setWorldCoordinates(-w_xval, ptYorg, ptZorg);
893  // if (iP[0].get_j()-iP[1].get_j() != 0)
894  if (std::fabs(iP[0].get_j() - iP[1].get_j()) >
895  vpMath::maximum(std::fabs(iP[0].get_j()), std::fabs(iP[1].get_j())) * std::numeric_limits<double>::epsilon())
896  pente = fabs((iP[0].get_i() - iP[1].get_i()) / (iP[0].get_j() - iP[1].get_j()));
897  else
898  pente = 2;
899 
900  unsigned int count = 1;
901  for (t = xmin; t <= xmax; t = t + xdelt) {
902  double x = ptXorg + (zoomx_3D * t);
903  ptunit.set_oX(x);
904  ptunit.track(cMo);
905  double u = 0.0, v = 0.0;
906  vpMeterPixelConversion::convertPoint(cam, ptunit.get_x(), ptunit.get_y(), u, v);
907  iPunit.set_uv(u, v);
908  iPunit = iPunit + dTopLeft3D;
909 
910  getGrid3DPoint(pente, iPunit, ip1, ip2, ip3);
911 
912  if (check3Dline(ip1, ip2)) {
914  if (count % 2 == 1) {
915  double ttemp;
916  if (power != 0)
917  ttemp = t * pow(10.0, power);
918  else
919  ttemp = t;
920  std::stringstream ss;
921  ss.precision(2);
922  ss << ttemp;
923  vpDisplay::displayText(I, ip3, ss.str(), vpColor::black);
924  }
925  }
926  count++;
927  }
928  if (power != 0) {
929  ip4 = iP[1] - vpImagePoint(-15, 10);
930  std::stringstream ss;
931  ss << "x10e";
932  ss << -power;
933  if (check3Dpoint(ip4))
934  vpDisplay::displayText(I, ip4, ss.str(), vpColor::black);
935  }
936 
937  power = laFonctionSansNom(ydelt);
938  ptunit.setWorldCoordinates(ptXorg, -w_yval, ptZorg);
939  // if (iP[2].get_j()-iP[3].get_j() != 0)
940  if (std::fabs(iP[2].get_j() - iP[3].get_j()) >
941  vpMath::maximum(std::fabs(iP[2].get_j()), std::fabs(iP[3].get_j())) * std::numeric_limits<double>::epsilon())
942  pente = fabs((iP[2].get_i() - iP[3].get_i()) / (iP[2].get_j() - iP[3].get_j()));
943  else
944  pente = 2;
945  count = 0;
946  for (t = ymin; t <= ymax; t = t + ydelt) {
947  double y = ptYorg - (zoomy_3D * t);
948  ptunit.set_oY(y);
949  ptunit.track(cMo);
950  double u = 0.0, v = 0.0;
951  vpMeterPixelConversion::convertPoint(cam, ptunit.get_x(), ptunit.get_y(), u, v);
952  iPunit.set_uv(u, v);
953  iPunit = iPunit + dTopLeft3D;
954 
955  getGrid3DPoint(pente, iPunit, ip1, ip2, ip3);
956 
957  if (check3Dline(ip1, ip2)) {
959  if (count % 2 == 1) {
960  double ttemp;
961  if (power != 0)
962  ttemp = t * pow(10.0, power);
963  else
964  ttemp = t;
965  std::stringstream ss;
966  ss.precision(2);
967  ss << ttemp;
968  vpDisplay::displayText(I, ip3, ss.str(), vpColor::black);
969  }
970  }
971  count++;
972  }
973  if (power != 0) {
974  ip4 = iP[2] - vpImagePoint(-15, 10);
975  std::stringstream ss;
976  ss << "x10e";
977  ss << -power;
978  if (check3Dpoint(ip4))
979  vpDisplay::displayText(I, ip4, ss.str(), vpColor::black);
980  }
981 
982  power = laFonctionSansNom(zdelt);
983  ptunit.setWorldCoordinates(ptXorg, ptYorg, -w_zval);
984  // if (iP[4].get_j()-iP[5].get_j() != 0)
985  if (std::fabs(iP[4].get_j() - iP[5].get_j()) >
986  vpMath::maximum(std::fabs(iP[4].get_j()), std::fabs(iP[5].get_j())) * std::numeric_limits<double>::epsilon())
987  pente = fabs((iP[4].get_i() - iP[5].get_i()) / (iP[4].get_j() - iP[5].get_j()));
988  else
989  pente = 2;
990  count = 0;
991  for (t = zmin; t <= zmax; t = t + zdelt) {
992  double z = ptZorg + (zoomz_3D * t);
993  ptunit.set_oZ(z);
994  ptunit.track(cMo);
995  double u = 0.0, v = 0.0;
996  vpMeterPixelConversion::convertPoint(cam, ptunit.get_x(), ptunit.get_y(), u, v);
997  iPunit.set_uv(u, v);
998  iPunit = iPunit + dTopLeft3D;
999 
1000  getGrid3DPoint(pente, iPunit, ip1, ip2, ip3);
1001 
1002  if (check3Dline(ip1, ip2)) {
1003  vpDisplay::displayLine(I, ip1, ip2, vpColor::black);
1004  if (count % 2 == 1) {
1005  double ttemp;
1006  if (power != 0)
1007  ttemp = t * pow(10.0, power);
1008  else
1009  ttemp = t;
1010  std::stringstream ss;
1011  ss.precision(2);
1012  ss << ttemp;
1013  vpDisplay::displayText(I, ip3, ss.str(), vpColor::black);
1014  }
1015  }
1016  count++;
1017  }
1018  if (power != 0) {
1019  ip4 = iP[5] - vpImagePoint(-15, 10);
1020  std::stringstream ss;
1021  ss << "x10e";
1022  ss << -power;
1023  if (check3Dpoint(ip4))
1024  vpDisplay::displayText(I, ip4, ss.str(), vpColor::black);
1025  }
1026 
1027  // Ligne horizontal
1028  if (check3Dline(iP[0], iP[1])) {
1029  vpDisplay::displayArrow(I, iP[0], iP[1], vpColor::black, gridThickness);
1030  if (dispUnit) {
1031  iPunit.set_ij(iP[1].get_i(), iP[1].get_j() - 10 * epsj);
1032  check3Dpoint(iPunit);
1033  vpDisplay::displayText(I, iPunit, unitx.c_str(), vpColor::black);
1034  }
1035  }
1036  if (check3Dline(iP[3], iP[2])) {
1037  vpDisplay::displayArrow(I, iP[3], iP[2], vpColor::black, gridThickness);
1038  if (dispUnit) {
1039  iPunit.set_ij(iP[2].get_i(), iP[2].get_j() - 10 * epsj);
1040  check3Dpoint(iPunit);
1041  vpDisplay::displayText(I, iPunit, unity.c_str(), vpColor::black);
1042  }
1043  }
1044  if (check3Dline(iP[4], iP[5])) {
1045  vpDisplay::displayArrow(I, iP[4], iP[5], vpColor::black, gridThickness);
1046  if (dispUnit) {
1047  iPunit.set_ij(iP[5].get_i(), iP[5].get_j() - 10 * epsj);
1048  check3Dpoint(iPunit);
1049  vpDisplay::displayText(I, iPunit, unitz.c_str(), vpColor::black);
1050  }
1051  }
1052 
1053  if (dispTitle)
1054  displayTitle(I);
1055  if (dispLegend)
1056  displayLegend(I);
1057 }
1058 
1059 vpMouseButton::vpMouseButtonType vpPlotGraph::plot(vpImage<unsigned char> &I, unsigned int curveNb, double x, double y,
1060  double z)
1061 {
1062  if (!scaleInitialized) {
1063  if (x < 0) {
1064  xmax = 0;
1065  rescalex(0, x);
1066  }
1067  if (x > 0) {
1068  xmin = 0;
1069  rescalex(1, x);
1070  }
1071  if (y < 0) {
1072  ymax = 0;
1073  rescaley(0, y);
1074  }
1075  if (y > 0) {
1076  ymin = 0;
1077  rescaley(1, y);
1078  }
1079  if (z < 0) {
1080  zmax = 0;
1081  rescalez(0, z);
1082  }
1083  if (z > 0) {
1084  zmin = 0;
1085  rescalez(1, z);
1086  }
1087  scaleInitialized = true;
1088  computeGraphParameters3D();
1089  clearGraphZone(I);
1090  displayGrid3D(I);
1091  // if (std::fabs(y) == 0 || z == 0)
1092  if (std::fabs(y) <= std::numeric_limits<double>::epsilon() ||
1093  std::fabs(z) <= std::numeric_limits<double>::epsilon())
1094  scaleInitialized = false;
1095  }
1096 
1097  if (firstPoint) {
1098  clearGraphZone(I);
1099  displayGrid3D(I);
1100  vpDisplay::flushROI(I, graphZone);
1101  firstPoint = false;
1102  }
1103 
1104  bool changed = false;
1105  if (x > xmax) {
1106  rescalex(1, x);
1107  changed = true;
1108  }
1109  else if (x < xmin) {
1110  rescalex(0, x);
1111  changed = true;
1112  }
1113 
1114  if (y > ymax) {
1115  rescaley(1, y);
1116  changed = true;
1117  }
1118  else if (y < ymin) {
1119  rescaley(0, y);
1120  changed = true;
1121  }
1122 
1123  if (z > zmax) {
1124  rescalez(1, z);
1125  changed = true;
1126  }
1127  else if (z < zmin) {
1128  rescalez(0, z);
1129  changed = true;
1130  }
1131 
1133 
1134  if (changed || move(I, button)) {
1135  computeGraphParameters3D();
1136  replot3D(I);
1137  }
1138 
1139  vpPoint pointPlot;
1140  pointPlot.setWorldCoordinates(ptXorg + (zoomx_3D * x), ptYorg - (zoomy_3D * y), ptZorg + (zoomz_3D * z));
1141  pointPlot.track(cMo);
1142  double u = 0.0, v = 0.0;
1143  vpMeterPixelConversion::convertPoint(cam, pointPlot.get_x(), pointPlot.get_y(), u, v);
1144  vpImagePoint iP;
1145  iP.set_uv(u, v);
1146  iP = iP + dTopLeft3D;
1147 
1148  if ((curveList + curveNb)->nbPoint) {
1149  if (check3Dline((curveList + curveNb)->lastPoint, iP))
1150  vpDisplay::displayLine(I, (curveList + curveNb)->lastPoint, iP, (curveList + curveNb)->color,
1151  (curveList + curveNb)->thickness);
1152  }
1153 #if (defined VISP_HAVE_X11 || defined VISP_HAVE_GDI)
1154  double top;
1155  double left;
1156  double width_;
1157  double height_;
1158 
1159  if (iP.get_i() <= (curveList + curveNb)->lastPoint.get_i()) {
1160  top = iP.get_i() - 5;
1161  height_ = (curveList + curveNb)->lastPoint.get_i() - top + 10;
1162  }
1163  else {
1164  top = (curveList + curveNb)->lastPoint.get_i() - 5;
1165  height_ = iP.get_i() - top + 10;
1166  }
1167  if (iP.get_j() <= (curveList + curveNb)->lastPoint.get_j()) {
1168  left = iP.get_j() - 5;
1169  width_ = (curveList + curveNb)->lastPoint.get_j() - left + 10;
1170  }
1171  else {
1172  left = (curveList + curveNb)->lastPoint.get_j() - 5;
1173  width_ = iP.get_j() - left + 10;
1174  }
1175  vpDisplay::flushROI(I, vpRect(left, top, width_, height_));
1176 #endif
1177 
1178  (curveList + curveNb)->lastPoint = iP;
1179  (curveList + curveNb)->pointListx.push_back(x);
1180  (curveList + curveNb)->pointListy.push_back(y);
1181  (curveList + curveNb)->pointListz.push_back(z);
1182  (curveList + curveNb)->nbPoint++;
1183 
1184 #if (!defined VISP_HAVE_X11 && defined FLUSH_ON_PLOT)
1185  vpDisplay::flushROI(I, graphZone);
1186 #endif
1187  return button;
1188 }
1189 
1190 void vpPlotGraph::replot3D(vpImage<unsigned char> &I)
1191 {
1192  clearGraphZone(I);
1193  displayGrid3D(I);
1194 
1195  for (unsigned int i = 0; i < curveNbr; ++i) {
1196  std::list<double>::const_iterator it_ptListx = (curveList + i)->pointListx.begin();
1197  std::list<double>::const_iterator it_ptListy = (curveList + i)->pointListy.begin();
1198  std::list<double>::const_iterator it_ptListz = (curveList + i)->pointListz.begin();
1199 
1200  unsigned int k = 0;
1201  vpImagePoint iP;
1202  vpPoint pointPlot;
1203  while (k < (curveList + i)->nbPoint) {
1204  double x = *it_ptListx;
1205  double y = *it_ptListy;
1206  double z = *it_ptListz;
1207  pointPlot.setWorldCoordinates(ptXorg + (zoomx_3D * x), ptYorg - (zoomy_3D * y), ptZorg + (zoomz_3D * z));
1208  pointPlot.track(cMo);
1209  double u = 0.0, v = 0.0;
1210  vpMeterPixelConversion::convertPoint(cam, pointPlot.get_x(), pointPlot.get_y(), u, v);
1211  iP.set_uv(u, v);
1212  iP = iP + dTopLeft3D;
1213 
1214  // vpDisplay::displayCross(I,iP,3,vpColor::cyan);
1215  if (k > 0) {
1216  if (check3Dline((curveList + i)->lastPoint, iP))
1217  vpDisplay::displayLine(I, (curveList + i)->lastPoint, iP, (curveList + i)->color);
1218  // vpDisplay::displayCross(I,iP,3,vpColor::orange);
1219  }
1220 
1221  (curveList + i)->lastPoint = iP;
1222 
1223  ++it_ptListx;
1224  ++it_ptListy;
1225  ++it_ptListz;
1226  k++;
1227  }
1228  }
1229  vpDisplay::flushROI(I, graphZone);
1230 }
1231 
1232 void vpPlotGraph::rescalez(unsigned int side, double extremity)
1233 {
1234  switch (side) {
1235  case 0:
1236  zmin = (3 * extremity - zmax) / 2;
1237  break;
1238  case 1:
1239  zmax = (3 * extremity - zmin) / 2;
1240  break;
1241  }
1242 
1243  zdelt = (zmax - zmin) / (double)nbDivisionz;
1244 }
1245 
1250 bool vpPlotGraph::move(const vpImage<unsigned char> &I, vpMouseButton::vpMouseButtonType &button)
1251 {
1252  bool changed = false;
1253  vpHomogeneousMatrix displacement = navigation(I, changed, button);
1254 
1255  // if (displacement[2][3] != 0)
1256  if (std::fabs(displacement[2][3]) > std::numeric_limits<double>::epsilon())
1257  cMf = cMf * displacement;
1258  vpHomogeneousMatrix fMo = cMf.inverse() * cMo;
1259 
1260  cMo = cMf * displacement * fMo;
1261  return changed;
1262 }
1263 
1264 vpHomogeneousMatrix vpPlotGraph::navigation(const vpImage<unsigned char> &I, bool &changed,
1266 {
1267  vpImagePoint iP;
1268  vpImagePoint trash;
1269  bool clicked = false;
1270  bool clickedUp = false;
1271 
1272  vpHomogeneousMatrix mov(0, 0, 0, 0, 0, 0);
1273  changed = false;
1274 
1275  // if(!blocked) vpDisplay::getClickUp(I,trash, b,false);
1276 
1277  if (!blocked)
1278  clicked = vpDisplay::getClick(I, iP, b, false);
1279 
1280  if (blocked)
1281  clickedUp = vpDisplay::getClickUp(I, trash, b, false);
1282 
1283  if (clicked) {
1284  if (!iP.inRectangle(graphZone))
1285  return mov;
1286  }
1287 
1288  if (clicked) {
1289  if (b == vpMouseButton::button1)
1290  blockedr = true;
1291  if (b == vpMouseButton::button2)
1292  blockedz = true;
1293  blocked = true;
1294  }
1295 
1296  else if (clickedUp) {
1297  if (b == vpMouseButton::button1) {
1298  old_iPr = vpImagePoint(-1, -1);
1299  blockedr = false;
1300  }
1301  if (b == vpMouseButton::button2) {
1302  old_iPz = vpImagePoint(-1, -1);
1303  blockedz = false;
1304  }
1305  if (!(blockedr || blockedz)) {
1306  blocked = false;
1307  // while (vpDisplay::getClick(I,trash,b,false)) {};
1308  }
1309  }
1310 
1311  vpTime::sleepMs(5);
1313 
1314  if (old_iPr != vpImagePoint(-1, -1) && blockedr) {
1315  double width_ = vpMath::minimum(I.getWidth(), I.getHeight());
1316 
1317  double diffi = iP.get_i() - old_iPr.get_i();
1318  double diffj = iP.get_j() - old_iPr.get_j();
1319 
1320  double anglei = diffi * 360 / width_;
1321  double anglej = diffj * 360 / width_;
1322  mov.buildFrom(0, 0, 0, vpMath::rad(anglei), vpMath::rad(-anglej), 0);
1323  changed = true;
1324  }
1325 
1326  if (blockedr)
1327  old_iPr = iP;
1328 
1329  if (old_iPz != vpImagePoint(-1, -1) && blockedz) {
1330  double diffi = iP.get_i() - old_iPz.get_i();
1331  mov.buildFrom(0, 0, diffi * 0.01, 0, 0, 0);
1332  changed = true;
1333  }
1334 
1335  if (blockedz)
1336  old_iPz = iP;
1337 
1338  return mov;
1339 }
1340 
1341 #elif !defined(VISP_BUILD_SHARED_LIBS)
1342 // Work around to avoid warning: libvisp_core.a(vpPlotGraph.cpp.o) has no symbols
1343 void dummy_vpPlotGraph() { };
1344 #endif
1345 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:152
static const vpColor red
Definition: vpColor.h:211
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 blue
Definition: vpColor.h:217
static const vpColor purple
Definition: vpColor.h:222
static const vpColor green
Definition: vpColor.h:214
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayROI(const vpImage< unsigned char > &I, const vpRect &roi)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void flushROI(const vpImage< unsigned char > &I, const vpRect &roi)
static bool getClickUp(const vpImage< unsigned char > &I, vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static void displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static bool getPointerPosition(const vpImage< unsigned char > &I, vpImagePoint &ip)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:304
double get_j() const
Definition: vpImagePoint.h:125
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
bool inRectangle(const vpRect &rect) const
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:315
void set_i(double ii)
Definition: vpImagePoint.h:293
void set_uv(double u, double v)
Definition: vpImagePoint.h:352
double get_i() const
Definition: vpImagePoint.h:114
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getHeight() const
Definition: vpImage.h:184
static double rad(double deg)
Definition: vpMath.h:127
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:252
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:260
static int sign(double x)
Definition: vpMath.h:422
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:77
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:465
void set_oY(double oY)
Set the point oY coordinate in the object frame.
Definition: vpPoint.cpp:497
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:463
void set_oZ(double oZ)
Set the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:499
void set_oX(double oX)
Set the point oX coordinate in the object frame.
Definition: vpPoint.cpp:495
void setWorldCoordinates(double oX, double oY, double oZ)
Definition: vpPoint.cpp:110
Defines a rectangle in the plane.
Definition: vpRect.h:76
VISP_EXPORT void sleepMs(double t)