MRPT  1.9.9
CDisplayWindowPlots.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "gui-precomp.h" // Precompiled headers
11 
12 #include <mrpt/config.h>
14 #include <mrpt/system/os.h>
15 #include <mrpt/img/CImage.h>
16 #include <mrpt/gui/WxSubsystem.h>
17 #include <mrpt/gui/WxUtils.h>
18 
19 #include <mrpt/math/utils.h>
20 
21 using namespace mrpt;
22 using namespace mrpt::gui;
23 using namespace mrpt::math;
24 using namespace mrpt::system;
25 using namespace std;
27 
28 #if MRPT_HAS_WXWIDGETS
29 
30 BEGIN_EVENT_TABLE(CWindowDialogPlots, wxFrame)
31 
32 END_EVENT_TABLE()
33 
34 const long CWindowDialogPlots::ID_PLOT = wxNewId();
35 const long CWindowDialogPlots::ID_MENU_PRINT = wxNewId();
36 const long ID_MENUITEM1 = wxNewId();
37 const long ID_MENUITEM2 = wxNewId();
38 
40  CDisplayWindowPlots* winPlots, WxSubsystem::CWXMainFrame* parent,
41  wxWindowID id, const std::string& caption, wxSize initialSize)
42  : m_winPlots(winPlots), m_mainFrame(parent), m_firstSubmenu(true)
43 {
44  Create(
45  parent, id, _U(caption.c_str()), wxDefaultPosition, initialSize,
46  wxDEFAULT_FRAME_STYLE, _T("id"));
47 
48  SetClientSize(initialSize);
49 
50  wxIcon FrameIcon;
51  FrameIcon.CopyFromBitmap(mrpt::gui::WxSubsystem::getMRPTDefaultIcon());
52  SetIcon(FrameIcon);
53 
54  // Create the mpWindow object:
55  m_plot = new mpWindow(this, ID_PLOT);
56  m_plot->AddLayer(new mpScaleX());
57  m_plot->AddLayer(new mpScaleY());
58  m_plot->LockAspect(false);
59  m_plot->EnableDoubleBuffer(true);
60 
61  m_plot->Fit(-10, 10, -10, 10);
62 
63  // Menu:
64  wxMenuBar* MenuBar1 = new wxMenuBar();
65 
66  wxMenu* Menu1 = new wxMenu();
67  wxMenuItem* MenuItem1 =
68  new wxMenuItem(Menu1, ID_MENUITEM1, _("Close"), _(""), wxITEM_NORMAL);
69  Menu1->Append(MenuItem1);
70 
71  wxMenuItem* MenuItemPrint = new wxMenuItem(
72  Menu1, ID_MENU_PRINT, _("Print..."), _(""), wxITEM_NORMAL);
73  Menu1->Append(MenuItemPrint);
74 
75  MenuBar1->Append(Menu1, _("&File"));
76 
77  wxMenu* Menu2 = new wxMenu();
78  wxMenuItem* MenuItem2 = new wxMenuItem(
79  Menu2, ID_MENUITEM2, _("About..."), _(""), wxITEM_NORMAL);
80  Menu2->Append(MenuItem2);
81  MenuBar1->Append(Menu2, _("&Help"));
82 
83  SetMenuBar(MenuBar1);
84 
85  // Events:
86  Connect(
87  wxID_ANY, wxEVT_CLOSE_WINDOW,
88  (wxObjectEventFunction)&CWindowDialogPlots::OnClose);
89  Connect(
90  ID_MENUITEM1, wxEVT_COMMAND_MENU_SELECTED,
91  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuClose);
92  Connect(
93  ID_MENU_PRINT, wxEVT_COMMAND_MENU_SELECTED,
94  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuPrint);
95  Connect(
96  ID_MENUITEM2, wxEVT_COMMAND_MENU_SELECTED,
97  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuAbout);
98 
99  Connect(
100  wxID_ANY, wxEVT_SIZE,
101  (wxObjectEventFunction)&CWindowDialogPlots::OnResize);
102 
103  Connect(
104  wxID_ANY, wxEVT_CHAR,
105  (wxObjectEventFunction)&CWindowDialogPlots::OnChar);
106  m_plot->Connect(
107  wxEVT_CHAR, (wxObjectEventFunction)&CWindowDialogPlots::OnChar, 0,
108  this);
109  m_plot->Connect(
110  wxEVT_MOTION, (wxObjectEventFunction)&CWindowDialogPlots::OnMouseMove,
111  0, this);
112 
113  m_plot->Connect(
114  wxEVT_LEFT_DOWN,
115  (wxObjectEventFunction)&CWindowDialogPlots::OnMouseDown, nullptr, this);
116  m_plot->Connect(
117  wxEVT_RIGHT_DOWN,
118  (wxObjectEventFunction)&CWindowDialogPlots::OnMouseDown, nullptr, this);
119 
120  // Increment number of windows:
121  // int winCount =
123 // cout << "[CWindowDialogPlots] Notifying new window: " << winCount <<
124 // endl;
125 
126 // this->Iconize(false);
127 
128 #if 0
129  // JL: TEST CODE: This is the seed of the future new implementation based on wxFreeChart...
130  double data[][2] = {
131  { 10, 20, },
132  { 13, 16, },
133  { 7, 30, },
134  { 15, 34, },
135  { 25, 4, },
136  };
137  // first step: create plot
138  XYPlot *plot = new XYPlot();
139  // create dataset
140  XYSimpleDataset *dataset = new XYSimpleDataset();
141  // and add serie to it
142  dataset->AddSerie((double *) data, WXSIZEOF(data));
143  // set line renderer to dataset
144  dataset->SetRenderer(new XYLineRenderer());
145  // add our dataset to plot
146  plot->AddDataset(dataset);
147  // create left and bottom number axes
148  NumberAxis *leftAxis = new NumberAxis(AXIS_LEFT);
149  NumberAxis *bottomAxis = new NumberAxis(AXIS_BOTTOM);
150  // optional: set axis titles
151  leftAxis->SetTitle(wxT("X"));
152  bottomAxis->SetTitle(wxT("Y"));
153  // add axes to plot
154  plot->AddAxis(leftAxis);
155  plot->AddAxis(bottomAxis);
156  // link axes and dataset
157  plot->LinkDataVerticalAxis(0, 0);
158  plot->LinkDataHorizontalAxis(0, 0);
159  // and finally create chart
160  Chart* chart = new Chart(plot, wxT("my title"));
161  wxChartPanel *m_chartPanel = new wxChartPanel( this ); //, ID_PLOT );
162  m_chartPanel->SetChart( chart );
163 #endif
164 }
165 
166 // Destructor
168 // OnClose event:
169 void CWindowDialogPlots::OnClose(wxCloseEvent& event)
170 {
171  // Send the event:
172  bool allow_close = true;
173  try
174  {
175  mrptEventWindowClosed ev(m_winPlots, true /* allow close */);
176  m_winPlots->publishEvent(ev);
177  allow_close = ev.allow_close;
178  }
179  catch (...)
180  {
181  }
182  if (!allow_close) return; // Don't process this close event.
183 
184  // Set the m_hwnd=nullptr in our parent object.
185  m_winPlots->notifyChildWindowDestruction();
186 
187  // Decrement number of windows:
189 
190  // Signal we are destroyed:
191  m_winPlots->m_windowDestroyed.set_value();
192 
193  event.Skip(); // keep processing by parent classes.
194 }
195 
196 void CWindowDialogPlots::OnChar(wxKeyEvent& event)
197 {
198  if (m_winPlots)
199  {
200  const int code = event.GetKeyCode();
202 
203  m_winPlots->m_keyPushedCode = code;
204  m_winPlots->m_keyPushedModifier = mod;
205  m_winPlots->m_keyPushed = true;
206  // Send the event:
207  try
208  {
209  m_winPlots->publishEvent(
210  mrptEventWindowChar(m_winPlots, code, mod));
211  }
212  catch (...)
213  {
214  }
215  }
216  event.Skip();
217 }
218 
219 void CWindowDialogPlots::OnResize(wxSizeEvent& event)
220 {
221  // Send the event:
222  if (m_winPlots)
223  {
224  try
225  {
226  m_winPlots->publishEvent(
228  m_winPlots, event.GetSize().GetWidth(),
229  event.GetSize().GetHeight()));
230  }
231  catch (...)
232  {
233  }
234  }
235  event.Skip(); // so it's processed by the wx system!
236 }
237 
238 void CWindowDialogPlots::OnMouseDown(wxMouseEvent& event)
239 {
240  // Send the event:
241  if (m_winPlots)
242  {
243  try
244  {
245  m_winPlots->publishEvent(
247  m_winPlots, TPixelCoord(event.GetX(), event.GetY()),
248  event.LeftDown(), event.RightDown()));
249  }
250  catch (...)
251  {
252  }
253  }
254  event.Skip(); // so it's processed by the wx system!
255 }
256 
257 // Menu: Close
258 void CWindowDialogPlots::OnMenuClose(wxCommandEvent& event) { Close(); }
259 // Menu: Print
260 void CWindowDialogPlots::OnMenuPrint(wxCommandEvent& event)
261 {
262  m_plot->ShowPrintDialog();
263 }
264 // Menu: About
265 void CWindowDialogPlots::OnMenuAbout(wxCommandEvent& event)
266 {
267  ::wxMessageBox(
268  _("Plot viewer\n Class gui::CDisplayWindowPlots\n MRPT C++ & "
269  "wxMathPlot library"),
270  _("About..."));
271 }
272 
273 void CWindowDialogPlots::OnMenuSelected(wxCommandEvent& ev)
274 {
275  std::map<long, long>::const_iterator it = m_ID2ID.find(ev.GetId());
276  if (it != m_ID2ID.end())
277  {
278  if (m_winPlots && m_winPlots->m_callback)
279  m_winPlots->m_callback(
280  it->second, m_curCursorPos.x, m_curCursorPos.y,
281  m_winPlots->m_callback_param);
282  }
283 }
284 
285 void CWindowDialogPlots::OnMouseMove(wxMouseEvent& event)
286 {
287  int X, Y;
288  event.GetPosition(&X, &Y);
289  m_curCursorPos.x = m_plot->p2x(X);
290  m_curCursorPos.y = m_plot->p2y(Y);
291  m_last_mouse_point.x = X;
292  m_last_mouse_point.y = Y;
293 
294  // Send the event:
295  if (m_winPlots && m_winPlots->hasSubscribers())
296  {
297  try
298  {
299  m_winPlots->publishEvent(
301  m_winPlots,
302  mrpt::img::TPixelCoord(event.GetX(), event.GetY()),
303  event.LeftDown(), event.RightDown()));
304  }
305  catch (...)
306  {
307  }
308  }
309  event.Skip(); // so it's processed by the wx system!
310 }
311 
312 // Add / Modify a 2D plot using a MATLAB-like format string
314  const CVectorFloat& x, const CVectorFloat& y, const std::string& lineFormat,
315  const std::string& plotName)
316 {
317  mpFXYVector* theLayer;
318 
319  wxString lyName = _U(plotName.c_str());
320  bool updateAtTheEnd = false; // If we update an existing layer, update
321  // manually to refresh the changes!
322 
323  // Already existing layer?
324  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
325 
326  if (existingLy)
327  {
328  // Assure the class:
329  mpFXYVector* lyPlot2D = static_cast<mpFXYVector*>(existingLy);
330 
331  if (!lyPlot2D)
332  {
333  cerr << "[CWindowDialogPlots::plot] Plot name '" << plotName
334  << "' is not of expected class mpFXYVector!." << endl;
335  return;
336  }
337 
338  // Ok:
339  theLayer = lyPlot2D;
340  updateAtTheEnd = true;
341  }
342  else
343  {
344  // Create it:
345  theLayer = new mpFXYVector(lyName);
346  m_plot->AddLayer(theLayer);
347  }
348 
349  // Set data:
350  {
351  std::vector<float> x_(x.size()), y_(x.size());
352  ::memcpy(&x_[0], &x[0], sizeof(x[0]) * x_.size());
353  ::memcpy(&y_[0], &y[0], sizeof(y[0]) * y_.size());
354  theLayer->SetData(x_, y_);
355  }
356 
357  // Line style:
358  // -------------------
359  bool isContinuous = true;
360  int lineColor[] = {0, 0, 255};
361  int lineWidth = 1;
362  int lineStyle = wxSOLID;
363 
364  // parse string:
365  if (string::npos != lineFormat.find("."))
366  {
367  isContinuous = false;
368  }
369  if (string::npos != lineFormat.find("-"))
370  {
371  isContinuous = true;
372  lineStyle = wxSOLID;
373  }
374  if (string::npos != lineFormat.find(":"))
375  {
376  isContinuous = true;
377  lineStyle = wxLONG_DASH;
378  }
379 
380  if (string::npos != lineFormat.find("r"))
381  {
382  lineColor[0] = 0xFF;
383  lineColor[1] = 0x00;
384  lineColor[2] = 0x00;
385  }
386  if (string::npos != lineFormat.find("g"))
387  {
388  lineColor[0] = 0x00;
389  lineColor[1] = 0xFF;
390  lineColor[2] = 0x00;
391  }
392  if (string::npos != lineFormat.find("b"))
393  {
394  lineColor[0] = 0x00;
395  lineColor[1] = 0x00;
396  lineColor[2] = 0xFF;
397  }
398  if (string::npos != lineFormat.find("k"))
399  {
400  lineColor[0] = 0x00;
401  lineColor[1] = 0x00;
402  lineColor[2] = 0x00;
403  }
404  if (string::npos != lineFormat.find("m"))
405  {
406  lineColor[0] = 192;
407  lineColor[1] = 0;
408  lineColor[2] = 192;
409  }
410  if (string::npos != lineFormat.find("c"))
411  {
412  lineColor[0] = 0;
413  lineColor[1] = 192;
414  lineColor[2] = 192;
415  }
416 
417  if (string::npos != lineFormat.find("1"))
418  {
419  lineWidth = 1;
420  }
421  if (string::npos != lineFormat.find("2"))
422  {
423  lineWidth = 2;
424  }
425  if (string::npos != lineFormat.find("3"))
426  {
427  lineWidth = 3;
428  }
429  if (string::npos != lineFormat.find("4"))
430  {
431  lineWidth = 4;
432  }
433  if (string::npos != lineFormat.find("5"))
434  {
435  lineWidth = 5;
436  }
437  if (string::npos != lineFormat.find("6"))
438  {
439  lineWidth = 6;
440  }
441  if (string::npos != lineFormat.find("7"))
442  {
443  lineWidth = 7;
444  }
445  if (string::npos != lineFormat.find("8"))
446  {
447  lineWidth = 8;
448  }
449  if (string::npos != lineFormat.find("9"))
450  {
451  lineWidth = 9;
452  }
453 
454  theLayer->SetContinuity(isContinuous);
455 
456  wxPen pen(
457  wxColour(lineColor[0], lineColor[1], lineColor[2]), lineWidth,
458  lineStyle);
459  theLayer->SetPen(pen);
460 
461  theLayer->ShowName(false);
462 
463  if (updateAtTheEnd) m_plot->Refresh(false);
464 }
465 
466 // Add / Modify a 2D ellipse
467 // x[0,1]: Mean
468 // y[0,1,2]: Covariance matrix (0,0),(1,1),(0,1)
470  const CVectorFloat& x, const CVectorFloat& y, const std::string& lineFormat,
471  const std::string& plotName, bool showName)
472 {
473  mpCovarianceEllipse* theLayer;
474 
475  if (x.size() != 3 || y.size() != 3)
476  {
477  cerr << "[CWindowDialogPlots::plotEllipse] vectors do not have "
478  "expected size!!"
479  << endl;
480  return;
481  }
482 
483  wxString lyName = _U(plotName.c_str());
484  bool updateAtTheEnd = false; // If we update an existing layer, update
485  // manually to refresh the changes!
486 
487  // Already existing layer?
488  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
489 
490  if (existingLy)
491  {
492  // Assure the class:
493  mpCovarianceEllipse* lyPlotEllipse =
494  static_cast<mpCovarianceEllipse*>(existingLy);
495 
496  if (!lyPlotEllipse)
497  {
498  cerr << "[CWindowDialogPlots::plotEllipse] Plot name '" << plotName
499  << "' is not of expected class mpCovarianceEllipse!." << endl;
500  return;
501  }
502 
503  // Ok:
504  theLayer = lyPlotEllipse;
505  updateAtTheEnd = true;
506  }
507  else
508  {
509  // Create it:
510  theLayer = new mpCovarianceEllipse(1, 1, 0, 2, 32, lyName);
511  m_plot->AddLayer(theLayer);
512  }
513 
514  // Set data:
515  theLayer->SetCovarianceMatrix(y[0], y[2], y[1]);
516  theLayer->SetCoordinateBase(x[0], x[1]);
517  theLayer->SetQuantiles(x[2]);
518  theLayer->ShowName(showName);
519 
520  // Line style:
521  // -------------------
522  bool isContinuous = true;
523  int lineColor[] = {0, 0, 255};
524  int lineWidth = 1;
525  int lineStyle = wxSOLID;
526 
527  // parse string:
528  if (string::npos != lineFormat.find("."))
529  {
530  isContinuous = false;
531  }
532  if (string::npos != lineFormat.find("-"))
533  {
534  isContinuous = true;
535  lineStyle = wxSOLID;
536  }
537  if (string::npos != lineFormat.find(":"))
538  {
539  isContinuous = true;
540  lineStyle = wxLONG_DASH;
541  }
542 
543  if (string::npos != lineFormat.find("r"))
544  {
545  lineColor[0] = 0xFF;
546  lineColor[1] = 0x00;
547  lineColor[2] = 0x00;
548  }
549  if (string::npos != lineFormat.find("g"))
550  {
551  lineColor[0] = 0x00;
552  lineColor[1] = 0xFF;
553  lineColor[2] = 0x00;
554  }
555  if (string::npos != lineFormat.find("b"))
556  {
557  lineColor[0] = 0x00;
558  lineColor[1] = 0x00;
559  lineColor[2] = 0xFF;
560  }
561  if (string::npos != lineFormat.find("k"))
562  {
563  lineColor[0] = 0x00;
564  lineColor[1] = 0x00;
565  lineColor[2] = 0x00;
566  }
567  if (string::npos != lineFormat.find("m"))
568  {
569  lineColor[0] = 192;
570  lineColor[1] = 0;
571  lineColor[2] = 192;
572  }
573  if (string::npos != lineFormat.find("c"))
574  {
575  lineColor[0] = 0;
576  lineColor[1] = 192;
577  lineColor[2] = 192;
578  }
579 
580  if (string::npos != lineFormat.find("1"))
581  {
582  lineWidth = 1;
583  }
584  if (string::npos != lineFormat.find("2"))
585  {
586  lineWidth = 2;
587  }
588  if (string::npos != lineFormat.find("3"))
589  {
590  lineWidth = 3;
591  }
592  if (string::npos != lineFormat.find("4"))
593  {
594  lineWidth = 4;
595  }
596  if (string::npos != lineFormat.find("5"))
597  {
598  lineWidth = 5;
599  }
600  if (string::npos != lineFormat.find("6"))
601  {
602  lineWidth = 6;
603  }
604  if (string::npos != lineFormat.find("7"))
605  {
606  lineWidth = 7;
607  }
608  if (string::npos != lineFormat.find("8"))
609  {
610  lineWidth = 8;
611  }
612  if (string::npos != lineFormat.find("9"))
613  {
614  lineWidth = 9;
615  }
616 
617  theLayer->SetContinuity(isContinuous);
618 
619  wxPen pen(
620  wxColour(lineColor[0], lineColor[1], lineColor[2]), lineWidth,
621  lineStyle);
622  theLayer->SetPen(pen);
623 
624  if (updateAtTheEnd) m_plot->Refresh(false);
625 }
626 
628  void* theWxImage, const float& x0, const float& y0, const float& w,
629  const float& h, const std::string& plotName)
630 {
631  mpBitmapLayer* theLayer;
632 
633  wxString lyName = _U(plotName.c_str());
634  bool updateAtTheEnd = false; // If we update an existing layer, update
635  // manually to refresh the changes!
636 
637  // Already existing layer?
638  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
639 
640  if (existingLy)
641  {
642  // Assure the class:
643  mpBitmapLayer* ly = static_cast<mpBitmapLayer*>(existingLy);
644 
645  if (!ly)
646  {
647  cerr << "[CWindowDialogPlots::image] Plot name '" << plotName
648  << "' is not of expected class mpBitmapLayer!." << endl;
649  return;
650  }
651 
652  // Ok:
653  theLayer = ly;
654  updateAtTheEnd = true;
655  }
656  else
657  {
658  // Create it:
659  theLayer = new mpBitmapLayer();
660  m_plot->AddLayer(theLayer);
661  }
662 
663  // Set data:
664  wxImage* ii = static_cast<wxImage*>(theWxImage);
665  theLayer->SetBitmap(*ii, x0, y0, w, h);
666 
667  delete ii;
668  theWxImage = nullptr;
669 
670  if (updateAtTheEnd) m_plot->Refresh();
671 }
672 
673 #endif
674 
676  const std::string& windowCaption, unsigned int initialWindowWidth,
677  unsigned int initialWindowHeight)
678 {
681  windowCaption, initialWindowWidth, initialWindowHeight));
682 }
683 /*---------------------------------------------------------------
684  Constructor
685  ---------------------------------------------------------------*/
687  const std::string& windowCaption, unsigned int initialWidth,
688  unsigned int initialHeight)
689  : CBaseGUIWindow(static_cast<void*>(this), 400, 499, windowCaption),
690  m_holdon(false),
691  m_holdon_just_disabled(false),
692  m_holdon_cnt(0),
693  m_callback(nullptr),
694  m_callback_param(nullptr)
695 {
696  CBaseGUIWindow::createWxWindow(initialWidth, initialHeight);
697 }
698 
699 /*---------------------------------------------------------------
700  Destructor
701  ---------------------------------------------------------------*/
703 {
705 }
706 
707 /** Set cursor style to default (cursorIsCross=false) or to a cross
708  * (cursorIsCross=true) */
709 void CDisplayWindowPlots::setCursorCross(bool cursorIsCross)
710 {
711 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
713  if (!win) return;
714  win->m_plot->SetCursor(
715  *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
716 #else
717  MRPT_UNUSED_PARAM(cursorIsCross);
718 #endif
719 }
720 
721 /*---------------------------------------------------------------
722  getLastMousePosition
723  ---------------------------------------------------------------*/
725 {
726 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
728  if (!win) return false;
729  x = win->m_last_mouse_point.x;
730  y = win->m_last_mouse_point.y;
731  return true;
732 #else
735  return false;
736 #endif
737 }
738 
739 /*---------------------------------------------------------------
740  resize
741  ---------------------------------------------------------------*/
742 void CDisplayWindowPlots::resize(unsigned int width, unsigned int height)
743 {
744 #if MRPT_HAS_WXWIDGETS
745  if (!isOpen())
746  {
747  cerr << "[CDisplayWindowPlots::resize] Window closed!: " << m_caption
748  << endl;
749  return;
750  }
751 
752  // Send a request to destroy this object:
755  REQ->sourcePlots = this;
756  REQ->OPCODE = 403;
757  REQ->x = width;
758  REQ->y = height;
760 #else
763 #endif
764 }
765 
766 /*---------------------------------------------------------------
767  setPos
768  ---------------------------------------------------------------*/
770 {
771 #if MRPT_HAS_WXWIDGETS
772  if (!isOpen())
773  {
774  cerr << "[CDisplayWindowPlots::setPos] Window closed!: " << m_caption
775  << endl;
776  return;
777  }
778 
779  // Send a request to destroy this object:
782  REQ->sourcePlots = this;
783  REQ->OPCODE = 402;
784  REQ->x = x;
785  REQ->y = y;
787 #else
790 #endif
791 }
792 
793 /*---------------------------------------------------------------
794  setWindowTitle
795  ---------------------------------------------------------------*/
797 {
798 #if MRPT_HAS_WXWIDGETS
799  if (!isOpen())
800  {
801  cerr << "[CDisplayWindowPlots::setWindowTitle] Window closed!: "
802  << m_caption << endl;
803  return;
804  }
805 
806  // Send a request to destroy this object:
809  REQ->sourcePlots = this;
810  REQ->OPCODE = 404;
811  REQ->str = str;
813 #else
814  MRPT_UNUSED_PARAM(str);
815 #endif
816 }
817 
818 /*---------------------------------------------------------------
819  enableMousePanZoom
820  ---------------------------------------------------------------*/
822 {
823 #if MRPT_HAS_WXWIDGETS
824  if (!isOpen()) return;
825 
826  // Send a request to destroy this object:
829  REQ->sourcePlots = this;
830  REQ->OPCODE = 410;
831  REQ->boolVal = enabled;
833 #else
834  MRPT_UNUSED_PARAM(enabled);
835 #endif
836 }
837 
838 /*---------------------------------------------------------------
839  axis_equal
840  ---------------------------------------------------------------*/
842 {
843 #if MRPT_HAS_WXWIDGETS
844  if (!isOpen()) return;
845 
846  // Send a request to destroy this object:
849  REQ->sourcePlots = this;
850  REQ->OPCODE = 411;
851  REQ->boolVal = enabled;
853 #else
854  MRPT_UNUSED_PARAM(enabled);
855 #endif
856 }
857 
858 /*---------------------------------------------------------------
859  axis
860  ---------------------------------------------------------------*/
862  float x_min, float x_max, float y_min, float y_max, bool aspectRatioFix)
863 {
864 #if MRPT_HAS_WXWIDGETS
865  if (!isOpen()) return;
866 
867  // Send a request to destroy this object:
870  REQ->sourcePlots = this;
871  REQ->OPCODE = 412;
872  REQ->vector_x.resize(2);
873  REQ->vector_x[0] = x_min;
874  REQ->vector_x[1] = x_max;
875  REQ->vector_y.resize(2);
876  REQ->vector_y[0] = y_min;
877  REQ->vector_y[1] = y_max;
878  REQ->boolVal = aspectRatioFix;
880 #else
881  MRPT_UNUSED_PARAM(x_min);
882  MRPT_UNUSED_PARAM(x_max);
883  MRPT_UNUSED_PARAM(y_min);
884  MRPT_UNUSED_PARAM(y_max);
885  MRPT_UNUSED_PARAM(aspectRatioFix);
886 #endif
887 }
888 
889 /*---------------------------------------------------------------
890  axis_fit
891  ---------------------------------------------------------------*/
892 void CDisplayWindowPlots::axis_fit(bool aspectRatioFix)
893 {
894 #if MRPT_HAS_WXWIDGETS
895  if (!isOpen()) return;
896 
897  // Send a request to destroy this object:
900  REQ->sourcePlots = this;
901  REQ->OPCODE = 413;
902  REQ->boolVal = aspectRatioFix;
904 #else
905  MRPT_UNUSED_PARAM(aspectRatioFix);
906 #endif
907 }
908 
909 /*---------------------------------------------------------------
910  plotEllipse
911  ---------------------------------------------------------------*/
912 template <typename T>
914  const T mean_x, const T mean_y, const CMatrixTemplateNumeric<T>& cov22,
915  const float quantiles, const std::string& lineFormat,
916  const std::string& plotName, bool showName)
917 {
918 #if MRPT_HAS_WXWIDGETS
919  MRPT_START
920  if (!isOpen()) return;
921 
922  ASSERT_(cov22.cols() == 2 && cov22.rows() == 2);
923  ASSERT_(cov22(0, 0) >= 0);
924  ASSERT_(cov22(1, 1) >= 0);
925  ASSERT_(cov22(0, 1) == cov22(1, 0));
926 
928  {
929  m_holdon_just_disabled = false;
930  this->clf();
931  }
932  std::string holdon_post;
933  if (m_holdon)
934  holdon_post =
935  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
936 
937  // Send a request to destroy this object:
940  REQ->sourcePlots = this;
941  REQ->OPCODE = 421;
942  // 421: Add/update a 2D ellipse: format string=str, plot name =plotName,
943  // vector_x[0,1]:X/Y center, vector_y[0,1,2]: Covariance matrix entries
944  // 00,11,01.
945  REQ->str = lineFormat;
946  REQ->plotName = plotName + holdon_post;
947 
948  REQ->vector_x.resize(3);
949  REQ->vector_x[0] = mean_x;
950  REQ->vector_x[1] = mean_y;
951  REQ->vector_x[2] = quantiles;
952 
953  REQ->vector_y.resize(3);
954  REQ->vector_y[0] = cov22(0, 0);
955  REQ->vector_y[1] = cov22(1, 1);
956  REQ->vector_y[2] = cov22(0, 1);
957 
958  REQ->boolVal = showName;
959 
961  MRPT_END
962 #else
963  MRPT_UNUSED_PARAM(mean_x);
964  MRPT_UNUSED_PARAM(mean_y);
965  MRPT_UNUSED_PARAM(cov22);
966  MRPT_UNUSED_PARAM(quantiles);
967  MRPT_UNUSED_PARAM(lineFormat);
968  MRPT_UNUSED_PARAM(plotName);
969  MRPT_UNUSED_PARAM(showName);
970 #endif
971 }
972 
973 // Explicit instantations:
975  const float mean_x, const float mean_y,
976  const CMatrixTemplateNumeric<float>& cov22, const float quantiles,
977  const std::string& lineFormat, const std::string& plotName, bool showName);
979  const double mean_x, const double mean_y,
980  const CMatrixTemplateNumeric<double>& cov22, const float quantiles,
981  const std::string& lineFormat, const std::string& plotName, bool showName);
982 
983 /*---------------------------------------------------------------
984  plotEllipse
985  ---------------------------------------------------------------*/
986 template <typename T>
988  const T mean_x, const T mean_y, const CMatrixFixedNumeric<T, 2, 2>& cov22,
989  const float quantiles, const std::string& lineFormat,
990  const std::string& plotName, bool showName)
991 {
992 #if MRPT_HAS_WXWIDGETS
993  MRPT_START
994  if (!isOpen()) return;
995 
996  ASSERT_(cov22(0, 0) >= 0);
997  ASSERT_(cov22(1, 1) >= 0);
998  ASSERT_(cov22(0, 1) == cov22(1, 0));
999 
1001  {
1002  m_holdon_just_disabled = false;
1003  this->clf();
1004  }
1005  std::string holdon_post;
1006  if (m_holdon)
1007  holdon_post =
1008  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1009 
1010  // Send a request to destroy this object:
1013  REQ->sourcePlots = this;
1014  REQ->OPCODE = 421;
1015  // 421: Add/update a 2D ellipse: format string=str, plot name =plotName,
1016  // vector_x[0,1]:X/Y center, vector_y[0,1,2]: Covariance matrix entries
1017  // 00,11,01.
1018  REQ->str = lineFormat;
1019  REQ->plotName = plotName + holdon_post;
1020 
1021  REQ->vector_x.resize(3);
1022  REQ->vector_x[0] = mean_x;
1023  REQ->vector_x[1] = mean_y;
1024  REQ->vector_x[2] = quantiles;
1025 
1026  REQ->vector_y.resize(3);
1027  REQ->vector_y[0] = cov22(0, 0);
1028  REQ->vector_y[1] = cov22(1, 1);
1029  REQ->vector_y[2] = cov22(0, 1);
1030 
1031  REQ->boolVal = showName;
1032 
1034  MRPT_END
1035 #else
1036  MRPT_UNUSED_PARAM(mean_x);
1037  MRPT_UNUSED_PARAM(mean_y);
1038  MRPT_UNUSED_PARAM(cov22);
1039  MRPT_UNUSED_PARAM(quantiles);
1040  MRPT_UNUSED_PARAM(lineFormat);
1041  MRPT_UNUSED_PARAM(plotName);
1042  MRPT_UNUSED_PARAM(showName);
1043 #endif
1044 }
1045 
1046 // Explicit instantations:
1047 template void CDisplayWindowPlots::plotEllipse(
1048  const float mean_x, const float mean_y,
1049  const CMatrixFixedNumeric<float, 2, 2>& cov22, const float quantiles,
1050  const std::string& lineFormat, const std::string& plotName, bool showName);
1051 template void CDisplayWindowPlots::plotEllipse(
1052  const double mean_x, const double mean_y,
1053  const CMatrixFixedNumeric<double, 2, 2>& cov22, const float quantiles,
1054  const std::string& lineFormat, const std::string& plotName, bool showName);
1055 
1056 /*---------------------------------------------------------------
1057  image
1058  ---------------------------------------------------------------*/
1060  const mrpt::img::CImage& img, const float& x_left, const float& y_bottom,
1061  const float& x_width, const float& y_height, const std::string& plotName)
1062 {
1063 #if MRPT_HAS_WXWIDGETS
1064  MRPT_START
1065  if (!isOpen()) return;
1066 
1068  {
1069  m_holdon_just_disabled = false;
1070  this->clf();
1071  }
1072  std::string holdon_post;
1073  if (m_holdon)
1074  holdon_post =
1075  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1076 
1077  // Send a request to destroy this object:
1080  REQ->sourcePlots = this;
1081  REQ->OPCODE = 422;
1082 
1083  // 422: Add/update a bitmap: plot name =plotName, vector_x[0,1]:X/Y corner,
1084  // vector_x[2,3]: X/Y widths, voidPtr2: pointer to a newly created wxImage
1085  // with the bitmap.
1086  REQ->plotName = plotName + holdon_post;
1087 
1088  REQ->vector_x.resize(4);
1089  REQ->vector_x[0] = x_left;
1090  REQ->vector_x[1] = y_bottom;
1091  REQ->vector_x[2] = x_width;
1092  REQ->vector_x[3] = y_height;
1093 
1095 
1097  MRPT_END
1098 #else
1100  MRPT_UNUSED_PARAM(x_left);
1101  MRPT_UNUSED_PARAM(y_bottom);
1102  MRPT_UNUSED_PARAM(x_width);
1103  MRPT_UNUSED_PARAM(y_height);
1104  MRPT_UNUSED_PARAM(plotName);
1105 #endif
1106 }
1107 
1108 /*---------------------------------------------------------------
1109  internal_plot
1110  ---------------------------------------------------------------*/
1112  CVectorFloat& x, CVectorFloat& y, const std::string& lineFormat,
1113  const std::string& plotName)
1114 {
1115 #if MRPT_HAS_WXWIDGETS
1116  MRPT_START
1117  if (!isOpen()) return;
1118 
1119  ASSERT_EQUAL_(x.size(), y.size());
1120 
1122  {
1123  m_holdon_just_disabled = false;
1124  this->clf();
1125  }
1126 
1127  if (x.empty()) return;
1128 
1129  std::string holdon_post;
1130  if (m_holdon)
1131  holdon_post =
1132  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1133 
1134  // Send a request to destroy this object:
1137  REQ->sourcePlots = this;
1138  REQ->OPCODE = 420;
1139  REQ->str = lineFormat;
1140  REQ->plotName = plotName + holdon_post;
1141  REQ->vector_x.swap(x);
1142  REQ->vector_y.swap(y);
1143 
1145  MRPT_END
1146 #else
1149  MRPT_UNUSED_PARAM(lineFormat);
1150  MRPT_UNUSED_PARAM(plotName);
1151 #endif
1152 }
1153 
1154 /*---------------------------------------------------------------
1155  clear
1156  ---------------------------------------------------------------*/
1158 {
1159  MRPT_START
1160 #if MRPT_HAS_WXWIDGETS
1161  if (!isOpen()) return;
1162 
1163  // Send a request to destroy this object:
1166  REQ->sourcePlots = this;
1167  REQ->OPCODE = 414;
1168 
1169  // 414: Clear all plot objects.
1170 
1172 #endif
1173  MRPT_END
1174 }
1175 
1176 /*---------------------------------------------------------------
1177  hold_on
1178  ---------------------------------------------------------------*/
1180 /*---------------------------------------------------------------
1181  hold_off
1182  ---------------------------------------------------------------*/
1184 {
1185  if (m_holdon)
1186  {
1187  m_holdon = false;
1188  m_holdon_just_disabled = true;
1189  }
1190 }
1191 
1192 /*---------------------------------------------------------------
1193  addPopupMenuEntry
1194  ---------------------------------------------------------------*/
1196  const std::string& label, int menuID)
1197 {
1198 #if MRPT_HAS_WXWIDGETS
1199  MRPT_START
1200  if (!isOpen()) return;
1201 
1204  REQ->sourcePlots = this;
1205  REQ->OPCODE = 440;
1206  REQ->plotName = label;
1207  REQ->x = menuID;
1208  // 440: Inser submenu in the popup menu.
1209 
1211  MRPT_END
1212 #else
1213  MRPT_UNUSED_PARAM(label);
1214  MRPT_UNUSED_PARAM(menuID);
1215 #endif
1216 }
1217 
1218 /*---------------------------------------------------------------
1219  setMenuCallback
1220  ---------------------------------------------------------------*/
1222  TCallbackMenu userFunction, void* userParam)
1223 {
1224  ASSERT_(userFunction != nullptr);
1225  m_callback = userFunction;
1226  m_callback_param = userParam;
1227 }
An event sent by a window upon resize.
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
An event sent by a window upon a mouse click, giving the (x,y) pixel coordinates. ...
#define MRPT_START
Definition: exceptions.h:262
The data structure for each inter-thread request:
Definition: WxSubsystem.h:190
const long ID_MENUITEM1
#define _U(x)
Definition: WxSubsystem.h:503
Create a GUI window and display plots with MATLAB-like interfaces and commands.
mrpt::void_ptr_noncopy m_hwnd
The window handle.
void enableMousePanZoom(bool enabled)
Enable/disable the feature of pan/zoom with the mouse (default=enabled)
std::string m_caption
The caption of the window.
static int notifyWindowCreation()
Atomically increments the number of windows created with the main frame as parent.
void OnMenuClose(wxCommandEvent &event)
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:44
The wx dialog for gui::CDisplayWindowPlots.
Definition: WxSubsystem.h:438
mrptKeyModifier
Definition: keycodes.h:157
void setPos(int x, int y) override
Changes the position of the window on the screen.
static wxBitmap getMRPTDefaultIcon()
bool m_holdon
Whether hold_on is enabled.
STL namespace.
void axis(float x_min, float x_max, float y_min, float y_max, bool aspectRatioFix=false)
Set the view area according to the passed coordinated.
void internal_plot(mrpt::math::CVectorFloat &x, mrpt::math::CVectorFloat &y, const std::string &lineFormat, const std::string &plotName)
void hold_off()
Disables keeping all the graphs (this is the default behavior).
wxImage * MRPTImage2wxImage(const mrpt::img::CImage &img)
Create a wxImage from a MRPT image.
Definition: WxUtils.cpp:28
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:297
An event sent by a window upon when it&#39;s about to be closed, either manually by the user or programma...
An event sent by a window when the mouse is moved over it.
GLenum GLsizei width
Definition: glext.h:3531
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
void axis_equal(bool enable=true)
Enable/disable the fixed X/Y aspect ratio fix feature (default=disabled).
CDisplayWindowPlots(const std::string &windowCaption=std::string(), unsigned int initialWidth=350, unsigned int initialHeight=300)
Constructor.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
void OnMenuSelected(wxCommandEvent &ev)
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
uint32_t m_holdon_cnt
Counter for hold_on.
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure.
Definition: exceptions.h:153
GLint GLvoid * img
Definition: glext.h:3763
bool isOpen()
Returns false if the user has already closed the window.
void plot(const mrpt::math::CVectorFloat &x, const mrpt::math::CVectorFloat &y, const std::string &lineFormat, const std::string &plotName)
Redirected from CDisplayWindowPlots::plot.
virtual bool getLastMousePosition(int &x, int &y) const override
Gets the last x,y pixel coordinates of the mouse.
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:37
void(*)(int menuID, float cursor_x, float cursor_y, void *userParam) TCallbackMenu
Type for the callback function used in setMenuCallback.
const long ID_MENUITEM2
An event sent by a window upon a char pressed by the user.
void addPopupMenuEntry(const std::string &label, int menuID)
Disables keeping all the graphs (this is the default behavior).
mrpt::gui::CDisplayWindow3D::Ptr win
GLsizei const GLchar ** string
Definition: glext.h:4101
mrptKeyModifier keyEventToMrptKeyModifier(const wxKeyEvent &ev)
Extracts the key modifiers from a wxKeyEvent.
Definition: WxUtils.cpp:1135
void image(void *theWxImage, const float &x0, const float &y0, const float &w, const float &h, const std::string &plotName)
Redirected from CDisplayWindowPlots::image.
void OnMouseMove(wxMouseEvent &event)
virtual ~CDisplayWindowPlots()
Destructor.
void clear()
Remove all plot objects in the display.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void axis_fit(bool aspectRatioFix=false)
Fix automatically the view area according to existing graphs.
std::shared_ptr< CDisplayWindowPlots > Ptr
void OnResize(wxSizeEvent &event)
This class implements the GUI thread required for the wxWidgets-based GUI.
Definition: WxSubsystem.h:97
Definition: inftrees.h:28
void hold_on()
Enables keeping all the graphs, instead of overwritting them.
void clf()
Remove all plot objects in the display (clear and clf do exactly the same).
void image(const mrpt::img::CImage &img, const float &x_left, const float &y_bottom, const float &x_width, const float &y_height, const std::string &plotName=std::string("image"))
Adds a bitmap image layer.
void setWindowTitle(const std::string &str) override
Changes the window title text.
void plotEllipse(const mrpt::math::CVectorFloat &x, const mrpt::math::CVectorFloat &y, const std::string &lineFormat, const std::string &plotName, bool showName=false)
Redirected from CDisplayWindowPlots::plotEllipse.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
#define MRPT_END
Definition: exceptions.h:266
static CDisplayWindowPlots::Ptr Create(const std::string &windowCaption, unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Class factory returning a smart pointer.
void OnMouseDown(wxMouseEvent &event)
mrpt::gui::CDisplayWindowPlots * sourcePlots
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:215
void destroyWxWindow()
Must be called by child classes in their destructors.
GLenum GLint GLint y
Definition: glext.h:3538
virtual void setCursorCross(bool cursorIsCross) override
Set cursor style to default (cursorIsCross=false) or to a cross (cursorIsCross=true) ...
void OnClose(wxCloseEvent &event)
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:14
void OnMenuPrint(wxCommandEvent &event)
void createWxWindow(unsigned int initialWidth, unsigned int initialHeight)
Must be called by child classes just within the constructor.
GLenum GLint x
Definition: glext.h:3538
void OnMenuAbout(wxCommandEvent &event)
GLenum GLsizei GLsizei height
Definition: glext.h:3554
std::string str
Parameters, depending on OPCODE.
Definition: WxSubsystem.h:223
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
const Scalar * const_iterator
Definition: eigen_plugins.h:27
The base class for GUI window classes.
void setMenuCallback(TCallbackMenu userFunction, void *userParam=nullptr)
Must be called to have a callback when the user selects one of the user-defined entries in the popup ...
void resize(unsigned int width, unsigned int height) override
Resizes the window, stretching the image to fit into the display area.
static int notifyWindowDestruction()
Atomically decrements the number of windows created with the main frame as parent.
void plotEllipse(const T mean_x, const T mean_y, const mrpt::math::CMatrixTemplateNumeric< T > &cov22, const float quantiles, const std::string &lineFormat=std::string("b-"), const std::string &plotName=std::string("plotEllipse"), bool showName=false)
Plots a 2D ellipse given its mean, covariance matrix, and Each call to this function creates a new pl...
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:130
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
Definition: os.cpp:356
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020