Main MRPT website > C++ reference
MRPT logo
mathplot.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mathplot.cpp
3 // Purpose: Framework for plotting in wxWindows
4 // Original Author: David Schalig
5 // Maintainer: Davide Rondini
6 // Contributors: Jose Luis Blanco, Val Greene
7 // Created: 21/07/2003
8 // Last edit: 22/02/2009
9 // Copyright: (c) David Schalig, Davide Rondini
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12 
13 #ifndef _MP_MATHPLOT_H_
14 #define _MP_MATHPLOT_H_
15 
16 // JL: This is VERY ugly, but ask MS why we cannot export a DLL class with STL members !!
17 #if defined(_MSC_VER)
18  #pragma warning(push)
19  #pragma warning(disable:4251)
20 #endif
21 
22 /** @file mathplot.h */
23 /** @mainpage wxMathPlot
24  wxMathPlot is a framework for mathematical graph plotting in wxWindows.
25 
26  The framework is designed for convenience and ease of use.
27 
28  @section screenshots Screenshots
29  <a href="http://wxmathplot.sourceforge.net/screenshot.shtml" >Go to the screenshots page.</a>
30 
31  @section overview Overview
32  The heart of wxMathPlot is mpWindow, which is a 2D canvas for plot layers.
33  mpWindow can be embedded as subwindow in a wxPane, a wxFrame, or any other wxWindow.
34  mpWindow provides a zoomable and moveable view of the layers. The current view can
35  be controlled with the mouse, the scrollbars, and a context menu.
36 
37  Plot layers are implementations of the abstract base class mpLayer. Those can
38  be function plots, scale rulers, or any other vector data visualisation. wxMathPlot provides two mpLayer implementations for plotting horizontal and vertical rulers: mpScaleX and mpScaleY.
39  For convenient function plotting a series of classes derived from mpLayer are provided, like mpFX, mpProfile, mpLegend and so on. These base classes already come with plot code, user's own functions can be implemented by overriding just one member for retrieving a function value.
40 
41  mpWindow has built-in support for mouse-based pan and zoom through intuitive combinations of buttons and the mouse wheel. It also incorporates an optional double buffering mechanism to avoid flicker. Plots can be easily sent to printer evices or exported in bitmap formats like PNG, BMP or JPEG.
42 
43  @section coding Coding conventions
44  wxMathPlot sticks to wxWindow's coding conventions. All entities defined by wxMathPlot have the prefix <i>mp</i>.
45 
46  @section author Author and license
47  wxMathPlot is published under the terms of the wxWindow license.<br>
48  The original author is David Schalig <mrhill@users.sourceforge.net>.<br>
49  From June 2007 the project is maintained by Davide Rondini <cdron77@users.sourceforge.net>.<br>
50  Authors can be contacted via the wxMathPlot's homepage at
51  https://sourceforge.net/projects/wxmathplot<br>
52  Contributors:<br>
53  Jose Luis Blanco, Val Greene.<br>
54 */
55 
56 //this definition uses windows dll to export function.
57 //WXDLLIMPEXP_MATHPLOT definition definition changed to WXDLLIMPEXP_MATHPLOT
58 //mathplot_EXPORTS will be defined by cmake
59 //#ifdef mathplot_EXPORTS
60 // #define WXDLLIMPEXP_MATHPLOT WXEXPORT
61 // #define WXDLLIMPEXP_DATA_MATHPLOT(type) WXEXPORT type
62 //#else // not making DLL
63 // #define WXDLLIMPEXP_MATHPLOT
64 // #define WXDLLIMPEXP_DATA_MATHPLOT(type) type
65 //#endif
66 
67 // Hack for MRPT: Link as part of mrpt-gui itself.
68 #include <mrpt/gui/link_pragmas.h>
69 #define WXDLLIMPEXP_MATHPLOT GUI_IMPEXP
70 
71 
72 #if defined(__GNUG__) && !defined(__APPLE__)
73 #pragma interface "mathplot.h"
74 #endif
75 
76 #include <vector>
77 
78 // #include <wx/wx.h>
79 #include <wx/defs.h>
80 #include <wx/menu.h>
81 #include <wx/scrolwin.h>
82 #include <wx/event.h>
83 #include <wx/dynarray.h>
84 #include <wx/pen.h>
85 #include <wx/dcmemory.h>
86 #include <wx/string.h>
87 #include <wx/print.h>
88 #include <wx/image.h>
89 
90 
91 #include <deque>
92 
93 // For memory leak debug
94 #ifdef _WINDOWS
95 #ifdef _DEBUG
96 #include <crtdbg.h>
97 #define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__)
98 #else
99 #define DEBUG_NEW new
100 #endif // _DEBUG
101 #endif // _WINDOWS
102 
103 // Separation for axes when set close to border
104 #define X_BORDER_SEPARATION 40
105 #define Y_BORDER_SEPARATION 60
106 
107 //-----------------------------------------------------------------------------
108 // classes
109 //-----------------------------------------------------------------------------
110 
121 
122 /** Command IDs used by mpWindow */
123 enum
124 {
125  mpID_FIT = 2000, //!< Fit view to match bounding box of all layers
126  mpID_ZOOM_IN, //!< Zoom into view at clickposition / window center
127  mpID_ZOOM_OUT, //!< Zoom out
128  mpID_CENTER, //!< Center view on click position
129  mpID_LOCKASPECT, //!< Lock x/y scaling aspect
130  mpID_HELP_MOUSE, //!< Shows information about the mouse commands
131  mpID_PRINT //!< JL: Prints the graph
132 };
133 
134 //-----------------------------------------------------------------------------
135 // mpLayer
136 //-----------------------------------------------------------------------------
137 
138 typedef enum __mp_Layer_Type {
139  mpLAYER_UNDEF, //!< Layer type undefined
140  mpLAYER_AXIS, //!< Axis type layer
141  mpLAYER_PLOT, //!< Plot type layer
142  mpLAYER_INFO, //!< Info box type layer
143  mpLAYER_BITMAP //!< Bitmap type layer
144 } mpLayerType;
145 
146 /** Plot layer, abstract base class.
147  Any number of mpLayer implementations can be attached to mpWindow.
148  Examples for mpLayer implementations are function graphs, or scale rulers.
149 
150  For convenience mpLayer defines a name, a font (wxFont), a pen (wxPen),
151  and a continuity property (bool) as class members.
152  The default values at constructor are the default font, a black pen, and
153  continuity set to false (draw separate points).
154  These may or may not be used by implementations.
155 */
156 class WXDLLIMPEXP_MATHPLOT mpLayer : public wxObject
157 {
158 public:
159  mpLayer();
160 
161  virtual ~mpLayer() {};
162 
163  /** Check whether this layer has a bounding box.
164  The default implementation returns \a TRUE. Override and return
165  FALSE if your mpLayer implementation should be ignored by the calculation
166  of the global bounding box for all layers in a mpWindow.
167  @retval TRUE Has bounding box
168  @retval FALSE Has not bounding box
169  */
170  virtual bool HasBBox() { return TRUE; }
171 
172  /** Check whether the layer is an info box.
173  The default implementation returns \a FALSE. It is overrided to \a TRUE for mpInfoLayer
174  class and its derivative. It is necessary to define mouse actions behaviour over
175  info boxes.
176  @return whether the layer is an info boxes
177  @sa mpInfoLayer::IsInfo */
178  virtual bool IsInfo() { return false; };
179 
180  /** Get inclusive left border of bounding box.
181  @return Value
182  */
183  virtual double GetMinX() { return -1.0; }
184 
185  /** Get inclusive right border of bounding box.
186  @return Value
187  */
188  virtual double GetMaxX() { return 1.0; }
189 
190  /** Get inclusive bottom border of bounding box.
191  @return Value
192  */
193  virtual double GetMinY() { return -1.0; }
194 
195  /** Get inclusive top border of bounding box.
196  @return Value
197  */
198  virtual double GetMaxY() { return 1.0; }
199 
200  /** Plot given view of layer to the given device context.
201  An implementation of this function has to transform layer coordinates to
202  wxDC coordinates based on the view parameters retrievable from the mpWindow
203  passed in \a w.
204  Note that the public methods of mpWindow: x2p,y2p and p2x,p2y are already provided
205  which transform layer coordinates to DC pixel coordinates, and <b>user code should rely
206  on them</b> for portability and future changes to be applied transparently, instead of
207  implementing the following formulas manually.
208 
209  The passed device context \a dc has its coordinate origin set to the top-left corner
210  of the visible area (the default). The coordinate orientation is as shown in the
211  following picture:
212  <pre>
213  (wxDC origin 0,0)
214  x-------------> ascending X ----------------+
215  | |
216  | |
217  V ascending Y |
218  | |
219  | |
220  | |
221  +-------------------------------------------+ <-- right-bottom corner of the mpWindow visible area.
222  </pre>
223  Note that Y ascends in downward direction, whereas the usual vertical orientation
224  for mathematical plots is vice versa. Thus Y-orientation will be swapped usually,
225  when transforming between wxDC and mpLayer coordinates. This change of coordinates
226  is taken into account in the methods p2x,p2y,x2p,y2p.
227 
228  <b> Rules for transformation between mpLayer and wxDC coordinates </b>
229  @code
230  dc_X = (layer_X - mpWindow::GetPosX()) * mpWindow::GetScaleX()
231  dc_Y = (mpWindow::GetPosY() - layer_Y) * mpWindow::GetScaleY() // swapping Y-orientation
232 
233  layer_X = (dc_X / mpWindow::GetScaleX()) + mpWindow::GetPosX() // scale guaranteed to be not 0
234  layer_Y = mpWindow::GetPosY() - (dc_Y / mpWindow::GetScaleY()) // swapping Y-orientation
235  @endcode
236 
237  @param dc Device context to plot to.
238  @param w View to plot. The visible area can be retrieved from this object.
239  @sa mpWindow::p2x,mpWindow::p2y,mpWindow::x2p,mpWindow::y2p
240  */
241  virtual void Plot(wxDC & dc, mpWindow & w) = 0;
242 
243  /** Get layer name.
244  @return Name
245  */
246  wxString GetName() const { return m_name; }
247 
248  /** Get font set for this layer.
249  @return Font
250  */
251  const wxFont& GetFont() const { return m_font; }
252 
253  /** Get pen set for this layer.
254  @return Pen
255  */
256  const wxPen& GetPen() const { return m_pen; }
257 
258  /** Set the 'continuity' property of the layer (true:draws a continuous line, false:draws separate points).
259  * @sa GetContinuity
260  */
261  void SetContinuity(bool continuity) {m_continuous = continuity;}
262 
263  /** Gets the 'continuity' property of the layer.
264  * @sa SetContinuity
265  */
266  bool GetContinuity() const {return m_continuous;}
267 
268  /** Shows or hides the text label with the name of the layer (default is visible).
269  */
270  void ShowName(bool show) { m_showName = show; };
271 
272  /** Set layer name
273  @param name Name, will be copied to internal class member
274  */
275  void SetName(wxString name) { m_name = name; }
276 
277  /** Set layer font
278  @param font Font, will be copied to internal class member
279  */
280  void SetFont(wxFont& font) { m_font = font; }
281 
282  /** Set layer pen
283  @param pen Pen, will be copied to internal class member
284  */
285  void SetPen(wxPen pen) { m_pen = pen; }
286 
287  /** Set Draw mode: inside or outside margins. Default is outside, which allows the layer to draw up to the mpWindow border.
288  @param drawModeOutside The draw mode to be set */
289  void SetDrawOutsideMargins(bool drawModeOutside) { m_drawOutsideMargins = drawModeOutside; };
290 
291  /** Get Draw mode: inside or outside margins.
292  @return The draw mode */
293  bool GetDrawOutsideMargins() { return m_drawOutsideMargins; };
294 
295  /** Get a small square bitmap filled with the colour of the pen used in the layer. Useful to create legends or similar reference to the layers.
296  @param side side length in pixels
297  @return a wxBitmap filled with layer's colour */
298  wxBitmap GetColourSquare(int side = 16);
299 
300  /** Get layer type: a Layer can be of different types: plot lines, axis, info boxes, etc, this method returns the right value.
301  @return An integer indicating layer type */
302  mpLayerType GetLayerType() { return m_type; };
303 
304  /** Checks whether the layer is visible or not.
305  @return \a true if visible */
306  bool IsVisible() {return m_visible; };
307 
308  /** Sets layer visibility.
309  @param show visibility bool. */
310  void SetVisible(bool show) { m_visible = show; };
311 
312  /** Get brush set for this layer.
313  @return brush. */
314  const wxBrush& GetBrush() const { return m_brush; };
315 
316  /** Set layer brush
317  @param brush brush, will be copied to internal class member */
318  void SetBrush(wxBrush brush) { m_brush = brush; };
319 
320 protected:
321  wxFont m_font; //!< Layer's font
322  wxPen m_pen; //!< Layer's pen
323  wxBrush m_brush; //!< Layer's brush
324  wxString m_name; //!< Layer's name
325  bool m_continuous; //!< Specify if the layer will be plotted as a continuous line or a set of points.
326  bool m_showName; //!< States whether the name of the layer must be shown (default is true).
327  bool m_drawOutsideMargins; //!< select if the layer should draw only inside margins or over all DC
328  mpLayerType m_type; //!< Define layer type, which is assigned by constructor
329  bool m_visible; //!< Toggles layer visibility
330  DECLARE_DYNAMIC_CLASS(mpLayer)
331 };
332 
333 
334 //-----------------------------------------------------------------------------
335 // mpInfoLayer
336 //-----------------------------------------------------------------------------
337 
338 /** @class mpInfoLayer
339  @brief Base class to create small rectangular info boxes
340  mpInfoLayer is the base class to create a small rectangular info box in transparent overlay over plot layers. It is used to implement objects like legends.
341 */
343 {
344 public:
345  /** Default constructor. */
346  mpInfoLayer();
347 
348  /** Complete constructor.
349  @param rect Sets the initial size rectangle of the layer.
350  @param brush pointer to a fill brush. Default is transparent */
351  mpInfoLayer(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);
352 
353  /** Destructor */
354  virtual ~mpInfoLayer();
355 
356  /** Updates the content of the info box. Should be overidden by derived classes.
357  Update may behave in different ways according to the type of event which called it.
358  @param w parent mpWindow from which to obtain informations
359  @param event The event which called the update. */
360  virtual void UpdateInfo(mpWindow& w, wxEvent& event);
361 
362  /** mpInfoLayer has not bounding box. @sa mpLayer::HasBBox
363  @return always \a FALSE */
364  virtual bool HasBBox() { return false; };
365 
366  /** Plot method. Can be overidden by derived classes.
367  @param dc the device content where to plot
368  @param w the window to plot
369  @sa mpLayer::Plot */
370  virtual void Plot(wxDC & dc, mpWindow & w);
371 
372  /** Specifies that this is an Info box layer.
373  @return always \a TRUE
374  @sa mpLayer::IsInfo */
375  virtual bool IsInfo() { return true; };
376 
377  /** Checks whether a point is inside the info box rectangle.
378  @param point The point to be checked
379  @return \a true if the point is inside the bounding box */
380  virtual bool Inside(wxPoint& point);
381 
382  /** Moves the layer rectangle of given pixel deltas.
383  @param delta The wxPoint container for delta coordinates along x and y. Units are in pixels. */
384  virtual void Move(wxPoint delta);
385 
386  /** Updates the rectangle reference point. Used by internal methods of mpWindow to correctly move mpInfoLayers. */
387  virtual void UpdateReference();
388 
389  /** Returns the position of the upper left corner of the box (in pixels)
390  @return The rectangle position */
391  wxPoint GetPosition();
392 
393  /** Returns the size of the box (in pixels)
394  @return The rectangle size */
395  wxSize GetSize();
396 
397  /** Returns the current rectangle coordinates.
398  @return The info layer rectangle */
399  const wxRect& GetRectangle() { return m_dim; };
400 
401 protected:
402  wxRect m_dim; //!< The bounding rectangle of the box. It may be resized dynamically by the Plot method.
403  wxPoint m_reference; //!< Holds the reference point for movements
404  wxBrush m_brush; //!< The brush to be used for the background
405  int m_winX, m_winY; //!< Holds the mpWindow size. Used to rescale position when window is resized.
406 
407  DECLARE_DYNAMIC_CLASS(mpInfoLayer)
408 };
409 
410 /** @class mpInfoCoords
411  @brief Implements an overlay box which shows the mouse coordinates in plot units.
412  When an mpInfoCoords layer is activated, when mouse is moved over the mpWindow, its coordinates (in mpWindow units, not pixels) are continuously reported inside the layer box. */
414 {
415 public:
416  /** Default constructor */
417  mpInfoCoords();
418  /** Complete constructor, setting initial rectangle and background brush.
419  @param rect The initial bounding rectangle.
420  @param brush The wxBrush to be used for box background: default is transparent */
421  mpInfoCoords(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);
422 
423  /** Default destructor */
424  ~mpInfoCoords();
425 
426  /** Updates the content of the info box. It is used to update coordinates.
427  @param w parent mpWindow from which to obtain information
428  @param event The event which called the update. */
429  virtual void UpdateInfo(mpWindow& w, wxEvent& event);
430 
431  /** Plot method.
432  @param dc the device content where to plot
433  @param w the window to plot
434  @sa mpLayer::Plot */
435  virtual void Plot(wxDC & dc, mpWindow & w);
436 
437 protected:
438  wxString m_content; //!< string holding the coordinates to be drawn.
439 };
440 
441 /** @class mpInfoLegend
442  @brief Implements the legend to be added to the plot
443  This layer allows you to add a legend to describe the plots in the window. The legend uses the layer name as a label, and displays only layers of type mpLAYER_PLOT. */
445 {
446 public:
447  /** Default constructor */
448  mpInfoLegend();
449 
450  /** Complete constructor, setting initial rectangle and background brush.
451  @param rect The initial bounding rectangle.
452  @param brush The wxBrush to be used for box background: default is transparent
453  @sa mpInfoLayer::mpInfoLayer */
454  mpInfoLegend(wxRect rect, const wxBrush* brush = wxTRANSPARENT_BRUSH);
455 
456  /** Default destructor */
457  ~mpInfoLegend();
458 
459  /** Updates the content of the info box. Unused in this class.
460  @param w parent mpWindow from which to obtain information
461  @param event The event which called the update. */
462  virtual void UpdateInfo(mpWindow& w, wxEvent& event);
463 
464  /** Plot method.
465  @param dc the device content where to plot
466  @param w the window to plot
467  @sa mpLayer::Plot */
468  virtual void Plot(wxDC & dc, mpWindow & w);
469 
470 protected:
471 
472 };
473 
474 
475 //-----------------------------------------------------------------------------
476 // mpLayer implementations - functions
477 //-----------------------------------------------------------------------------
478 
479 /** @name Label alignment constants
480 @{*/
481 
482 /** @internal */
483 #define mpALIGNMASK 0x03
484 /** Aligns label to the right. For use with mpFX. */
485 #define mpALIGN_RIGHT 0x00
486 /** Aligns label to the center. For use with mpFX and mpFY. */
487 #define mpALIGN_CENTER 0x01
488 /** Aligns label to the left. For use with mpFX. */
489 #define mpALIGN_LEFT 0x02
490 /** Aligns label to the top. For use with mpFY. */
491 #define mpALIGN_TOP mpALIGN_RIGHT
492 /** Aligns label to the bottom. For use with mpFY. */
493 #define mpALIGN_BOTTOM mpALIGN_LEFT
494 /** Aligns X axis to bottom border. For mpScaleX */
495 #define mpALIGN_BORDER_BOTTOM 0x04
496 /** Aligns X axis to top border. For mpScaleX */
497 #define mpALIGN_BORDER_TOP 0x05
498 /** Set label for X axis in normal mode */
499 #define mpX_NORMAL 0x00
500 /** Set label for X axis in time mode: the value is represented as minutes:seconds.milliseconds if time is less than 2 minutes, hours:minutes:seconds otherwise. */
501 #define mpX_TIME 0x01
502 /** Set label for X axis in hours mode: the value is always represented as hours:minutes:seconds. */
503 #define mpX_HOURS 0x02
504 /** Set label for X axis in date mode: the value is always represented as yyyy-mm-dd. */
505 #define mpX_DATE 0x03
506 /** Set label for X axis in datetime mode: the value is always represented as yyyy-mm-ddThh:mm:ss. */
507 #define mpX_DATETIME 0x04
508 /** Aligns Y axis to left border. For mpScaleY */
509 #define mpALIGN_BORDER_LEFT mpALIGN_BORDER_BOTTOM
510 /** Aligns Y axis to right border. For mpScaleY */
511 #define mpALIGN_BORDER_RIGHT mpALIGN_BORDER_TOP
512 /** Aligns label to north-east. For use with mpFXY. */
513 #define mpALIGN_NE 0x00
514 /** Aligns label to north-west. For use with mpFXY. */
515 #define mpALIGN_NW 0x01
516 /** Aligns label to south-west. For use with mpFXY. */
517 #define mpALIGN_SW 0x02
518 /** Aligns label to south-east. For use with mpFXY. */
519 #define mpALIGN_SE 0x03
520 
521 /*@}*/
522 
523 /** @name mpLayer implementations - functions
524 @{*/
525 
526 /** Abstract base class providing plot and labeling functionality for functions F:X->Y.
527  Override mpFX::GetY to implement a function.
528  Optionally implement a constructor and pass a name (label) and a label alignment
529  to the constructor mpFX::mpFX. If the layer name is empty, no label will be plotted.
530 */
532 {
533 public:
534  /** @param name Label
535  @param flags Label alignment, pass one of #mpALIGN_RIGHT, #mpALIGN_CENTER, #mpALIGN_LEFT.
536  */
537  mpFX(wxString name = wxEmptyString, int flags = mpALIGN_RIGHT);
538 
539  /** Get function value for argument.
540  Override this function in your implementation.
541  @param x Argument
542  @return Function value
543  */
544  virtual double GetY( double x ) = 0;
545 
546  /** Layer plot handler.
547  This implementation will plot the function in the visible area and
548  put a label according to the aligment specified.
549  */
550  virtual void Plot(wxDC & dc, mpWindow & w);
551 
552 protected:
553  int m_flags; //!< Holds label alignment
554 
555  DECLARE_DYNAMIC_CLASS(mpFX)
556 };
557 
558 /** Abstract base class providing plot and labeling functionality for functions F:Y->X.
559  Override mpFY::GetX to implement a function.
560  Optionally implement a constructor and pass a name (label) and a label alignment
561  to the constructor mpFY::mpFY. If the layer name is empty, no label will be plotted.
562 */
564 {
565 public:
566  /** @param name Label
567  @param flags Label alignment, pass one of #mpALIGN_BOTTOM, #mpALIGN_CENTER, #mpALIGN_TOP.
568  */
569  mpFY(wxString name = wxEmptyString, int flags = mpALIGN_TOP);
570 
571  /** Get function value for argument.
572  Override this function in your implementation.
573  @param y Argument
574  @return Function value
575  */
576  virtual double GetX( double y ) = 0;
577 
578  /** Layer plot handler.
579  This implementation will plot the function in the visible area and
580  put a label according to the aligment specified.
581  */
582  virtual void Plot(wxDC & dc, mpWindow & w);
583 
584 protected:
585  int m_flags; //!< Holds label alignment
586 
587  DECLARE_DYNAMIC_CLASS(mpFY)
588 };
589 
590 /** Abstract base class providing plot and labeling functionality for a locus plot F:N->X,Y.
591  Locus argument N is assumed to be in range 0 .. MAX_N, and implicitly derived by enumerating
592  all locus values. Override mpFXY::Rewind and mpFXY::GetNextXY to implement a locus.
593  Optionally implement a constructor and pass a name (label) and a label alignment
594  to the constructor mpFXY::mpFXY. If the layer name is empty, no label will be plotted.
595 */
597 {
598 public:
599  /** @param name Label
600  @param flags Label alignment, pass one of #mpALIGN_NE, #mpALIGN_NW, #mpALIGN_SW, #mpALIGN_SE.
601  */
602  mpFXY(wxString name = wxEmptyString, int flags = mpALIGN_NE);
603 
604  /** Rewind value enumeration with mpFXY::GetNextXY.
605  Override this function in your implementation.
606  */
607  virtual void Rewind() = 0;
608 
609  /** Get locus value for next N.
610  Override this function in your implementation.
611  @param x Returns X value
612  @param y Returns Y value
613  */
614  virtual bool GetNextXY(double & x, double & y) = 0;
615 
616  /** Layer plot handler.
617  This implementation will plot the locus in the visible area and
618  put a label according to the alignment specified.
619  */
620  virtual void Plot(wxDC & dc, mpWindow & w);
621 
622 
623 protected:
624  int m_flags; //!< Holds label alignment
625 
626  // Data to calculate label positioning
627  wxCoord maxDrawX, minDrawX, maxDrawY, minDrawY;
628  //int drawnPoints;
629 
630  /** Update label positioning data
631  @param xnew New x coordinate
632  @param ynew New y coordinate
633  */
634  void UpdateViewBoundary(wxCoord xnew, wxCoord ynew);
635 
636  DECLARE_DYNAMIC_CLASS(mpFXY)
637 };
638 
639 /** Abstract base class providing plot and labeling functionality for functions F:Y->X.
640  Override mpProfile::GetX to implement a function.
641  This class is similar to mpFY, but the Plot method is different. The plot is in fact represented by lines instead of points, which gives best rendering of rapidly-varying functions, and in general, data which are not so close one to another.
642  Optionally implement a constructor and pass a name (label) and a label alignment
643  to the constructor mpProfile::mpProfile. If the layer name is empty, no label will be plotted.
644 */
646 {
647 public:
648  /** @param name Label
649  @param flags Label alignment, pass one of #mpALIGN_BOTTOM, #mpALIGN_CENTER, #mpALIGN_TOP.
650  */
651  mpProfile(wxString name = wxEmptyString, int flags = mpALIGN_TOP);
652 
653  /** Get function value for argument.
654  Override this function in your implementation.
655  @param x Argument
656  @return Function value
657  */
658  virtual double GetY( double x ) = 0;
659 
660  /** Layer plot handler.
661  This implementation will plot the function in the visible area and
662  put a label according to the aligment specified.
663  */
664  virtual void Plot(wxDC & dc, mpWindow & w);
665 
666 protected:
667  int m_flags; //!< Holds label alignment
668 
669  DECLARE_DYNAMIC_CLASS(mpProfile)
670 };
671 
672 /*@}*/
673 
674 //-----------------------------------------------------------------------------
675 // mpLayer implementations - furniture (scales, ...)
676 //-----------------------------------------------------------------------------
677 
678 /** @name mpLayer implementations - furniture (scales, ...)
679 @{*/
680 
681 /** Plot layer implementing a x-scale ruler.
682  The ruler is fixed at Y=0 in the coordinate system. A label is plotted at
683  the bottom-right hand of the ruler. The scale numbering automatically
684  adjusts to view and zoom factor.
685 */
687 {
688 public:
689  /** Full constructor.
690  @param name Label to plot by the ruler
691  @param flags Set the position of the scale with respect to the window.
692  @param ticks Select ticks or grid. Give TRUE (default) for drawing axis ticks, FALSE for drawing the grid.
693  @param type mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
694  mpScaleX(wxString name = wxT("X"), int flags = mpALIGN_CENTER, bool ticks = true, unsigned int type = mpX_NORMAL);
695 
696  /** Layer plot handler.
697  This implementation will plot the ruler adjusted to the visible area. */
698  virtual void Plot(wxDC & dc, mpWindow & w);
699 
700  /** Check whether this layer has a bounding box.
701  This implementation returns \a FALSE thus making the ruler invisible
702  to the plot layer bounding box calculation by mpWindow. */
703  virtual bool HasBBox() { return FALSE; }
704 
705  /** Set X axis alignment.
706  @param align alignment (choose between mpALIGN_BORDER_BOTTOM, mpALIGN_BOTTOM, mpALIGN_CENTER, mpALIGN_TOP, mpALIGN_BORDER_TOP */
707  void SetAlign(int align) { m_flags = align; };
708 
709  /** Set X axis ticks or grid
710  @param ticks TRUE to plot axis ticks, FALSE to plot grid. */
711  void SetTicks(bool ticks) { m_ticks = ticks; };
712 
713  /** Get X axis ticks or grid
714  @return TRUE if plot is drawing axis ticks, FALSE if the grid is active. */
715  bool GetTicks() { return m_ticks; };
716 
717  /** Get X axis label view mode.
718  @return mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
719  unsigned int GetLabelMode() { return m_labelType; };
720 
721  /** Set X axis label view mode.
722  @param mode mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds. */
723  void SetLabelMode(unsigned int mode) { m_labelType = mode; };
724 
725  /** Set X axis Label format (used for mpX_NORMAL draw mode).
726  @param format The format string */
727  void SetLabelFormat(const wxString& format) { m_labelFormat = format; };
728 
729  /** Get X axis Label format (used for mpX_NORMAL draw mode).
730  @return The format string */
731  const wxString& SetLabelFormat() { return m_labelFormat; };
732 
733 protected:
734  int m_flags; //!< Flag for axis alignment
735  bool m_ticks; //!< Flag to toggle between ticks or grid
736  unsigned int m_labelType; //!< Select labels mode: mpX_NORMAL for normal labels, mpX_TIME for time axis in hours, minutes, seconds
737  wxString m_labelFormat; //!< Format string used to print labels
738 
739  DECLARE_DYNAMIC_CLASS(mpScaleX)
740 };
741 
742 /** Plot layer implementing a y-scale ruler.
743  If align is set to mpALIGN_CENTER, the ruler is fixed at X=0 in the coordinate system. If the align is set to mpALIGN_TOP or mpALIGN_BOTTOM, the axis is always drawn respectively at top or bottom of the window. A label is plotted at
744  the top-right hand of the ruler. The scale numbering automatically
745  adjusts to view and zoom factor.
746 */
748 {
749 public:
750  /** @param name Label to plot by the ruler
751  @param flags Set position of the scale respect to the window.
752  @param ticks Select ticks or grid. Give TRUE (default) for drawing axis ticks, FALSE for drawing the grid */
753  mpScaleY(wxString name = wxT("Y"), int flags = mpALIGN_CENTER, bool ticks = true);
754 
755  /** Layer plot handler.
756  This implementation will plot the ruler adjusted to the visible area.
757  */
758  virtual void Plot(wxDC & dc, mpWindow & w);
759 
760  /** Check whether this layer has a bounding box.
761  This implementation returns \a FALSE thus making the ruler invisible
762  to the plot layer bounding box calculation by mpWindow.
763  */
764  virtual bool HasBBox() { return FALSE; }
765 
766  /** Set Y axis alignment.
767  @param align alignment (choose between mpALIGN_BORDER_LEFT, mpALIGN_LEFT, mpALIGN_CENTER, mpALIGN_RIGHT, mpALIGN_BORDER_RIGHT) */
768  void SetAlign(int align) { m_flags = align; };
769 
770  /** Set Y axis ticks or grid
771  @param ticks TRUE to plot axis ticks, FALSE to plot grid. */
772  void SetTicks(bool ticks) { m_ticks = ticks; };
773 
774  /** Get Y axis ticks or grid
775  @return TRUE if plot is drawing axis ticks, FALSE if the grid is active. */
776  bool GetTicks() { return m_ticks; };
777 
778  /** Set Y axis Label format.
779  @param format The format string */
780  void SetLabelFormat(const wxString& format) { m_labelFormat = format; };
781 
782  /** Get Y axis Label format.
783  @return The format string */
784  const wxString& SetLabelFormat() { return m_labelFormat; };
785 
786 protected:
787  int m_flags; //!< Flag for axis alignment
788  bool m_ticks; //!< Flag to toggle between ticks or grid
789  wxString m_labelFormat; //!< Format string used to print labels
790 
791  DECLARE_DYNAMIC_CLASS(mpScaleY)
792 };
793 
794 //-----------------------------------------------------------------------------
795 // mpWindow
796 //-----------------------------------------------------------------------------
797 
798 /** @name Constants defining mouse modes for mpWindow
799 @{*/
800 
801 /** Mouse panning drags the view. Mouse mode for mpWindow. */
802 #define mpMOUSEMODE_DRAG 0
803 /** Mouse panning creates a zoom box. Mouse mode for mpWindow. */
804 #define mpMOUSEMODE_ZOOMBOX 1
805 
806 /*@}*/
807 /** Define the type for the list of layers inside mpWindow */
808 //WX_DECLARE_HASH_MAP( int, mpLayer*, wxIntegerHash, wxIntegerEqual, wxLayerList );
809 typedef std::deque<mpLayer*> wxLayerList;
810 
811 /** Canvas for plotting mpLayer implementations.
812 
813  This class defines a zoomable and moveable 2D plot canvas. Any number
814  of mpLayer implementations (scale rulers, function plots, ...) can be
815  attached using mpWindow::AddLayer.
816 
817  The canvas window provides a context menu with actions for navigating the view.
818  The context menu can be retrieved with mpWindow::GetPopupMenu, e.g. for extending it
819  externally.
820 
821  Since wxMathPlot version 0.03, the mpWindow incorporates the following features:
822  - DoubleBuffering (Default=disabled): Can be set with EnableDoubleBuffer
823  - Mouse based pan/zoom (Default=enabled): Can be set with EnableMousePanZoom.
824 
825  The mouse commands can be visualized by the user through the popup menu, and are:
826  - Mouse Move+CTRL: Pan (Move)
827  - Mouse Wheel: Vertical scroll
828  - Mouse Wheel+SHIFT: Horizontal scroll
829  - Mouse Wheel UP+CTRL: Zoom in
830  - Mouse Wheel DOWN+CTRL: Zoom out
831 
832 */
833 class WXDLLIMPEXP_MATHPLOT mpWindow : public wxWindow
834 {
835 public:
836  mpWindow() {}
837  mpWindow( wxWindow *parent, wxWindowID id,
838  const wxPoint &pos = wxDefaultPosition,
839  const wxSize &size = wxDefaultSize,
840  long flags = 0);
841  ~mpWindow();
842 
843  /** Get reference to context menu of the plot canvas.
844  @return Pointer to menu. The menu can be modified.
845  */
846  wxMenu* GetPopupMenu() { return &m_popmenu; }
847 
848  /** Add a plot layer to the canvas.
849  @param layer Pointer to layer. The mpLayer object will get under control of mpWindow,
850  i.e. it will be delete'd on mpWindow destruction
851  @param refreshDisplay States whether to refresh the display (UpdateAll) after adding the layer.
852  @retval TRUE Success
853  @retval FALSE Failure due to out of memory.
854  */
855  bool AddLayer( mpLayer* layer, bool refreshDisplay = true);
856 
857  /** Remove a plot layer from the canvas.
858  @param layer Pointer to layer. The mpLayer object will be destructed using delete.
859  @param alsoDeleteObject If set to true, the mpLayer object will be also "deleted", not just removed from the internal list.
860  @param refreshDisplay States whether to refresh the display (UpdateAll) after removing the layer.
861  @return true if layer is deleted correctly
862 
863  N.B. Only the layer reference in the mpWindow is deleted, the layer object still exists!
864  */
865  bool DelLayer( mpLayer* layer, bool alsoDeleteObject = false, bool refreshDisplay = true);
866 
867  /** Remove all layers from the plot.
868  @param alsoDeleteObject If set to true, the mpLayer objects will be also "deleted", not just removed from the internal list.
869  @param refreshDisplay States whether to refresh the display (UpdateAll) after removing the layers.
870  */
871  void DelAllLayers( bool alsoDeleteObject, bool refreshDisplay = true);
872 
873 
874  /*! Get the layer in list position indicated.
875  N.B. You <i>must</i> know the index of the layer inside the list!
876  @param position position of the layer in the layers list
877  @return pointer to mpLayer
878  */
879  mpLayer* GetLayer(int position);
880 
881  /*! Get the layer by its name (case sensitive).
882  @param name The name of the layer to retrieve
883  @return A pointer to the mpLayer object, or NULL if not found.
884  */
885  mpLayer* GetLayerByName( const wxString &name);
886 
887  /** Get current view's X scale.
888  See @ref mpLayer::Plot "rules for coordinate transformation"
889  @return Scale
890  */
891  double GetXscl() { return m_scaleX; }
892  double GetScaleX(void) const{ return m_scaleX; }; // Schaling's method: maybe another method esists with the same name
893 
894  /** Get current view's Y scale.
895  See @ref mpLayer::Plot "rules for coordinate transformation"
896  @return Scale
897  */
898  double GetYscl() const { return m_scaleY; }
899  double GetScaleY(void) const { return m_scaleY; } // Schaling's method: maybe another method exists with the same name
900 
901  /** Get current view's X position.
902  See @ref mpLayer::Plot "rules for coordinate transformation"
903  @return X Position in layer coordinate system, that corresponds to the center point of the view.
904  */
905  double GetXpos() const { return m_posX; }
906  double GetPosX(void) const { return m_posX; }
907 
908  /** Get current view's Y position.
909  See @ref mpLayer::Plot "rules for coordinate transformation"
910  @return Y Position in layer coordinate system, that corresponds to the center point of the view.
911  */
912  double GetYpos() const { return m_posY; }
913  double GetPosY(void) const { return m_posY; }
914 
915  /** Get current view's X dimension in device context units.
916  Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
917  implementations should rely on the value returned by the function.
918  See @ref mpLayer::Plot "rules for coordinate transformation"
919  @return X dimension.
920  */
921  int GetScrX(void) const { return m_scrX; }
922  int GetXScreen(void) const { return m_scrX; }
923 
924  /** Get current view's Y dimension in device context units.
925  Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
926  implementations should rely on the value returned by the function.
927  See @ref mpLayer::Plot "rules for coordinate transformation"
928  @return Y dimension.
929  */
930  int GetScrY(void) const { return m_scrY; }
931  int GetYScreen(void) const { return m_scrY; }
932 
933  /** Set current view's X scale and refresh display.
934  @param scaleX New scale, must not be 0.
935  */
936  void SetScaleX(double scaleX);
937 
938  /** Set current view's Y scale and refresh display.
939  @param scaleY New scale, must not be 0.
940  */
941  void SetScaleY(double scaleY) { if (scaleY!=0) m_scaleY=scaleY; UpdateAll(); }
942 
943  /** Set current view's X position and refresh display.
944  @param posX New position that corresponds to the center point of the view.
945  */
946  void SetPosX(double posX) { m_posX=posX; UpdateAll(); }
947 
948  /** Set current view's Y position and refresh display.
949  @param posY New position that corresponds to the center point of the view.
950  */
951  void SetPosY(double posY) { m_posY=posY; UpdateAll(); }
952 
953  /** Set current view's X and Y position and refresh display.
954  @param posX New position that corresponds to the center point of the view.
955  @param posY New position that corresponds to the center point of the view.
956  */
957  void SetPos( double posX, double posY) { m_posX=posX; m_posY=posY; UpdateAll(); }
958 
959  /** Set current view's dimensions in device context units.
960  Needed by plotting functions. It doesn't refresh display.
961  @param scrX New position that corresponds to the center point of the view.
962  @param scrY New position that corresponds to the center point of the view.
963  */
964  void SetScr( int scrX, int scrY) { m_scrX=scrX; m_scrY=scrY; }
965 
966  /** Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates, using current mpWindow position and scale.
967  * @sa p2y,x2p,y2p */
968 // double p2x(wxCoord pixelCoordX, bool drawOutside = true ); // { return m_posX + pixelCoordX/m_scaleX; }
969  inline double p2x(wxCoord pixelCoordX ) { return m_posX + pixelCoordX/m_scaleX; }
970 
971  /** Converts mpWindow (screen) pixel coordinates into graph (floating point) coordinates, using current mpWindow position and scale.
972  * @sa p2x,x2p,y2p */
973 // double p2y(wxCoord pixelCoordY, bool drawOutside = true ); //{ return m_posY - pixelCoordY/m_scaleY; }
974  inline double p2y(wxCoord pixelCoordY ) { return m_posY - pixelCoordY/m_scaleY; }
975 
976  /** Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates, using current mpWindow position and scale.
977  * @sa p2x,p2y,y2p */
978 // wxCoord x2p(double x, bool drawOutside = true); // { return (wxCoord) ( (x-m_posX) * m_scaleX); }
979  inline wxCoord x2p(double x) { return (wxCoord) ( (x-m_posX) * m_scaleX); }
980 
981  /** Converts graph (floating point) coordinates into mpWindow (screen) pixel coordinates, using current mpWindow position and scale.
982  * @sa p2x,p2y,x2p */
983 // wxCoord y2p(double y, bool drawOutside = true); // { return (wxCoord) ( (m_posY-y) * m_scaleY); }
984  inline wxCoord y2p(double y) { return (wxCoord) ( (m_posY-y) * m_scaleY); }
985 
986 
987  /** Enable/disable the double-buffering of the window, eliminating the flicker (default=disabled).
988  */
989  void EnableDoubleBuffer( bool enabled ) { m_enableDoubleBuffer = enabled; }
990 
991  /** Enable/disable the feature of pan/zoom with the mouse (default=enabled)
992  */
993  void EnableMousePanZoom( bool enabled ) { m_enableMouseNavigation = enabled; }
994 
995  /** Enable or disable X/Y scale aspect locking for the view.
996  @note Explicit calls to mpWindow::SetScaleX and mpWindow::SetScaleY will set
997  an unlocked aspect, but any other action changing the view scale will
998  lock the aspect again.
999  */
1000  void LockAspect(bool enable = TRUE);
1001 
1002  /** Checks whether the X/Y scale aspect is locked.
1003  @retval TRUE Locked
1004  @retval FALSE Unlocked
1005  */
1006  inline bool IsAspectLocked() { return m_lockaspect; }
1007 
1008  /** Set view to fit global bounding box of all plot layers and refresh display.
1009  Scale and position will be set to show all attached mpLayers.
1010  The X/Y scale aspect lock is taken into account.
1011  */
1012  void Fit();
1013 
1014  /** Set view to fit a given bounding box and refresh display.
1015  The X/Y scale aspect lock is taken into account.
1016  If provided, the parameters printSizeX and printSizeY are taken as the DC size, and the
1017  pixel scales are computed accordingly. Also, in this case the passed borders are not saved
1018  as the "desired borders", since this use will be invoked only when printing.
1019  */
1020  void Fit(double xMin, double xMax, double yMin, double yMax,wxCoord *printSizeX=NULL,wxCoord *printSizeY=NULL);
1021 
1022  /** Zoom into current view and refresh display
1023  * @param centerPoint The point (pixel coordinates) that will stay in the same position on the screen after the zoom (by default, the center of the mpWindow).
1024  */
1025  void ZoomIn( const wxPoint& centerPoint = wxDefaultPosition );
1026 
1027  /** Zoom out current view and refresh display
1028  * @param centerPoint The point (pixel coordinates) that will stay in the same position on the screen after the zoom (by default, the center of the mpWindow).
1029  */
1030  void ZoomOut( const wxPoint& centerPoint = wxDefaultPosition );
1031 
1032  /** Zoom in current view along X and refresh display */
1033  void ZoomInX();
1034  /** Zoom out current view along X and refresh display */
1035  void ZoomOutX();
1036  /** Zoom in current view along Y and refresh display */
1037  void ZoomInY();
1038  /** Zoom out current view along Y and refresh display */
1039  void ZoomOutY();
1040 
1041  /** Zoom view fitting given coordinates to the window (p0 and p1 do not need to be in any specific order) */
1042  void ZoomRect(wxPoint p0, wxPoint p1);
1043 
1044  /** Refresh display */
1045  void UpdateAll();
1046 
1047  // Added methods by Davide Rondini
1048 
1049  /** Counts the number of plot layers, excluding axes or text: this is to count only the layers which have a bounding box.
1050  \return The number of profiles plotted.
1051  */
1052  unsigned int CountLayers();
1053 
1054  /** Counts the number of plot layers, whether or not they have a bounding box.
1055  \return The number of layers in the mpWindow. */
1056  size_t CountAllLayers() { return m_layers.size(); };
1057 
1058  /** Draws the mpWindow on a page for printing
1059  \param print the mpPrintout where to print the graph */
1060  //void PrintGraph(mpPrintout *print);
1061 
1062  void ShowPrintDialog()
1063  {
1064  wxCommandEvent dum;
1065  OnPrintMenu(dum);
1066  }
1067 
1068 
1069  /** Returns the left-border layer coordinate that the user wants the mpWindow to show (it may be not exactly the actual shown coordinate in the case of locked aspect ratio).
1070  * @sa Fit
1071  */
1072  double GetDesiredXmin() {return m_desiredXmin; }
1073 
1074  /** Returns the right-border layer coordinate that the user wants the mpWindow to show (it may be not exactly the actual shown coordinate in the case of locked aspect ratio).
1075  * @sa Fit
1076  */
1077  double GetDesiredXmax() {return m_desiredXmax; }
1078 
1079  /** Returns the bottom-border layer coordinate that the user wants the mpWindow to show (it may be not exactly the actual shown coordinate in the case of locked aspect ratio).
1080  * @sa Fit
1081  */
1082  double GetDesiredYmin() {return m_desiredYmin; }
1083 
1084  /** Returns the top layer-border coordinate that the user wants the mpWindow to show (it may be not exactly the actual shown coordinate in the case of locked aspect ratio).
1085  * @sa Fit
1086  */
1087  double GetDesiredYmax() {return m_desiredYmax; }
1088 
1089  /** Returns the bounding box coordinates
1090  @param bbox Pointer to a 6-element double array where to store bounding box coordinates. */
1091  void GetBoundingBox(double* bbox);
1092 
1093  /** Enable/disable scrollbars
1094  @param status Set to true to show scrollbars */
1095  void SetMPScrollbars(bool status);
1096 
1097  /** Get scrollbars status.
1098  @return true if scrollbars are visible */
1099  bool GetMPScrollbars() {return m_enableScrollBars; };
1100 
1101  /** Draw the window on a wxBitmap, then save it to a file.
1102  @param filename File name where to save the screenshot
1103  @param type image type to be saved: see wxImage output file types for flags
1104  @param imageSize Set a size for the output image. Default is the same as the screen size
1105  @param fit Decide whether to fit the plot into the size*/
1106  bool SaveScreenshot(const wxString& filename, int type = wxBITMAP_TYPE_BMP, wxSize imageSize = wxDefaultSize, bool fit = false);
1107 
1108  /** This value sets the zoom steps whenever the user clicks "Zoom in/out" or performs zoom with the mouse wheel.
1109  * It must be a number above unity. This number is used for zoom in, and its inverse for zoom out. Set to 1.5 by default. */
1110  static double zoomIncrementalFactor;
1111 
1112  /** Set window margins, creating a blank area where some kinds of layers cannot draw. This is useful for example to draw axes outside the area where the plots are drawn.
1113  @param top Top border
1114  @param right Right border
1115  @param bottom Bottom border
1116  @param left Left border */
1117  void SetMargins(int top, int right, int bottom, int left);
1118 
1119  /** Set the top margin. @param top Top Margin */
1120  void SetMarginTop(int top) { m_marginTop = top; };
1121  /** Set the right margin. @param right Right Margin */
1122  void SetMarginRight(int right) { m_marginRight = right; };
1123  /** Set the bottom margin. @param bottom Bottom Margin */
1124  void SetMarginBottom(int bottom) { m_marginBottom = bottom; };
1125  /** Set the left margin. @param left Left Margin */
1126  void SetMarginLeft(int left) { m_marginLeft = left; };
1127 
1128  /** Get the top margin. @param top Top Margin */
1129  int GetMarginTop() { return m_marginTop; };
1130  /** Get the right margin. @param right Right Margin */
1131  int GetMarginRight() { return m_marginRight; };
1132  /** Get the bottom margin. @param bottom Bottom Margin */
1133  int GetMarginBottom() { return m_marginBottom; };
1134  /** Get the left margin. @param left Left Margin */
1135  int GetMarginLeft() { return m_marginLeft; };
1136 
1137  /** Sets whether to show coordinate tooltip when mouse passes over the plot. \param value true for enable, false for disable */
1138  // void EnableCoordTooltip(bool value = true);
1139  /** Gets coordinate tooltip status. \return true for enable, false for disable */
1140  // bool GetCoordTooltip() { return m_coordTooltip; };
1141 
1142  /** Check if a given point is inside the area of a mpInfoLayer and eventually returns its pointer.
1143  @param point The position to be checked
1144  @return If an info layer is found, returns its pointer, NULL otherwise */
1145  mpInfoLayer* IsInsideInfoLayer(wxPoint& point);
1146 
1147  /** Sets the visibility of a layer by its name.
1148  @param name The layer name to set visibility
1149  @param viewable the view status to be set */
1150  void SetLayerVisible(const wxString &name, bool viewable);
1151 
1152  /** Check whether a layer with given name is visible
1153  @param name The layer name
1154  @return layer visibility status */
1155  bool IsLayerVisible(const wxString &name );
1156 
1157  /** Sets the visibility of a layer by its position in layer list.
1158  @param position The layer position in layer list
1159  @param viewable the view status to be set */
1160  void SetLayerVisible(const unsigned int position, bool viewable);
1161 
1162  /** Check whether the layer at given position is visible
1163  @param position The layer position in layer list
1164  @return layer visibility status */
1165  bool IsLayerVisible(const unsigned int position );
1166 
1167  /** Set Color theme. Provide colours to set a new colour theme.
1168  @param bgColour Background colour
1169  @param drawColour The colour used to draw all elements in foreground, axes excluded
1170  @param axesColour The colour used to draw axes (but not their labels) */
1171  void SetColourTheme(const wxColour& bgColour, const wxColour& drawColour, const wxColour& axesColour);
1172 
1173  /** Get axes draw colour
1174  @return reference to axis colour used in theme */
1175  const wxColour& GetAxesColour() { return m_axColour; };
1176 
1177 protected:
1178  void OnPaint (wxPaintEvent &event); //!< Paint handler, will plot all attached layers
1179  void OnSize (wxSizeEvent &event); //!< Size handler, will update scroll bar sizes
1180  // void OnScroll2 (wxScrollWinEvent &event); //!< Scroll handler, will move canvas
1181  void OnShowPopupMenu (wxMouseEvent &event); //!< Mouse handler, will show context menu
1182  void OnMouseRightDown(wxMouseEvent &event); //!< Mouse handler, for detecting when the user drags with the right button or just "clicks" for the menu
1183  void OnCenter (wxCommandEvent &event); //!< Context menu handler
1184  void OnFit (wxCommandEvent &event); //!< Context menu handler
1185  void OnZoomIn (wxCommandEvent &event); //!< Context menu handler
1186  void OnZoomOut (wxCommandEvent &event); //!< Context menu handler
1187  void OnLockAspect (wxCommandEvent &event); //!< Context menu handler
1188  void OnMouseHelp (wxCommandEvent &event); //!< Context menu handler
1189  void OnPrintMenu (wxCommandEvent &event); //!< Context menu handler
1190  void OnMouseWheel (wxMouseEvent &event); //!< Mouse handler for the wheel
1191  void OnMouseMove (wxMouseEvent &event); //!< Mouse handler for mouse motion (for pan)
1192  void OnMouseLeftDown (wxMouseEvent &event); //!< Mouse left click (for rect zoom)
1193  void OnMouseLeftRelease (wxMouseEvent &event); //!< Mouse left click (for rect zoom)
1194  void OnScrollThumbTrack (wxScrollWinEvent &event); //!< Scroll thumb on scroll bar moving
1195  void OnScrollPageUp (wxScrollWinEvent &event); //!< Scroll page up
1196  void OnScrollPageDown (wxScrollWinEvent &event); //!< Scroll page down
1197  void OnScrollLineUp (wxScrollWinEvent &event); //!< Scroll line up
1198  void OnScrollLineDown (wxScrollWinEvent &event); //!< Scroll line down
1199  void OnScrollTop (wxScrollWinEvent &event); //!< Scroll to top
1200  void OnScrollBottom (wxScrollWinEvent &event); //!< Scroll to bottom
1201 
1202  void DoScrollCalc (const int position, const int orientation);
1203 
1204  void DoZoomInXCalc (const int staticXpixel);
1205  void DoZoomInYCalc (const int staticYpixel);
1206  void DoZoomOutXCalc (const int staticXpixel);
1207  void DoZoomOutYCalc (const int staticYpixel);
1208 
1209  /** Recalculate global layer bounding box, and save it in m_minX,...
1210  * \return true if there is any valid BBox information.
1211  */
1212  virtual bool UpdateBBox();
1213 
1214  //wxList m_layers; //!< List of attached plot layers
1215  wxLayerList m_layers; //!< List of attached plot layers
1216  wxMenu m_popmenu; //!< Canvas' context menu
1217  bool m_lockaspect;//!< Scale aspect is locked or not
1218  // bool m_coordTooltip; //!< Selects whether to show coordinate tooltip
1219  wxColour m_bgColour; //!< Background Colour
1220  wxColour m_fgColour; //!< Foreground Colour
1221  wxColour m_axColour; //!< Axes Colour
1222 
1223  double m_minX; //!< Global layer bounding box, left border incl.
1224  double m_maxX; //!< Global layer bounding box, right border incl.
1225  double m_minY; //!< Global layer bounding box, bottom border incl.
1226  double m_maxY; //!< Global layer bounding box, top border incl.
1227  double m_scaleX; //!< Current view's X scale
1228  double m_scaleY; //!< Current view's Y scale
1229  double m_posX; //!< Current view's X position
1230  double m_posY; //!< Current view's Y position
1231  int m_scrX; //!< Current view's X dimension
1232  int m_scrY; //!< Current view's Y dimension
1233  int m_clickedX; //!< Last mouse click X position, for centering and zooming the view
1234  int m_clickedY; //!< Last mouse click Y position, for centering and zooming the view
1235 
1236  /** These are updated in Fit() only, and may be different from the real borders (layer coordinates) only if lock aspect ratio is true.
1237  */
1238  double m_desiredXmin,m_desiredXmax,m_desiredYmin,m_desiredYmax;
1239 
1240  int m_marginTop, m_marginRight, m_marginBottom, m_marginLeft;
1241 
1242  int m_last_lx,m_last_ly; //!< For double buffering
1243  wxMemoryDC m_buff_dc; //!< For double buffering
1244  wxBitmap *m_buff_bmp; //!< For double buffering
1245  bool m_enableDoubleBuffer; //!< For double buffering
1246  bool m_enableMouseNavigation; //!< For pan/zoom with the mouse.
1248  long m_mouseRClick_X,m_mouseRClick_Y; //!< For the right button "drag" feature
1249  int m_mouseLClick_X, m_mouseLClick_Y; //!< Starting coords for rectangular zoom selection
1251  int m_scrollX, m_scrollY;
1252  mpInfoLayer* m_movingInfoLayer; //!< For moving info layers over the window area
1253 
1254  DECLARE_DYNAMIC_CLASS(mpWindow)
1255  DECLARE_EVENT_TABLE()
1256 };
1257 
1258 //-----------------------------------------------------------------------------
1259 // mpFXYVector - provided by Jose Luis Blanco
1260 //-----------------------------------------------------------------------------
1261 
1262 /** A class providing graphs functionality for a 2D plot (either continuous or a set of points), from vectors of data.
1263  This class can be used directly, the user does not need to derive any new class. Simply pass the data as two vectors
1264  with the same length containing the X and Y coordinates to the method SetData.
1265 
1266  To generate a graph with a set of points, call
1267  \code
1268  layerVar->SetContinuity(false)
1269  \endcode
1270 
1271  or
1272 
1273  \code
1274  layerVar->SetContinuity(true)
1275  \endcode
1276 
1277  to render the sequence of coordinates as a continuous line.
1278 
1279  (Added: Jose Luis Blanco, AGO-2007)
1280 */
1282 {
1283 public:
1284  /** @param name Label
1285  @param flags Label alignment, pass one of #mpALIGN_NE, #mpALIGN_NW, #mpALIGN_SW, #mpALIGN_SE.
1286  */
1287  mpFXYVector(wxString name = wxEmptyString, int flags = mpALIGN_NE);
1288 
1289  /** Changes the internal data: the set of points to draw.
1290  Both vectors MUST be of the same length. This method DOES NOT refresh the mpWindow; do it manually.
1291  * @sa Clear
1292  */
1293  void SetData( const std::vector<double> &xs,const std::vector<double> &ys);
1294 
1295  /** Changes the internal data: the set of points to draw.
1296  Both vectors MUST be of the same length. This method DOES NOT refresh the mpWindow; do it manually.
1297  * @sa Clear
1298  */
1299  void SetData( const std::vector<float> &xs,const std::vector<float> &ys);
1300 
1301  /** Clears all the data, leaving the layer empty.
1302  * @sa SetData
1303  */
1304  void Clear();
1305 
1306  /** Returns the number of data points currently hold in X & Y.
1307  * @sa SetData
1308  */
1309  size_t GetDataLength() const
1310  {
1311  return m_xs.size();
1312  }
1313 
1314  /** Append a new data point (x,y)
1315  * @sa SetData
1316  */
1317  void AppendDataPoint(float x, float y);
1318 
1319 protected:
1320  /** The internal copy of the set of data to draw.
1321  */
1322  std::vector<double> m_xs,m_ys;
1323 
1324  /** The internal counter for the "GetNextXY" interface
1325  */
1326  size_t m_index;
1327 
1328  /** Loaded at SetData
1329  */
1330  double m_minX,m_maxX,m_minY,m_maxY;
1331 
1332  /** Rewind value enumeration with mpFXY::GetNextXY.
1333  Overridden in this implementation.
1334  */
1335  void Rewind();
1336 
1337  /** Get locus value for next N.
1338  Overridden in this implementation.
1339  @param x Returns X value
1340  @param y Returns Y value
1341  */
1342  bool GetNextXY(double & x, double & y);
1343 
1344 public:
1345  /** Returns the actual minimum X data (loaded in SetData).
1346  */
1347  double GetMinX() { return m_minX; }
1348 
1349  /** Returns the actual minimum Y data (loaded in SetData).
1350  */
1351  double GetMinY() { return m_minY; }
1352 
1353  /** Returns the actual maximum X data (loaded in SetData).
1354  */
1355  double GetMaxX() { return m_maxX; }
1356 
1357  /** Returns the actual maximum Y data (loaded in SetData).
1358  */
1359  double GetMaxY() { return m_maxY; }
1360 
1361 protected:
1362  int m_flags; //!< Holds label alignment
1363 
1364  DECLARE_DYNAMIC_CLASS(mpFXYVector)
1365 };
1366 
1367 //-----------------------------------------------------------------------------
1368 // mpText - provided by Val Greene
1369 //-----------------------------------------------------------------------------
1370 
1371 /** Plot layer implementing a text string.
1372 The text is plotted using a percentage system 0-100%, so the actual
1373 coordinates for the location are not required, and the text stays
1374 on the plot reguardless of the other layers location and scaling
1375 factors.
1376 */
1378 {
1379 public:
1380  /** @param name text to be drawn in the plot
1381  @param offsetx holds offset for the X location in percentage (0-100)
1382  @param offsety holds offset for the Y location in percentage (0-100) */
1383  mpText(wxString name = wxT("Title"), int offsetx = 5, int offsety = 50);
1384 
1385  /** Text Layer plot handler.
1386  This implementation will plot text adjusted to the visible area. */
1387  virtual void Plot(wxDC & dc, mpWindow & w);
1388 
1389  /** mpText should not be used for scaling decisions. */
1390  virtual bool HasBBox() { return FALSE; }
1391 
1392 protected:
1393  int m_offsetx; //!< Holds offset for X in percentage
1394  int m_offsety; //!< Holds offset for Y in percentage
1395 
1396  DECLARE_DYNAMIC_CLASS(mpText)
1397 };
1398 
1399 
1400 //-----------------------------------------------------------------------------
1401 // mpPrintout - provided by Davide Rondini
1402 //-----------------------------------------------------------------------------
1403 
1404 /** Printout class used by mpWindow to draw in the objects to be printed.
1405  The object itself can then used by the default wxWidgets printing system
1406  to print mppWindow objects.
1407 */
1408 class WXDLLIMPEXP_MATHPLOT mpPrintout : public wxPrintout
1409 {
1410 public:
1411  mpPrintout(mpWindow* drawWindow, const wxChar *title = _T("wxMathPlot print output"));
1412  virtual ~mpPrintout() {};
1413 
1414  void SetDrawState(bool drawState) {drawn = drawState;};
1415  bool OnPrintPage(int page);
1416  bool HasPage(int page);
1417 
1418 private:
1419  bool drawn;
1421 };
1422 
1423 
1424 //-----------------------------------------------------------------------------
1425 // mpMovableObject - provided by Jose Luis Blanco
1426 //-----------------------------------------------------------------------------
1427 /** This virtual class represents objects that can be moved to an arbitrary 2D location+rotation.
1428  * The current transformation is set through SetCoordinateBase.
1429  * To ease the implementation of descendent classes, mpMovableObject will
1430  * be in charge of Bounding Box computation and layer rendering, assuming that
1431  * the object updates its shape in m_shape_xs & m_shape_ys.
1432  */
1434 {
1435 public:
1436  /** Default constructor (sets location and rotation to (0,0,0))
1437  */
1439  m_reference_x(0),
1440  m_reference_y(0),
1441  m_reference_phi(0),
1442  m_shape_xs(0),
1443  m_shape_ys(0)
1444  {
1445  m_type = mpLAYER_PLOT;
1446  }
1447 
1448  virtual ~mpMovableObject() {};
1449 
1450  /** Get the current coordinate transformation.
1451  */
1452  void GetCoordinateBase( double &x, double &y, double &phi ) const
1453  {
1454  x = m_reference_x;
1455  y = m_reference_y;
1456  phi = m_reference_phi;
1457  }
1458 
1459  /** Set the coordinate transformation (phi in radians, 0 means no rotation).
1460  */
1461  void SetCoordinateBase( double x, double y, double phi = 0 )
1462  {
1463  m_reference_x = x;
1464  m_reference_y = y;
1465  m_reference_phi = phi;
1466  m_flags = mpALIGN_NE;
1467  ShapeUpdated();
1468  }
1469 
1470  virtual bool HasBBox() { return m_trans_shape_xs.size()!=0; }
1471 
1472  /** Get inclusive left border of bounding box.
1473  */
1474  virtual double GetMinX() { return m_bbox_min_x; }
1475 
1476  /** Get inclusive right border of bounding box.
1477  */
1478  virtual double GetMaxX() { return m_bbox_max_x; }
1479 
1480  /** Get inclusive bottom border of bounding box.
1481  */
1482  virtual double GetMinY() { return m_bbox_min_y; }
1483 
1484  /** Get inclusive top border of bounding box.
1485  */
1486  virtual double GetMaxY() { return m_bbox_max_y; }
1487 
1488  virtual void Plot(wxDC & dc, mpWindow & w);
1489 
1490  /** Set label axis alignment.
1491  * @param align alignment (choose between mpALIGN_NE, mpALIGN_NW, mpALIGN_SW, mpALIGN_SE
1492  */
1493  void SetAlign(int align) { m_flags = align; };
1494 
1495 protected:
1496  int m_flags; //!< Holds label alignment
1497 
1498  /** The coordinates of the object (orientation "phi" is in radians).
1499  */
1500  double m_reference_x,m_reference_y,m_reference_phi;
1501 
1502  /** A method for 2D translation and rotation, using the current transformation stored in m_reference_x,m_reference_y,m_reference_phi.
1503  */
1504  void TranslatePoint( double x,double y, double &out_x, double &out_y );
1505 
1506  /** This contains the object points, in local coordinates (to be transformed by the current transformation).
1507  */
1508  std::vector<double> m_shape_xs,m_shape_ys;
1509 
1510  /** The buffer for the translated & rotated points (to avoid recomputing them with each mpWindow refresh).
1511  *
1512  */
1513  std::vector<double> m_trans_shape_xs,m_trans_shape_ys;
1514 
1515  /** The precomputed bounding box:
1516  * @sa ShapeUpdated
1517  */
1518  double m_bbox_min_x,m_bbox_max_x,m_bbox_min_y,m_bbox_max_y;
1519 
1520  /** Must be called by the descendent class after updating the shape (m_shape_xs/ys), or when the transformation changes.
1521  * This method updates the buffers m_trans_shape_xs/ys, and the precomputed bounding box.
1522  */
1523  void ShapeUpdated();
1524 
1525 };
1526 
1527 //-----------------------------------------------------------------------------
1528 // mpCovarianceEllipse - provided by Jose Luis Blanco
1529 //-----------------------------------------------------------------------------
1530 /** A 2D ellipse, described by a 2x2 covariance matrix.
1531  * The relation between the multivariate Gaussian confidence interval and
1532  * the "quantiles" in this class is:
1533  * - 1 : 68.27% confidence interval
1534  * - 2 : 95.45%
1535  * - 3 : 99.73%
1536  * - 4 : 99.994%
1537  * For example, see http://en.wikipedia.org/wiki/Normal_distribution#Standard_deviation_and_confidence_intervals
1538  *
1539  * The ellipse will be always centered at the origin. Use mpMovableObject::SetCoordinateBase to move it.
1540  */
1542 {
1543 public:
1544  /** Default constructor.
1545  * Initializes to a unity diagonal covariance matrix, a 95% confidence interval (2 sigmas), 32 segments, and a continuous plot (m_continuous=true).
1546  */
1548  double cov_00 = 1,
1549  double cov_11 = 1,
1550  double cov_01 = 0,
1551  double quantiles = 2,
1552  int segments = 32,
1553  const wxString & layerName = wxT("") ) :
1554  m_cov_00(cov_00),
1555  m_cov_11(cov_11),
1556  m_cov_01(cov_01),
1557  m_quantiles(quantiles),
1558  m_segments(segments)
1559  {
1560  m_continuous = true;
1561  m_name = layerName;
1562  RecalculateShape();
1563  m_type = mpLAYER_PLOT;
1564  }
1565 
1567 
1568  double GetQuantiles() const { return m_quantiles; }
1569 
1570  /** Set how many "quantiles" to draw, that is, the confidence interval of the ellipse (see above).
1571  */
1572  void SetQuantiles(double q)
1573  {
1574  m_quantiles=q;
1575  RecalculateShape();
1576  }
1577 
1578  void SetSegments( int segments ) { m_segments = segments; }
1579  int GetSegments( ) const { return m_segments; }
1580 
1581  /** Returns the elements of the current covariance matrix:
1582  */
1583  void GetCovarianceMatrix( double &cov_00,double &cov_01,double &cov_11 ) const
1584  {
1585  cov_00 = m_cov_00;
1586  cov_01 = m_cov_01;
1587  cov_11 = m_cov_11;
1588  }
1589 
1590  /** Changes the covariance matrix:
1591  */
1592  void SetCovarianceMatrix( double cov_00,double cov_01,double cov_11 )
1593  {
1594  m_cov_00 = cov_00;
1595  m_cov_01 = cov_01;
1596  m_cov_11 = cov_11;
1597  RecalculateShape();
1598  }
1599 
1600 protected:
1601  /** The elements of the matrix (only 3 since cov(0,1)=cov(1,0) in any positive definite matrix).
1602  */
1603  double m_cov_00,m_cov_11,m_cov_01;
1604  double m_quantiles;
1605 
1606  /** The number of line segments that build up the ellipse.
1607  */
1609 
1610  /** Called to update the m_shape_xs, m_shape_ys vectors, whenever a parameter changes.
1611  */
1612  void RecalculateShape();
1613 };
1614 
1615 //-----------------------------------------------------------------------------
1616 // mpPolygon - provided by Jose Luis Blanco
1617 //-----------------------------------------------------------------------------
1618 /** An arbitrary polygon, descendant of mpMovableObject.
1619  * Use "setPoints" to set the list of N points. This class also can draw non-closed polygons by
1620  * passing the appropriate parameters to "setPoints". To draw a point-cloud, call "SetContinuity(false)".
1621  */
1623 {
1624 public:
1625  /** Default constructor.
1626  */
1627  mpPolygon( const wxString & layerName = wxT("") )
1628  {
1629  m_continuous = true;
1630  m_name = layerName;
1631  }
1632 
1633  virtual ~mpPolygon() {}
1634 
1635  /** Set the points in the polygon.
1636  * @param points_xs The X coordinates of the points.
1637  * @param points_ys The Y coordinates of the points.
1638  * @param closedShape If set to true, an additional segment will be added from the last to the first point.
1639  */
1640  void setPoints(
1641  const std::vector<double>& points_xs,
1642  const std::vector<double>& points_ys,
1643  bool closedShape=true );
1644 
1645  /** Set the points in the polygon.
1646  * @param points_xs The X coordinates of the points.
1647  * @param points_ys The Y coordinates of the points.
1648  * @param closedShape If set to true, an additional segment will be added from the last to the first point.
1649  */
1650  void setPoints(
1651  const std::vector<float>& points_xs,
1652  const std::vector<float>& points_ys,
1653  bool closedShape=true );
1654 
1655 
1656 
1657 };
1658 
1659 //-----------------------------------------------------------------------------
1660 // mpMovableObject - provided by Jose Luis Blanco
1661 //-----------------------------------------------------------------------------
1662 /** This virtual class represents objects that can be moved to an arbitrary 2D location+rotation.
1663  * The current transformation is set through SetCoordinateBase.
1664  * To ease the implementation of descendent classes, mpMovableObject will
1665  * be in charge of Bounding Box computation and layer render, assuming that
1666  * the object updates its shape in m_shape_xs & m_shape_ys.
1667  */
1669 {
1670 public:
1671  /** Default constructor.
1672  */
1674  {
1675  m_min_x = m_max_x =
1676  m_min_y = m_max_y = 0;
1677  m_validImg = false;
1678  m_type = mpLAYER_BITMAP;
1679  }
1680 
1681  virtual ~mpBitmapLayer() {};
1682 
1683  /** Returns a copy of the current bitmap assigned to the layer.
1684  */
1685  void GetBitmapCopy( wxImage &outBmp ) const;
1686 
1687  /** Change the bitmap associated with the layer (to update the screen, refresh the mpWindow).
1688  * @param inBmp The bitmap to associate. A copy is made, thus it can be released after calling this.
1689  * @param x The left corner X coordinate (in plot units).
1690  * @param y The top corner Y coordinate (in plot units).
1691  * @param lx The width in plot units.
1692  * @param ly The height in plot units.
1693  */
1694  void SetBitmap( const wxImage &inBmp, double x, double y, double lx, double ly );
1695 
1696  virtual bool HasBBox() { return true; }
1697 
1698  /** Get inclusive left border of bounding box.
1699  */
1700  virtual double GetMinX() { return m_min_x; }
1701 
1702  /** Get inclusive right border of bounding box.
1703  */
1704  virtual double GetMaxX() { return m_max_x; }
1705 
1706  /** Get inclusive bottom border of bounding box.
1707  */
1708  virtual double GetMinY() { return m_min_y; }
1709 
1710  /** Get inclusive top border of bounding box.
1711  */
1712  virtual double GetMaxY() { return m_max_y; }
1713 
1714  virtual void Plot(wxDC & dc, mpWindow & w);
1715 
1716  /** Set label axis alignment.
1717  * @param align alignment (choose between mpALIGN_NE, mpALIGN_NW, mpALIGN_SW, mpALIGN_SE
1718  */
1719  void SetAlign(int align) { m_flags = align; };
1720 
1721 protected:
1722  int m_flags; //!< Holds label alignment
1723 
1724  /** The internal copy of the Bitmap:
1725  */
1726  wxImage m_bitmap;
1727  wxBitmap m_scaledBitmap;
1728  wxCoord m_scaledBitmap_offset_x,m_scaledBitmap_offset_y;
1729 
1730 
1732 
1733 
1734  /** The shape of the bitmap:
1735  */
1736  double m_min_x,m_max_x,m_min_y,m_max_y;
1737 
1738 
1739 };
1740 
1741 
1742 
1743 /*@}*/
1744 
1745 #if defined(_MSC_VER)
1746  #pragma warning(pop)
1747 #endif
1748 
1749 
1750 #endif // _MP_MATHPLOT_H_



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013