1 /*# ---------------------------------------------------------------------
3 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
6 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
7 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 # This software is governed by the CeCILL-B license under French law and
10 # abiding by the rules of distribution of free software. You can use,
11 # modify and/ or redistribute the software under the terms of the CeCILL-B
12 # license as circulated by CEA, CNRS and INRIA at the following URL
13 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
14 # or in the file LICENSE.txt.
16 # As a counterpart to the access to the source code and rights to copy,
17 # modify and redistribute granted by the license, users are provided only
18 # with a limited warranty and the software's author, the holder of the
19 # economic rights, and the successive licensors have only limited
22 # The fact that you are presently reading this means that you have had
23 # knowledge of the CeCILL-B license and that you accept its terms.
24 # ------------------------------------------------------------------------ */
26 /////////////////////////////////////////////////////////////////////////////
28 // Purpose: Framework for mathematical graph plotting in wxWindows
29 // Author: David Schalig
31 // Created: 21/07/2003
32 // Copyright: (c) David Schalig
33 // Licence: wxWindows licence
34 /////////////////////////////////////////////////////////////////////////////
36 #ifndef _MP_MATHPLOT_H_
37 #define _MP_MATHPLOT_H_
38 #define ZOOM_FACTOR 1.5
40 /* @file mathplot.h */
41 /* @mainpage wxMathPlot
42 wxMathPlot is a framework for mathematical graph plotting in wxWindows.
44 The framework is designed for convenience and ease of use.
46 @section screenshots Screenshots
47 <a href="screenshots.html">Go to the screenshots page.</a>
49 @section overview Overview
50 The heart of wxMathPlot is mpWindow, which is a 2D canvas for plot layers.
51 mpWindow can be embedded as subwindow in a wxPane, a wxFrame, or any other wxWindow.
52 mpWindow provides a zoomable and moveable view of the layers. The current view can
53 be controlled with the mouse, the scrollbars, and a context menu.
55 Plot layers are implementations of the abstract base class mpLayer. Those can
56 be function plots, scale rulers, or any other vector data visualisation. wxMathPlot provides
57 two mpLayer implementations for plotting horizontal and vertical rulers: mpScaleX and mpScaleY.
58 For convenient function plotting three more abstract base classes derived from mpLayer
59 are provided: mpFX, mpFY and mpFXY. These base classes already come with plot code, own
60 functions can be implemented by overiding just one member for retrieving a function value.
62 @section coding Coding conventions
63 wxMathPlot sticks to wxWindow's coding conventions. All entities defined by wxMathPlot
64 have the prefix <i>mp</i>.
66 @section author Author and license
67 wxMathPlot is published under the terms of the wxWindow license.
68 The author David Schalig can be contacted via the wxMathPlot's homepage at
69 http://sourceforge.net/projects/wxmathplot
73 #if defined(__GNUG__) && !defined(__APPLE__)
74 #pragma interface "mathplot.h"
84 #include "wx/scrolwin.h"
86 #include "wx/dynarray.h"
89 //-----------------------------------------------------------------------------
91 //-----------------------------------------------------------------------------
101 /** Command IDs used by mpWindow */
104 mpID_FIT = 2000, //!< Fit view to match bounding box of all layers
105 mpID_ZOOM_IN, //!< Zoom into view at clickposition / window center
106 mpID_ZOOM_OUT, //!< Zoom out
107 mpID_CENTER, //!< Center view on click position
108 mpID_LOCKASPECT, //!< Lock x/y scaling aspect
109 mpID_LINE_GUIDES, //!< Enables or disables the line guides drawing condition
112 //-----------------------------------------------------------------------------
114 //-----------------------------------------------------------------------------
116 /** Plot layer, abstract base class.
117 Any number of mpLayer implementations can be attached to mpWindow.
118 Examples for mpLayer implementations are function graphs, or scale rulers.
120 For convenience mpLayer defines a name, a font (wxFont), and a pen (wxPen)
121 as class members. These may or may not be used by implementations.
123 class creaMaracasVisu_EXPORT mpLayer : public wxObject
128 /** Check whether this layer has a bounding box.
129 The default implementation returns \a TRUE. Overide and return
130 FALSE if your mpLayer implementation should be ignored by the calculation
131 of the global bounding box for all layers in a mpWindow.
132 @retval TRUE Has bounding box
133 @retval FALSE Has not bounding box
135 virtual bool HasBBox() { return TRUE; }
137 /** Get inclusive left border of bounding box.
140 virtual double GetMinX() { return -1.0; }
142 /** Get inclusive right border of bounding box.
145 virtual double GetMaxX() { return 1.0; }
147 /** Get inclusive bottom border of bounding box.
150 virtual double GetMinY() { return -1.0; }
152 /** Get inclusive top border of bounding box.
155 virtual double GetMaxY() { return 1.0; }
157 /** Plot given view of layer to the given device context.
158 An implementation of this function has to transform layer coordinates to
159 wxDC coordinates based on the view parameters retrievable from the mpWindow
160 passed in \a w. The passed device context \a dc has its coordinate origin set
161 to the center of the visible area. The coordinate orientation is as show in the
164 +--------------------------------------------------+
167 | (wxDC origin 0,0) |
168 | x-------------> acending X |
172 +--------------------------------------------------+
174 Note that Y ascends in downward direction, whereas the usual vertical orientation
175 for mathematical plots is vice versa. Thus Y-orientation will be swapped usually,
176 when transforming between wxDC and mpLayer coordinates.
178 <b> Rules for transformation between mpLayer and wxDC coordinates </b>
180 dc_X = (layer_X - mpWindow::GetPosX()) * mpWindow::GetScaleX()
181 dc_Y = (mpWindow::GetPosY() - layer_Y) * mpWindow::GetScaleY() // swapping Y-orientation
183 layer_X = (dc_X / mpWindow::GetScaleX()) + mpWindow::GetPosX() // scale guaranted to be not 0
184 layer_Y = mpWindow::GetPosY() - (dc_Y / mpWindow::GetScaleY()) // swapping Y-orientation
187 @param dc Device context to plot to.
188 @param w View to plot. The visible area can be retrieved from this object.
190 virtual void Plot(wxDC & dc, mpWindow & w) = 0;
195 wxString GetName() const { return m_name; }
197 /** Get font set for this layer.
200 const wxFont& GetFont() const { return m_font; }
202 /** Get pen set for this layer.
205 const wxPen& GetPen() const { return m_pen; }
208 @param name Name, will be copied to internal class member
210 void SetName(wxString name) { m_name = name; }
213 @param font Font, will be copied to internal class member
215 void SetFont(wxFont& font) { m_font = font; }
218 @param pen Pen, will be copied to internal class member
220 void SetPen(wxPen& pen) { m_pen = pen; }
223 ** Get the translation of the Y coordinate acoording to the new orientation of the axis du to the problem
224 ** identified in MACOS with the funtion 'SetAxisOrientation'
226 int GetYTranslated(double sizey, double y){
231 wxFont m_font; //!< Layer's font
232 wxPen m_pen; //!< Layer's pen
233 wxString m_name; //!< Layer's name
235 DECLARE_CLASS(mpLayer)
238 //-----------------------------------------------------------------------------
239 // mpLayer implementations - functions
240 //-----------------------------------------------------------------------------
242 /** @name Label alignment constants
246 #define mpALIGNMASK 0x03
247 /** Aligns label to the right. For use with mpFX. */
248 #define mpALIGN_RIGHT 0x00
249 /** Aligns label to the center. For use with mpFX and mpFY. */
250 #define mpALIGN_CENTER 0x01
251 /** Aligns label to the left. For use with mpFX. */
252 #define mpALIGN_LEFT 0x02
253 /** Aligns label to the top. For use with mpFY. */
254 #define mpALIGN_TOP mpALIGN_RIGHT
255 /** Aligns label to the bottom. For use with mpFY. */
256 #define mpALIGN_BOTTOM mpALIGN_LEFT
257 /** Aligns label to north-east. For use with mpFXY. */
258 #define mpALIGN_NE 0x00
259 /** Aligns label to north-west. For use with mpFXY. */
260 #define mpALIGN_NW 0x01
261 /** Aligns label to south-west. For use with mpFXY. */
262 #define mpALIGN_SW 0x02
263 /** Aligns label to south-east. For use with mpFXY. */
264 #define mpALIGN_SE 0x03
268 /** @name mpLayer implementations - functions
271 /** Abstract base class providing plot and labeling functionality for functions F:X->Y.
272 Override mpFX::GetY to implement a function.
273 Optionally implement a constructor and pass a name (label) and a label alignment
274 to the constructor mpFX::mpFX. If the layer name is empty, no label will be plotted.
276 class mpFX : public mpLayer
279 /** @param name Label
280 @param flags Label alignment, pass one of #mpALIGN_RIGHT, #mpALIGN_CENTER, #mpALIGN_LEFT.
282 mpFX(wxString name = wxEmptyString, int flags = mpALIGN_RIGHT);
284 /** Get function value for argument.
285 Override this function in your implementation.
287 @return Function value
289 virtual double GetY( double x ) = 0;
291 /** Layer plot handler.
292 This implementation will plot the function in the visible area and
293 put a label according to the aligment specified.
295 virtual void Plot(wxDC & dc, mpWindow & w);
298 int m_flags; //!< Holds label alignment
303 /** Abstract base class providing plot and labeling functionality for functions F:Y->X.
304 Override mpFY::GetX to implement a function.
305 Optionally implement a constructor and pass a name (label) and a label alignment
306 to the constructor mpFY::mpFY. If the layer name is empty, no label will be plotted.
308 class mpFY : public mpLayer
311 /** @param name Label
312 @param flags Label alignment, pass one of #mpALIGN_BOTTOM, #mpALIGN_CENTER, #mpALIGN_TOP.
314 mpFY(wxString name = wxEmptyString, int flags = mpALIGN_TOP);
316 /** Get function value for argument.
317 Override this function in your implementation.
319 @return Function value
321 virtual double GetX( double y ) = 0;
323 /** Layer plot handler.
324 This implementation will plot the function in the visible area and
325 put a label according to the aligment specified.
327 virtual void Plot(wxDC & dc, mpWindow & w);
330 int m_flags; //!< Holds label alignment
335 /** Abstract base class providing plot and labeling functionality for a locus plot F:N->X,Y.
336 Locus argument N is assumed to be in range 0 .. MAX_N, and implicitely derived by enumrating
337 all locus values. Override mpFXY::Rewind and mpFXY::GetNextXY to implement a locus.
338 Optionally implement a constructor and pass a name (label) and a label alignment
339 to the constructor mpFXY::mpFXY. If the layer name is empty, no label will be plotted.
341 class mpFXY : public mpLayer
344 /** @param name Label
345 @param flags Label alignment, pass one of #mpALIGN_NE, #mpALIGN_NW, #mpALIGN_SW, #mpALIGN_SE.
347 mpFXY(wxString name = wxEmptyString, int flags = mpALIGN_NE);
349 /** Rewind value enumeration with mpFXY::GetNextXY.
350 Override this function in your implementation.
352 virtual void Rewind() = 0;
354 /** Get locus value for next N.
355 Override this function in your implementation.
356 @param x Returns X value
357 @param y Returns Y value
359 virtual bool GetNextXY(double & x, double & y) = 0;
361 /** Layer plot handler.
362 This implementation will plot the locus in the visible area and
363 put a label according to the aligment specified.
365 virtual void Plot(wxDC & dc, mpWindow & w);
368 int m_flags; //!< Holds label alignment
375 //-----------------------------------------------------------------------------
376 // mpLayer implementations - furniture (scales, ...)
377 //-----------------------------------------------------------------------------
379 /** @name mpLayer implementations - furniture (scales, ...)
382 /** Plot layer implementing a x-scale ruler.
383 The ruler is fixed at Y=0 in the coordinate system. A label is plottet at
384 the bottom-right hand of the ruler. The scale numbering automatically
385 adjusts to view and zoom factor.
387 class mpScaleX : public mpLayer
390 /** @param name Label to plot by the ruler */
391 mpScaleX(wxString name = wxT("X"));
393 /** Layer plot handler.
394 This implementation will plot the ruler adjusted to the visible area.
396 virtual void Plot(wxDC & dc, mpWindow & w);
398 /** Check whether this layer has a bounding box.
399 This implementation returns \a FALSE thus making the ruler invisible
400 to the plot layer bounding box calculation by mpWindow.
402 virtual bool HasBBox() { return FALSE; }
404 DECLARE_CLASS(mpScaleX)
407 /** Plot layer implementing a y-scale ruler.
408 The ruler is fixed at X=0 in the coordinate system. A label is plottet at
409 the top-right hand of the ruler. The scale numbering automatically
410 adjusts to view and zoom factor.
412 class mpScaleY : public mpLayer
415 /** @param name Label to plot by the ruler */
416 mpScaleY(wxString name = wxT("Y"));
418 /** Layer plot handler.
419 This implementation will plot the ruler adjusted to the visible area.
421 virtual void Plot(wxDC & dc, mpWindow & w, int orgy);
423 /** Check whether this layer has a bounding box.
424 This implementation returns \a FALSE thus making the ruler invisible
425 to the plot layer bounding box calculation by mpWindow.
427 virtual bool HasBBox() { return FALSE; }
431 DECLARE_CLASS(mpScaleY)
434 //-----------------------------------------------------------------------------
436 //-----------------------------------------------------------------------------
438 /** @name Constants defining mouse modes for mpWindow
441 /** Mouse panning drags the view. Mouse mode for mpWindow. */
442 #define mpMOUSEMODE_DRAG 0
443 /** Mouse panning creates a zoom box. Mouse mode for mpWindow. */
444 #define mpMOUSEMODE_ZOOMBOX 1
448 /** Canvas for plotting mpLayer implementations.
450 This class defines a zoomable and moveable 2D plot canvas. Any number
451 of mpLayer implementations (scale rulers, function plots, ...) can be
452 attached using mpWindow::AddLayer.
454 The canvas window provides a context menu with actions for navigating the view.
455 The context menu can be retrieved with mpWindow::GetPopupMenu, e.g. for extending it
458 class creaMaracasVisu_EXPORT mpWindow : public wxScrolledWindow
462 mpWindow( wxWindow *parent, wxWindowID id,
463 const wxPoint &pos = wxDefaultPosition,
464 const wxSize &size = wxDefaultSize,
468 /** Get reference to context menu of the plot canvas.
469 @return Pointer to menu. The menu can be modified.
471 wxMenu* GetPopupMenu() { return &m_popmenu; }
473 //-----------------------
474 // new methods for plotter
475 //-----------------------
493 set the max value in the x axis
496 void setMaxScrX(int maxX)
501 set the max value in the y axis
504 void setMaxScrY(int maxY)
510 /**Get maximum value in x
517 /**Get maximum value in y
525 returns the zoomFactor
527 float getZoomFactor()
532 set the min value in the x axis
535 void setMinScrX(int minX)
540 set the min value in the y axis
543 void setMinScrY(int minY)
549 /**Get miniimum value in x
556 /**Get minimum value in y
565 Get the x-clicked by the user
574 Get the y-clicked by the user
583 Gets the x-offset of the zoom
586 int getOffsetPixelsX()
592 Gets the offset of the zoom
595 int getOffsetPixelsY()
600 Set the x-offset of the zoom
602 void setOffsetPixelX(int offX)
607 Set the y-offset of the zoom
609 void setOffsetPixelY(int offY)
615 Gets the x-offset of the zoom
623 Gets the offset of the zoom
630 Set the x-offset of the zoom
632 void setOffsetX(int offX)
637 Set the y-offset of the zoom
639 void setOffsetY(int offY)
645 * Sets real value of the y-coord for the vertical guide line
646 * @param newX_realGuide The new value to assing for the vertical guide
648 void setRealGuideX(int newX_realGuide)
650 real_guideLine_X = newX_realGuide;
651 if(real_guideLine_X!=-1)
656 * Gets the real value of the y-coord for the vertical guide line
657 * @retval real_guideLine_X The assigned value for the vertical guide
661 return real_guideLine_X;
665 * Sets real value of the y-coord for the vertical guide line
666 * @param newY_realGuide The new value to assing for the vertical guide
668 void setRealGuideY(int newY_realGuide)
670 real_guideLine_Y = newY_realGuide;
671 if(real_guideLine_Y!=-1)
676 * Gets the real value of the y-coord for the vertical guide line
677 * @retval real_guideLine_Y The assigned value for the vertical guide
681 return real_guideLine_Y;
685 * Sets the condition for drawing or not the guide lines
686 * @param ifDrawing The new condition to assing
688 /*void setLineGuidesCondition(bool ifDrawing)
690 drawGuides = ifDrawing;
695 * Gets the condition for drawing or not the guide lines
696 * @retval drawGuides The assigned condition
698 bool drawGuideLines();
701 * Guide lines menu handler method that reacts to the mpID_LINE_GUIDES cimmand event
702 * event The corresponding event to handle
705 //void OnGuideLines (wxCommandEvent &event);
707 //----------------------------------------------------------------------------------
709 //----------------------------------------------------------------------------------
712 /** Add a plot layer to the canvas.
713 @param layer Pointer to layer. The mpLayer object will get under control of mpWindow,
714 i.e. it will be delete'd on mpWindow destruction
716 @retval FALSE Failure due to out of memory.
718 bool AddLayer( mpLayer* layer);
720 /** Remove a plot layer from the canvas.
721 @param layer Pointer to layer. The mpLayer object will be destructed using delete.
723 void DelLayer( mpLayer* layer);
725 /** Get current view's X scale.
726 See @ref mpLayer::Plot "rules for coordinate transformation"
729 double GetScaleX(void) const { return m_scaleX; }
731 /** Get current view's Y scale.
732 See @ref mpLayer::Plot "rules for coordinate transformation"
735 double GetScaleY(void) const { return m_scaleY; }
737 /** Get current view's X position.
738 See @ref mpLayer::Plot "rules for coordinate transformation"
739 @return X Position in layer coordinate system, that corresponds to the center point of the view.
741 double GetPosX(void) const { return m_posX; }
743 /** Get current view's Y position.
744 See @ref mpLayer::Plot "rules for coordinate transformation"
745 @return Y Position in layer coordinate system, that corresponds to the center point of the view.
747 double GetPosY(void) const { return m_posY; }
749 /** Get current view's X dimension in device context units.
750 Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
751 implementations should rely on the value returned by the function.
752 See @ref mpLayer::Plot "rules for coordinate transformation"
755 int GetScrX(void) const { return m_scrX; }
757 /** Get current view's Y dimension in device context units.
758 Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
759 implementations should rely on the value returned by the function.
760 See @ref mpLayer::Plot "rules for coordinate transformation"
763 int GetScrY(void) const { return m_scrY; }
764 //void SetScrY(int x) const { return m_scrY; }
766 /** Set current view's X scale and refresh display.
767 @param scaleX New scale, must not be 0.
769 void SetScaleX(double scaleX) { if (scaleX!=0) m_scaleX=scaleX; /*UpdateAll();*/ }
771 /** Set current view's Y scale and refresh display.
772 @param scaleY New scale, must not be 0.
774 void SetScaleY(double scaleY) { if (scaleY!=0) m_scaleY=scaleY; /*UpdateAll();*/ }
776 /** Set current view's X position and refresh display.
777 @param posX New position that corresponds to the center point of the view.
779 void SetPosX(double posX) { m_posX=posX; UpdateAll(); }
781 /** Set current view's Y position and refresh display.
782 @param posY New position that corresponds to the center point of the view.
784 void SetPosY(double posY) { m_posY=posY; UpdateAll(); }
786 /** Set current view's X and Y position and refresh display.
787 @param posX New position that corresponds to the center point of the view.
788 @param posY New position that corresponds to the center point of the view.
790 void SetPos( double posX, double posY) { m_posX=posX; m_posY=posY; UpdateAll(); }
792 /** Enable or disable X/Y scale aspect locking for the view.
793 @note Explicit calls to mpWindow::SetScaleX and mpWindow::SetScaleY will set
794 an unlocked apect, but any other action changing the view scale will
795 lock the aspect again.
797 void LockAspect(bool enable = TRUE);
799 /** Checks whether the X/Y scale aspect is locked.
801 @retval FALSE Unlocked
803 inline bool IsAspectLocked() { return m_lockaspect; }
805 /** Set view to fit global bounding box of all plot layers and refresh display.
806 Scale and position will be set to a show all attached mpLayers.
807 The X/Y scale aspect lock is taken into account.
811 /** Zoom into current view and refresh display */
814 /** Zoom out current view and refresh display */
817 /** Refresh display */
821 ** Get the translation of the Y coordinate
823 int GetYTranslated(wxSize size, double y){
824 return size.GetHeight()-y;
829 void Refresh(bool eraseBackground = true, const wxRect* rect = NULL);
830 void OnPaint (wxPaintEvent &event); //!< Paint handler, will plot all attached layers
831 void OnSize (wxSizeEvent &event); //!< Size handler, will update scroll bar sizes
832 void OnScroll2 (wxScrollWinEvent &event); //!< Scroll handler, will move canvas
833 void OnShowPopupMenu (wxMouseEvent &event); //!< Mouse handler, will show context menu
834 void OnCenter (wxCommandEvent &event); //!< Context menu handler
835 void OnFit (wxCommandEvent &event); //!< Context menu handler
836 void OnZoomIn (wxCommandEvent &event); //!< Context menu handler
837 void OnZoomOut (wxCommandEvent &event); //!< Context menu handler
838 void OnLockAspect (wxCommandEvent &event); //!< Context menu handler
841 bool UpdateBBox(); //!< Recalculate global layer bounding box
843 wxList m_layers; //!< List of attached plot layers
844 wxMenu m_popmenu; //!< Canvas' context menu
845 bool m_lockaspect;//!< Scale aspect is locked or not
847 double m_minX; //!< Global layer bounding box, left border incl.
848 double m_maxX; //!< Global layer bounding box, right border incl.
849 double m_minY; //!< Global layer bounding box, bottom border incl.
850 double m_maxY; //!< Global layer bounding box, top border incl.
851 double m_scaleX; //!< Current view's X scale
852 double m_scaleY; //!< Current view's Y scale
853 double m_posX; //!< Current view's X position
854 double m_posY; //!< Current view's Y position
855 int m_scrX; //!< Current view's X dimension
856 int m_scrY; //!< Current view's Y dimension
857 int m_clickedX; //!< Last mouse click X position, for centering and zooming the view
858 int m_clickedY; //!< Last mouse click Y position, for centering and zooming the view
860 //----------------------------------------------
861 //NEW ATTRIBUTES FOR COMPATIBILITY WITH PPlotter
862 //----------------------------------------------
864 the max value in the x axis
869 the max value in the y axis
873 the min value in the x axis
878 the min value in the y axis
889 offset in pixels where the user has clicked
890 before changing the scale (in the actual function)
895 Offsets in real value according to the actual function
901 * The real value of the y-coord for the horizontal guide line
903 int real_guideLine_X;
905 * The real value of the y-coord for the vertical guide line
907 int real_guideLine_Y;
910 * Represents the condition for drawing or not the line guides, default color is red and assigned to draw them
914 Use to know which type of plotter is
921 //bitmap of functions
922 wxBitmap *_bitmap_functions;
925 DECLARE_CLASS(mpWindow)
926 DECLARE_EVENT_TABLE()
929 #endif // _MP_MATHPLOT_H_