Main MRPT website > C++ reference for 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-2017, 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/utils/CImage.h>
17 #include <mrpt/gui/WxSubsystem.h>
18 #include <mrpt/gui/WxUtils.h>
19 
20 #include <mrpt/math/utils.h>
21 
22 using namespace mrpt;
23 using namespace mrpt::gui;
24 using namespace mrpt::utils;
25 using namespace mrpt::math;
26 using namespace mrpt::system;
27 using namespace std;
28 
29 #if MRPT_HAS_WXWIDGETS
30 
31 BEGIN_EVENT_TABLE(CWindowDialogPlots, wxFrame)
32 
33 END_EVENT_TABLE()
34 
35 const long CWindowDialogPlots::ID_PLOT = wxNewId();
36 const long CWindowDialogPlots::ID_MENU_PRINT = wxNewId();
37 const long ID_MENUITEM1 = wxNewId();
38 const long ID_MENUITEM2 = wxNewId();
39 
41  CDisplayWindowPlots* winPlots, WxSubsystem::CWXMainFrame* parent,
42  wxWindowID id, const std::string& caption, wxSize initialSize)
43  : m_winPlots(winPlots), m_mainFrame(parent), m_firstSubmenu(true)
44 {
45  Create(
46  parent, id, _U(caption.c_str()), wxDefaultPosition, initialSize,
47  wxDEFAULT_FRAME_STYLE, _T("id"));
48 
49  SetClientSize(initialSize);
50 
51  wxIcon FrameIcon;
52  FrameIcon.CopyFromBitmap(mrpt::gui::WxSubsystem::getMRPTDefaultIcon());
53  SetIcon(FrameIcon);
54 
55  // Create the mpWindow object:
56  m_plot = new mpWindow(this, ID_PLOT);
57  m_plot->AddLayer(new mpScaleX());
58  m_plot->AddLayer(new mpScaleY());
59  m_plot->LockAspect(false);
60  m_plot->EnableDoubleBuffer(true);
61 
62  m_plot->Fit(-10, 10, -10, 10);
63 
64  // Menu:
65  wxMenuBar* MenuBar1 = new wxMenuBar();
66 
67  wxMenu* Menu1 = new wxMenu();
68  wxMenuItem* MenuItem1 =
69  new wxMenuItem(Menu1, ID_MENUITEM1, _("Close"), _(""), wxITEM_NORMAL);
70  Menu1->Append(MenuItem1);
71 
72  wxMenuItem* MenuItemPrint = new wxMenuItem(
73  Menu1, ID_MENU_PRINT, _("Print..."), _(""), wxITEM_NORMAL);
74  Menu1->Append(MenuItemPrint);
75 
76  MenuBar1->Append(Menu1, _("&File"));
77 
78  wxMenu* Menu2 = new wxMenu();
79  wxMenuItem* MenuItem2 = new wxMenuItem(
80  Menu2, ID_MENUITEM2, _("About..."), _(""), wxITEM_NORMAL);
81  Menu2->Append(MenuItem2);
82  MenuBar1->Append(Menu2, _("&Help"));
83 
84  SetMenuBar(MenuBar1);
85 
86  // Events:
87  Connect(
88  wxID_ANY, wxEVT_CLOSE_WINDOW,
89  (wxObjectEventFunction)&CWindowDialogPlots::OnClose);
90  Connect(
91  ID_MENUITEM1, wxEVT_COMMAND_MENU_SELECTED,
92  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuClose);
93  Connect(
94  ID_MENU_PRINT, wxEVT_COMMAND_MENU_SELECTED,
95  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuPrint);
96  Connect(
97  ID_MENUITEM2, wxEVT_COMMAND_MENU_SELECTED,
98  (wxObjectEventFunction)&CWindowDialogPlots::OnMenuAbout);
99 
100  Connect(
101  wxID_ANY, wxEVT_SIZE,
102  (wxObjectEventFunction)&CWindowDialogPlots::OnResize);
103 
104  Connect(
105  wxID_ANY, wxEVT_CHAR,
106  (wxObjectEventFunction)&CWindowDialogPlots::OnChar);
107  m_plot->Connect(
108  wxEVT_CHAR, (wxObjectEventFunction)&CWindowDialogPlots::OnChar, 0,
109  this);
110  m_plot->Connect(
111  wxEVT_MOTION, (wxObjectEventFunction)&CWindowDialogPlots::OnMouseMove,
112  0, this);
113 
114  m_plot->Connect(
115  wxEVT_LEFT_DOWN,
116  (wxObjectEventFunction)&CWindowDialogPlots::OnMouseDown, nullptr, this);
117  m_plot->Connect(
118  wxEVT_RIGHT_DOWN,
119  (wxObjectEventFunction)&CWindowDialogPlots::OnMouseDown, nullptr, this);
120 
121  // Increment number of windows:
122  // int winCount =
124 // cout << "[CWindowDialogPlots] Notifying new window: " << winCount << 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, TPixelCoord(event.GetX(), event.GetY()),
302  event.LeftDown(), event.RightDown()));
303  }
304  catch (...)
305  {
306  }
307  }
308  event.Skip(); // so it's processed by the wx system!
309 }
310 
311 // Add / Modify a 2D plot using a MATLAB-like format string
313  const CVectorFloat& x, const CVectorFloat& y, const std::string& lineFormat,
314  const std::string& plotName)
315 {
316  mpFXYVector* theLayer;
317 
318  wxString lyName = _U(plotName.c_str());
319  bool updateAtTheEnd = false; // If we update an existing layer, update
320  // manually to refresh the changes!
321 
322  // Already existing layer?
323  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
324 
325  if (existingLy)
326  {
327  // Assure the class:
328  mpFXYVector* lyPlot2D = static_cast<mpFXYVector*>(existingLy);
329 
330  if (!lyPlot2D)
331  {
332  cerr << "[CWindowDialogPlots::plot] Plot name '" << plotName
333  << "' is not of expected class mpFXYVector!." << endl;
334  return;
335  }
336 
337  // Ok:
338  theLayer = lyPlot2D;
339  updateAtTheEnd = true;
340  }
341  else
342  {
343  // Create it:
344  theLayer = new mpFXYVector(lyName);
345  m_plot->AddLayer(theLayer);
346  }
347 
348  // Set data:
349  {
350  std::vector<float> x_(x.size()), y_(x.size());
351  ::memcpy(&x_[0], &x[0], sizeof(x[0]) * x_.size());
352  ::memcpy(&y_[0], &y[0], sizeof(y[0]) * y_.size());
353  theLayer->SetData(x_, y_);
354  }
355 
356  // Line style:
357  // -------------------
358  bool isContinuous = true;
359  int lineColor[] = {0, 0, 255};
360  int lineWidth = 1;
361  int lineStyle = wxSOLID;
362 
363  // parse string:
364  if (string::npos != lineFormat.find("."))
365  {
366  isContinuous = false;
367  }
368  if (string::npos != lineFormat.find("-"))
369  {
370  isContinuous = true;
371  lineStyle = wxSOLID;
372  }
373  if (string::npos != lineFormat.find(":"))
374  {
375  isContinuous = true;
376  lineStyle = wxLONG_DASH;
377  }
378 
379  if (string::npos != lineFormat.find("r"))
380  {
381  lineColor[0] = 0xFF;
382  lineColor[1] = 0x00;
383  lineColor[2] = 0x00;
384  }
385  if (string::npos != lineFormat.find("g"))
386  {
387  lineColor[0] = 0x00;
388  lineColor[1] = 0xFF;
389  lineColor[2] = 0x00;
390  }
391  if (string::npos != lineFormat.find("b"))
392  {
393  lineColor[0] = 0x00;
394  lineColor[1] = 0x00;
395  lineColor[2] = 0xFF;
396  }
397  if (string::npos != lineFormat.find("k"))
398  {
399  lineColor[0] = 0x00;
400  lineColor[1] = 0x00;
401  lineColor[2] = 0x00;
402  }
403  if (string::npos != lineFormat.find("m"))
404  {
405  lineColor[0] = 192;
406  lineColor[1] = 0;
407  lineColor[2] = 192;
408  }
409  if (string::npos != lineFormat.find("c"))
410  {
411  lineColor[0] = 0;
412  lineColor[1] = 192;
413  lineColor[2] = 192;
414  }
415 
416  if (string::npos != lineFormat.find("1"))
417  {
418  lineWidth = 1;
419  }
420  if (string::npos != lineFormat.find("2"))
421  {
422  lineWidth = 2;
423  }
424  if (string::npos != lineFormat.find("3"))
425  {
426  lineWidth = 3;
427  }
428  if (string::npos != lineFormat.find("4"))
429  {
430  lineWidth = 4;
431  }
432  if (string::npos != lineFormat.find("5"))
433  {
434  lineWidth = 5;
435  }
436  if (string::npos != lineFormat.find("6"))
437  {
438  lineWidth = 6;
439  }
440  if (string::npos != lineFormat.find("7"))
441  {
442  lineWidth = 7;
443  }
444  if (string::npos != lineFormat.find("8"))
445  {
446  lineWidth = 8;
447  }
448  if (string::npos != lineFormat.find("9"))
449  {
450  lineWidth = 9;
451  }
452 
453  theLayer->SetContinuity(isContinuous);
454 
455  wxPen pen(
456  wxColour(lineColor[0], lineColor[1], lineColor[2]), lineWidth,
457  lineStyle);
458  theLayer->SetPen(pen);
459 
460  theLayer->ShowName(false);
461 
462  if (updateAtTheEnd) m_plot->Refresh(false);
463 }
464 
465 // Add / Modify a 2D ellipse
466 // x[0,1]: Mean
467 // y[0,1,2]: Covariance matrix (0,0),(1,1),(0,1)
469  const CVectorFloat& x, const CVectorFloat& y, const std::string& lineFormat,
470  const std::string& plotName, bool showName)
471 {
472  mpCovarianceEllipse* theLayer;
473 
474  if (x.size() != 3 || y.size() != 3)
475  {
476  cerr << "[CWindowDialogPlots::plotEllipse] vectors do not have "
477  "expected size!!"
478  << endl;
479  return;
480  }
481 
482  wxString lyName = _U(plotName.c_str());
483  bool updateAtTheEnd = false; // If we update an existing layer, update
484  // manually to refresh the changes!
485 
486  // Already existing layer?
487  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
488 
489  if (existingLy)
490  {
491  // Assure the class:
492  mpCovarianceEllipse* lyPlotEllipse =
493  static_cast<mpCovarianceEllipse*>(existingLy);
494 
495  if (!lyPlotEllipse)
496  {
497  cerr << "[CWindowDialogPlots::plotEllipse] Plot name '" << plotName
498  << "' is not of expected class mpCovarianceEllipse!." << endl;
499  return;
500  }
501 
502  // Ok:
503  theLayer = lyPlotEllipse;
504  updateAtTheEnd = true;
505  }
506  else
507  {
508  // Create it:
509  theLayer = new mpCovarianceEllipse(1, 1, 0, 2, 32, lyName);
510  m_plot->AddLayer(theLayer);
511  }
512 
513  // Set data:
514  theLayer->SetCovarianceMatrix(y[0], y[2], y[1]);
515  theLayer->SetCoordinateBase(x[0], x[1]);
516  theLayer->SetQuantiles(x[2]);
517  theLayer->ShowName(showName);
518 
519  // Line style:
520  // -------------------
521  bool isContinuous = true;
522  int lineColor[] = {0, 0, 255};
523  int lineWidth = 1;
524  int lineStyle = wxSOLID;
525 
526  // parse string:
527  if (string::npos != lineFormat.find("."))
528  {
529  isContinuous = false;
530  }
531  if (string::npos != lineFormat.find("-"))
532  {
533  isContinuous = true;
534  lineStyle = wxSOLID;
535  }
536  if (string::npos != lineFormat.find(":"))
537  {
538  isContinuous = true;
539  lineStyle = wxLONG_DASH;
540  }
541 
542  if (string::npos != lineFormat.find("r"))
543  {
544  lineColor[0] = 0xFF;
545  lineColor[1] = 0x00;
546  lineColor[2] = 0x00;
547  }
548  if (string::npos != lineFormat.find("g"))
549  {
550  lineColor[0] = 0x00;
551  lineColor[1] = 0xFF;
552  lineColor[2] = 0x00;
553  }
554  if (string::npos != lineFormat.find("b"))
555  {
556  lineColor[0] = 0x00;
557  lineColor[1] = 0x00;
558  lineColor[2] = 0xFF;
559  }
560  if (string::npos != lineFormat.find("k"))
561  {
562  lineColor[0] = 0x00;
563  lineColor[1] = 0x00;
564  lineColor[2] = 0x00;
565  }
566  if (string::npos != lineFormat.find("m"))
567  {
568  lineColor[0] = 192;
569  lineColor[1] = 0;
570  lineColor[2] = 192;
571  }
572  if (string::npos != lineFormat.find("c"))
573  {
574  lineColor[0] = 0;
575  lineColor[1] = 192;
576  lineColor[2] = 192;
577  }
578 
579  if (string::npos != lineFormat.find("1"))
580  {
581  lineWidth = 1;
582  }
583  if (string::npos != lineFormat.find("2"))
584  {
585  lineWidth = 2;
586  }
587  if (string::npos != lineFormat.find("3"))
588  {
589  lineWidth = 3;
590  }
591  if (string::npos != lineFormat.find("4"))
592  {
593  lineWidth = 4;
594  }
595  if (string::npos != lineFormat.find("5"))
596  {
597  lineWidth = 5;
598  }
599  if (string::npos != lineFormat.find("6"))
600  {
601  lineWidth = 6;
602  }
603  if (string::npos != lineFormat.find("7"))
604  {
605  lineWidth = 7;
606  }
607  if (string::npos != lineFormat.find("8"))
608  {
609  lineWidth = 8;
610  }
611  if (string::npos != lineFormat.find("9"))
612  {
613  lineWidth = 9;
614  }
615 
616  theLayer->SetContinuity(isContinuous);
617 
618  wxPen pen(
619  wxColour(lineColor[0], lineColor[1], lineColor[2]), lineWidth,
620  lineStyle);
621  theLayer->SetPen(pen);
622 
623  if (updateAtTheEnd) m_plot->Refresh(false);
624 }
625 
627  void* theWxImage, const float& x0, const float& y0, const float& w,
628  const float& h, const std::string& plotName)
629 {
630  mpBitmapLayer* theLayer;
631 
632  wxString lyName = _U(plotName.c_str());
633  bool updateAtTheEnd = false; // If we update an existing layer, update
634  // manually to refresh the changes!
635 
636  // Already existing layer?
637  mpLayer* existingLy = m_plot->GetLayerByName(lyName);
638 
639  if (existingLy)
640  {
641  // Assure the class:
642  mpBitmapLayer* ly = static_cast<mpBitmapLayer*>(existingLy);
643 
644  if (!ly)
645  {
646  cerr << "[CWindowDialogPlots::image] Plot name '" << plotName
647  << "' is not of expected class mpBitmapLayer!." << endl;
648  return;
649  }
650 
651  // Ok:
652  theLayer = ly;
653  updateAtTheEnd = true;
654  }
655  else
656  {
657  // Create it:
658  theLayer = new mpBitmapLayer();
659  m_plot->AddLayer(theLayer);
660  }
661 
662  // Set data:
663  wxImage* ii = static_cast<wxImage*>(theWxImage);
664  theLayer->SetBitmap(*ii, x0, y0, w, h);
665 
666  delete ii;
667  theWxImage = nullptr;
668 
669  if (updateAtTheEnd) m_plot->Refresh();
670 }
671 
672 #endif
673 
675  const std::string& windowCaption, unsigned int initialWindowWidth,
676  unsigned int initialWindowHeight)
677 {
680  windowCaption, initialWindowWidth, initialWindowHeight));
681 }
682 /*---------------------------------------------------------------
683  Constructor
684  ---------------------------------------------------------------*/
686  const std::string& windowCaption, unsigned int initialWidth,
687  unsigned int initialHeight)
688  : CBaseGUIWindow(static_cast<void*>(this), 400, 499, windowCaption),
689  m_holdon(false),
690  m_holdon_just_disabled(false),
691  m_holdon_cnt(0),
692  m_callback(nullptr),
693  m_callback_param(nullptr)
694 {
695  CBaseGUIWindow::createWxWindow(initialWidth, initialHeight);
696 }
697 
698 /*---------------------------------------------------------------
699  Destructor
700  ---------------------------------------------------------------*/
702 {
704 }
705 
706 /** Set cursor style to default (cursorIsCross=false) or to a cross
707  * (cursorIsCross=true) */
708 void CDisplayWindowPlots::setCursorCross(bool cursorIsCross)
709 {
710 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
711  const CWindowDialogPlots* win = (const CWindowDialogPlots*)m_hwnd.get();
712  if (!win) return;
713  win->m_plot->SetCursor(
714  *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
715 #else
716  MRPT_UNUSED_PARAM(cursorIsCross);
717 #endif
718 }
719 
720 /*---------------------------------------------------------------
721  getLastMousePosition
722  ---------------------------------------------------------------*/
724 {
725 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
726  const CWindowDialogPlots* win = (const CWindowDialogPlots*)m_hwnd.get();
727  if (!win) return false;
728  x = win->m_last_mouse_point.x;
729  y = win->m_last_mouse_point.y;
730  return true;
731 #else
734  return false;
735 #endif
736 }
737 
738 /*---------------------------------------------------------------
739  resize
740  ---------------------------------------------------------------*/
741 void CDisplayWindowPlots::resize(unsigned int width, unsigned int height)
742 {
743 #if MRPT_HAS_WXWIDGETS
744  if (!isOpen())
745  {
746  cerr << "[CDisplayWindowPlots::resize] Window closed!: " << m_caption
747  << endl;
748  return;
749  }
750 
751  // Send a request to destroy this object:
754  REQ->sourcePlots = this;
755  REQ->OPCODE = 403;
756  REQ->x = width;
757  REQ->y = height;
759 #else
762 #endif
763 }
764 
765 /*---------------------------------------------------------------
766  setPos
767  ---------------------------------------------------------------*/
769 {
770 #if MRPT_HAS_WXWIDGETS
771  if (!isOpen())
772  {
773  cerr << "[CDisplayWindowPlots::setPos] Window closed!: " << m_caption
774  << endl;
775  return;
776  }
777 
778  // Send a request to destroy this object:
781  REQ->sourcePlots = this;
782  REQ->OPCODE = 402;
783  REQ->x = x;
784  REQ->y = y;
786 #else
789 #endif
790 }
791 
792 /*---------------------------------------------------------------
793  setWindowTitle
794  ---------------------------------------------------------------*/
796 {
797 #if MRPT_HAS_WXWIDGETS
798  if (!isOpen())
799  {
800  cerr << "[CDisplayWindowPlots::setWindowTitle] Window closed!: "
801  << m_caption << endl;
802  return;
803  }
804 
805  // Send a request to destroy this object:
808  REQ->sourcePlots = this;
809  REQ->OPCODE = 404;
810  REQ->str = str;
812 #else
813  MRPT_UNUSED_PARAM(str);
814 #endif
815 }
816 
817 /*---------------------------------------------------------------
818  enableMousePanZoom
819  ---------------------------------------------------------------*/
821 {
822 #if MRPT_HAS_WXWIDGETS
823  if (!isOpen()) return;
824 
825  // Send a request to destroy this object:
828  REQ->sourcePlots = this;
829  REQ->OPCODE = 410;
830  REQ->boolVal = enabled;
832 #else
833  MRPT_UNUSED_PARAM(enabled);
834 #endif
835 }
836 
837 /*---------------------------------------------------------------
838  axis_equal
839  ---------------------------------------------------------------*/
841 {
842 #if MRPT_HAS_WXWIDGETS
843  if (!isOpen()) return;
844 
845  // Send a request to destroy this object:
848  REQ->sourcePlots = this;
849  REQ->OPCODE = 411;
850  REQ->boolVal = enabled;
852 #else
853  MRPT_UNUSED_PARAM(enabled);
854 #endif
855 }
856 
857 /*---------------------------------------------------------------
858  axis
859  ---------------------------------------------------------------*/
861  float x_min, float x_max, float y_min, float y_max, bool aspectRatioFix)
862 {
863 #if MRPT_HAS_WXWIDGETS
864  if (!isOpen()) return;
865 
866  // Send a request to destroy this object:
869  REQ->sourcePlots = this;
870  REQ->OPCODE = 412;
871  REQ->vector_x.resize(2);
872  REQ->vector_x[0] = x_min;
873  REQ->vector_x[1] = x_max;
874  REQ->vector_y.resize(2);
875  REQ->vector_y[0] = y_min;
876  REQ->vector_y[1] = y_max;
877  REQ->boolVal = aspectRatioFix;
879 #else
880  MRPT_UNUSED_PARAM(x_min);
881  MRPT_UNUSED_PARAM(x_max);
882  MRPT_UNUSED_PARAM(y_min);
883  MRPT_UNUSED_PARAM(y_max);
884  MRPT_UNUSED_PARAM(aspectRatioFix);
885 #endif
886 }
887 
888 /*---------------------------------------------------------------
889  axis_fit
890  ---------------------------------------------------------------*/
891 void CDisplayWindowPlots::axis_fit(bool aspectRatioFix)
892 {
893 #if MRPT_HAS_WXWIDGETS
894  if (!isOpen()) return;
895 
896  // Send a request to destroy this object:
899  REQ->sourcePlots = this;
900  REQ->OPCODE = 413;
901  REQ->boolVal = aspectRatioFix;
903 #else
904  MRPT_UNUSED_PARAM(aspectRatioFix);
905 #endif
906 }
907 
908 /*---------------------------------------------------------------
909  plotEllipse
910  ---------------------------------------------------------------*/
911 template <typename T>
913  const T mean_x, const T mean_y, const CMatrixTemplateNumeric<T>& cov22,
914  const float quantiles, const std::string& lineFormat,
915  const std::string& plotName, bool showName)
916 {
917 #if MRPT_HAS_WXWIDGETS
918  MRPT_START
919  if (!isOpen()) return;
920 
921  ASSERT_(cov22.getColCount() == 2 && cov22.getRowCount() == 2);
922  ASSERT_(cov22(0, 0) >= 0);
923  ASSERT_(cov22(1, 1) >= 0);
924  ASSERT_(cov22(0, 1) == cov22(1, 0));
925 
927  {
928  m_holdon_just_disabled = false;
929  this->clf();
930  }
931  std::string holdon_post;
932  if (m_holdon)
933  holdon_post =
934  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
935 
936  // Send a request to destroy this object:
939  REQ->sourcePlots = this;
940  REQ->OPCODE = 421;
941  // 421: Add/update a 2D ellipse: format string=str, plot name =plotName,
942  // vector_x[0,1]:X/Y center, vector_y[0,1,2]: Covariance matrix entries
943  // 00,11,01.
944  REQ->str = lineFormat;
945  REQ->plotName = plotName + holdon_post;
946 
947  REQ->vector_x.resize(3);
948  REQ->vector_x[0] = mean_x;
949  REQ->vector_x[1] = mean_y;
950  REQ->vector_x[2] = quantiles;
951 
952  REQ->vector_y.resize(3);
953  REQ->vector_y[0] = cov22(0, 0);
954  REQ->vector_y[1] = cov22(1, 1);
955  REQ->vector_y[2] = cov22(0, 1);
956 
957  REQ->boolVal = showName;
958 
960  MRPT_END
961 #else
962  MRPT_UNUSED_PARAM(mean_x);
963  MRPT_UNUSED_PARAM(mean_y);
964  MRPT_UNUSED_PARAM(cov22);
965  MRPT_UNUSED_PARAM(quantiles);
966  MRPT_UNUSED_PARAM(lineFormat);
967  MRPT_UNUSED_PARAM(plotName);
968  MRPT_UNUSED_PARAM(showName);
969 #endif
970 }
971 
972 // Explicit instantations:
974  const float mean_x, const float mean_y,
975  const CMatrixTemplateNumeric<float>& cov22, const float quantiles,
976  const std::string& lineFormat, const std::string& plotName, bool showName);
978  const double mean_x, const double mean_y,
979  const CMatrixTemplateNumeric<double>& cov22, const float quantiles,
980  const std::string& lineFormat, const std::string& plotName, bool showName);
981 
982 /*---------------------------------------------------------------
983  plotEllipse
984  ---------------------------------------------------------------*/
985 template <typename T>
987  const T mean_x, const T mean_y, const CMatrixFixedNumeric<T, 2, 2>& cov22,
988  const float quantiles, const std::string& lineFormat,
989  const std::string& plotName, bool showName)
990 {
991 #if MRPT_HAS_WXWIDGETS
992  MRPT_START
993  if (!isOpen()) return;
994 
995  ASSERT_(cov22(0, 0) >= 0);
996  ASSERT_(cov22(1, 1) >= 0);
997  ASSERT_(cov22(0, 1) == cov22(1, 0));
998 
1000  {
1001  m_holdon_just_disabled = false;
1002  this->clf();
1003  }
1004  std::string holdon_post;
1005  if (m_holdon)
1006  holdon_post =
1007  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1008 
1009  // Send a request to destroy this object:
1012  REQ->sourcePlots = this;
1013  REQ->OPCODE = 421;
1014  // 421: Add/update a 2D ellipse: format string=str, plot name =plotName,
1015  // vector_x[0,1]:X/Y center, vector_y[0,1,2]: Covariance matrix entries
1016  // 00,11,01.
1017  REQ->str = lineFormat;
1018  REQ->plotName = plotName + holdon_post;
1019 
1020  REQ->vector_x.resize(3);
1021  REQ->vector_x[0] = mean_x;
1022  REQ->vector_x[1] = mean_y;
1023  REQ->vector_x[2] = quantiles;
1024 
1025  REQ->vector_y.resize(3);
1026  REQ->vector_y[0] = cov22(0, 0);
1027  REQ->vector_y[1] = cov22(1, 1);
1028  REQ->vector_y[2] = cov22(0, 1);
1029 
1030  REQ->boolVal = showName;
1031 
1033  MRPT_END
1034 #else
1035  MRPT_UNUSED_PARAM(mean_x);
1036  MRPT_UNUSED_PARAM(mean_y);
1037  MRPT_UNUSED_PARAM(cov22);
1038  MRPT_UNUSED_PARAM(quantiles);
1039  MRPT_UNUSED_PARAM(lineFormat);
1040  MRPT_UNUSED_PARAM(plotName);
1041  MRPT_UNUSED_PARAM(showName);
1042 #endif
1043 }
1044 
1045 // Explicit instantations:
1046 template void CDisplayWindowPlots::plotEllipse(
1047  const float mean_x, const float mean_y,
1048  const CMatrixFixedNumeric<float, 2, 2>& cov22, const float quantiles,
1049  const std::string& lineFormat, const std::string& plotName, bool showName);
1050 template void CDisplayWindowPlots::plotEllipse(
1051  const double mean_x, const double mean_y,
1052  const CMatrixFixedNumeric<double, 2, 2>& cov22, const float quantiles,
1053  const std::string& lineFormat, const std::string& plotName, bool showName);
1054 
1055 /*---------------------------------------------------------------
1056  image
1057  ---------------------------------------------------------------*/
1059  const utils::CImage& img, const float& x_left, const float& y_bottom,
1060  const float& x_width, const float& y_height, const std::string& plotName)
1061 {
1062 #if MRPT_HAS_WXWIDGETS
1063  MRPT_START
1064  if (!isOpen()) return;
1065 
1067  {
1068  m_holdon_just_disabled = false;
1069  this->clf();
1070  }
1071  std::string holdon_post;
1072  if (m_holdon)
1073  holdon_post =
1074  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1075 
1076  // Send a request to destroy this object:
1079  REQ->sourcePlots = this;
1080  REQ->OPCODE = 422;
1081 
1082  // 422: Add/update a bitmap: plot name =plotName, vector_x[0,1]:X/Y corner,
1083  // vector_x[2,3]: X/Y widths, voidPtr2: pointer to a newly created wxImage
1084  // with the bitmap.
1085  REQ->plotName = plotName + holdon_post;
1086 
1087  REQ->vector_x.resize(4);
1088  REQ->vector_x[0] = x_left;
1089  REQ->vector_x[1] = y_bottom;
1090  REQ->vector_x[2] = x_width;
1091  REQ->vector_x[3] = y_height;
1092 
1094 
1096  MRPT_END
1097 #else
1099  MRPT_UNUSED_PARAM(x_left);
1100  MRPT_UNUSED_PARAM(y_bottom);
1101  MRPT_UNUSED_PARAM(x_width);
1102  MRPT_UNUSED_PARAM(y_height);
1103  MRPT_UNUSED_PARAM(plotName);
1104 #endif
1105 }
1106 
1107 /*---------------------------------------------------------------
1108  internal_plot
1109  ---------------------------------------------------------------*/
1111  CVectorFloat& x, CVectorFloat& y, const std::string& lineFormat,
1112  const std::string& plotName)
1113 {
1114 #if MRPT_HAS_WXWIDGETS
1115  MRPT_START
1116  if (!isOpen()) return;
1117 
1118  ASSERT_EQUAL_(x.size(), y.size());
1119 
1121  {
1122  m_holdon_just_disabled = false;
1123  this->clf();
1124  }
1125 
1126  if (x.empty()) return;
1127 
1128  std::string holdon_post;
1129  if (m_holdon)
1130  holdon_post =
1131  format("_fig_%u", static_cast<unsigned int>(m_holdon_cnt++));
1132 
1133  // Send a request to destroy this object:
1136  REQ->sourcePlots = this;
1137  REQ->OPCODE = 420;
1138  REQ->str = lineFormat;
1139  REQ->plotName = plotName + holdon_post;
1140  REQ->vector_x.swap(x);
1141  REQ->vector_y.swap(y);
1142 
1144  MRPT_END
1145 #else
1148  MRPT_UNUSED_PARAM(lineFormat);
1149  MRPT_UNUSED_PARAM(plotName);
1150 #endif
1151 }
1152 
1153 /*---------------------------------------------------------------
1154  clear
1155  ---------------------------------------------------------------*/
1157 {
1158  MRPT_START
1159 #if MRPT_HAS_WXWIDGETS
1160  if (!isOpen()) return;
1161 
1162  // Send a request to destroy this object:
1165  REQ->sourcePlots = this;
1166  REQ->OPCODE = 414;
1167 
1168  // 414: Clear all plot objects.
1169 
1171 #endif
1172  MRPT_END
1173 }
1174 
1175 /*---------------------------------------------------------------
1176  hold_on
1177  ---------------------------------------------------------------*/
1179 /*---------------------------------------------------------------
1180  hold_off
1181  ---------------------------------------------------------------*/
1183 {
1184  if (m_holdon)
1185  {
1186  m_holdon = false;
1187  m_holdon_just_disabled = true;
1188  }
1189 }
1190 
1191 /*---------------------------------------------------------------
1192  addPopupMenuEntry
1193  ---------------------------------------------------------------*/
1195  const std::string& label, int menuID)
1196 {
1197 #if MRPT_HAS_WXWIDGETS
1198  MRPT_START
1199  if (!isOpen()) return;
1200 
1203  REQ->sourcePlots = this;
1204  REQ->OPCODE = 440;
1205  REQ->plotName = label;
1206  REQ->x = menuID;
1207  // 440: Inser submenu in the popup menu.
1208 
1210  MRPT_END
1211 #else
1212  MRPT_UNUSED_PARAM(label);
1213  MRPT_UNUSED_PARAM(menuID);
1214 #endif
1215 }
1216 
1217 /*---------------------------------------------------------------
1218  setMenuCallback
1219  ---------------------------------------------------------------*/
1221  TCallbackMenu userFunction, void* userParam)
1222 {
1223  ASSERT_(userFunction != nullptr)
1224  m_callback = userFunction;
1225  m_callback_param = userParam;
1226 }
#define ASSERT_EQUAL_(__A, __B)
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. ...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
The data structure for each inter-thread request:
Definition: WxSubsystem.h:193
const long ID_MENUITEM1
#define _U(x)
Definition: WxSubsystem.h:506
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
Create a GUI window and display plots with MATLAB-like interfaces and commands.
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.
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
static int notifyWindowCreation()
Atomically increments the number of windows created with the main frame as parent.
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:38
void OnMenuClose(wxCommandEvent &event)
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
The wx dialog for gui::CDisplayWindowPlots.
Definition: WxSubsystem.h:441
mrptKeyModifier
Definition: keycodes.h:159
void setPos(int x, int y) override
Changes the position of the window on the screen.
wxPoint m_last_mouse_point
In pixels.
Definition: WxSubsystem.h:465
static wxBitmap getMRPTDefaultIcon()
bool m_holdon
Whether hold_on is enabled.
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:27
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).
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:300
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
void image(const utils::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.
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.
void OnMenuSelected(wxCommandEvent &ev)
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
#define MRPT_END
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
uint32_t m_holdon_cnt
Counter for hold_on.
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.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
const long ID_MENUITEM2
wxImage * MRPTImage2wxImage(const mrpt::utils::CImage &img)
Create a wxImage from a MRPT image.
Definition: WxUtils.cpp:29
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).
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.
#define MRPT_START
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:100
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 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.
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)
#define ASSERT_(f)
mrpt::gui::CDisplayWindowPlots * sourcePlots
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:218
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:16
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:226
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
mrpt::utils::void_ptr_noncopy m_hwnd
The window handle.
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...
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:355



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019