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,
469 /** Get reference to context menu of the plot canvas.
470 @return Pointer to menu. The menu can be modified.
472 wxMenu* GetPopupMenu() { return &m_popmenu; }
474 //-----------------------
475 // new methods for plotter
476 //-----------------------
494 set the max value in the x axis
497 void setMaxScrX(int maxX)
502 set the max value in the y axis
505 void setMaxScrY(int maxY)
511 /**Get maximum value in x
518 /**Get maximum value in y
526 returns the zoomFactor
528 float getZoomFactor()
533 set the min value in the x axis
536 void setMinScrX(int minX)
541 set the min value in the y axis
544 void setMinScrY(int minY)
550 /**Get miniimum value in x
557 /**Get minimum value in y
566 Get the x-clicked by the user
575 Get the y-clicked by the user
584 Gets the x-offset of the zoom
587 int getOffsetPixelsX()
593 Gets the offset of the zoom
596 int getOffsetPixelsY()
601 Set the x-offset of the zoom
603 void setOffsetPixelX(int offX)
608 Set the y-offset of the zoom
610 void setOffsetPixelY(int offY)
616 Gets the x-offset of the zoom
624 Gets the offset of the zoom
631 Set the x-offset of the zoom
633 void setOffsetX(int offX)
638 Set the y-offset of the zoom
640 void setOffsetY(int offY)
646 * Sets real value of the y-coord for the vertical guide line
647 * @param newX_realGuide The new value to assing for the vertical guide
649 void setRealGuideX(int newX_realGuide)
651 real_guideLine_X = newX_realGuide;
652 if(real_guideLine_X!=-1)
657 * Gets the real value of the y-coord for the vertical guide line
658 * @retval real_guideLine_X The assigned value for the vertical guide
662 return real_guideLine_X;
666 * Sets real value of the y-coord for the vertical guide line
667 * @param newY_realGuide The new value to assing for the vertical guide
669 void setRealGuideY(int newY_realGuide)
671 real_guideLine_Y = newY_realGuide;
672 if(real_guideLine_Y!=-1)
677 * Gets the real value of the y-coord for the vertical guide line
678 * @retval real_guideLine_Y The assigned value for the vertical guide
682 return real_guideLine_Y;
686 * Sets the condition for drawing or not the guide lines
687 * @param ifDrawing The new condition to assing
689 /*void setLineGuidesCondition(bool ifDrawing)
691 drawGuides = ifDrawing;
696 * Gets the condition for drawing or not the guide lines
697 * @retval drawGuides The assigned condition
699 bool drawGuideLines();
702 * Guide lines menu handler method that reacts to the mpID_LINE_GUIDES cimmand event
703 * event The corresponding event to handle
706 //void OnGuideLines (wxCommandEvent &event);
708 //----------------------------------------------------------------------------------
710 //----------------------------------------------------------------------------------
713 /** Add a plot layer to the canvas.
714 @param layer Pointer to layer. The mpLayer object will get under control of mpWindow,
715 i.e. it will be delete'd on mpWindow destruction
717 @retval FALSE Failure due to out of memory.
719 bool AddLayer( mpLayer* layer);
721 /** Remove a plot layer from the canvas.
722 @param layer Pointer to layer. The mpLayer object will be destructed using delete.
724 void DelLayer( mpLayer* layer);
726 /** Get current view's X scale.
727 See @ref mpLayer::Plot "rules for coordinate transformation"
730 double GetScaleX(void) const { return m_scaleX; }
732 /** Get current view's Y scale.
733 See @ref mpLayer::Plot "rules for coordinate transformation"
736 double GetScaleY(void) const { return m_scaleY; }
738 /** Get current view's X position.
739 See @ref mpLayer::Plot "rules for coordinate transformation"
740 @return X Position in layer coordinate system, that corresponds to the center point of the view.
742 double GetPosX(void) const { return m_posX; }
744 /** Get current view's Y position.
745 See @ref mpLayer::Plot "rules for coordinate transformation"
746 @return Y Position in layer coordinate system, that corresponds to the center point of the view.
748 double GetPosY(void) const { return m_posY; }
750 /** Get current view's X dimension in device context units.
751 Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
752 implementations should rely on the value returned by the function.
753 See @ref mpLayer::Plot "rules for coordinate transformation"
756 int GetScrX(void) const { return m_scrX; }
758 /** Get current view's Y dimension in device context units.
759 Usually this is equal to wxDC::GetSize, but it might differ thus mpLayer
760 implementations should rely on the value returned by the function.
761 See @ref mpLayer::Plot "rules for coordinate transformation"
764 int GetScrY(void) const { return m_scrY; }
765 //void SetScrY(int x) const { return m_scrY; }
767 /** Set current view's X scale and refresh display.
768 @param scaleX New scale, must not be 0.
770 void SetScaleX(double scaleX) { if (scaleX!=0) m_scaleX=scaleX; /*UpdateAll();*/ }
772 /** Set current view's Y scale and refresh display.
773 @param scaleY New scale, must not be 0.
775 void SetScaleY(double scaleY) { if (scaleY!=0) m_scaleY=scaleY; /*UpdateAll();*/ }
777 /** Set current view's X position and refresh display.
778 @param posX New position that corresponds to the center point of the view.
780 void SetPosX(double posX) { m_posX=posX; UpdateAll(); }
782 /** Set current view's Y position and refresh display.
783 @param posY New position that corresponds to the center point of the view.
785 void SetPosY(double posY) { m_posY=posY; UpdateAll(); }
787 /** Set current view's X and Y position and refresh display.
788 @param posX New position that corresponds to the center point of the view.
789 @param posY New position that corresponds to the center point of the view.
791 void SetPos( double posX, double posY) { m_posX=posX; m_posY=posY; UpdateAll(); }
793 /** Enable or disable X/Y scale aspect locking for the view.
794 @note Explicit calls to mpWindow::SetScaleX and mpWindow::SetScaleY will set
795 an unlocked apect, but any other action changing the view scale will
796 lock the aspect again.
798 void LockAspect(bool enable = TRUE);
800 /** Checks whether the X/Y scale aspect is locked.
802 @retval FALSE Unlocked
804 inline bool IsAspectLocked() { return m_lockaspect; }
806 /** Set view to fit global bounding box of all plot layers and refresh display.
807 Scale and position will be set to a show all attached mpLayers.
808 The X/Y scale aspect lock is taken into account.
812 /** Zoom into current view and refresh display */
815 /** Zoom out current view and refresh display */
818 /** Refresh display */
822 ** Get the translation of the Y coordinate
824 int GetYTranslated(wxSize size, double y){
825 return size.GetHeight()-y;
830 void Refresh(bool eraseBackground = true, const wxRect* rect = NULL);
831 void OnPaint (wxPaintEvent &event); //!< Paint handler, will plot all attached layers
832 void OnSize (wxSizeEvent &event); //!< Size handler, will update scroll bar sizes
833 void OnScroll2 (wxScrollWinEvent &event); //!< Scroll handler, will move canvas
834 void OnShowPopupMenu (wxMouseEvent &event); //!< Mouse handler, will show context menu
835 void OnCenter (wxCommandEvent &event); //!< Context menu handler
836 void OnFit (wxCommandEvent &event); //!< Context menu handler
837 void OnZoomIn (wxCommandEvent &event); //!< Context menu handler
838 void OnZoomOut (wxCommandEvent &event); //!< Context menu handler
839 void OnLockAspect (wxCommandEvent &event); //!< Context menu handler
842 bool UpdateBBox(); //!< Recalculate global layer bounding box
844 wxList m_layers; //!< List of attached plot layers
845 wxMenu m_popmenu; //!< Canvas' context menu
846 bool m_lockaspect;//!< Scale aspect is locked or not
848 double m_minX; //!< Global layer bounding box, left border incl.
849 double m_maxX; //!< Global layer bounding box, right border incl.
850 double m_minY; //!< Global layer bounding box, bottom border incl.
851 double m_maxY; //!< Global layer bounding box, top border incl.
852 double m_scaleX; //!< Current view's X scale
853 double m_scaleY; //!< Current view's Y scale
854 double m_posX; //!< Current view's X position
855 double m_posY; //!< Current view's Y position
856 int m_scrX; //!< Current view's X dimension
857 int m_scrY; //!< Current view's Y dimension
858 int m_clickedX; //!< Last mouse click X position, for centering and zooming the view
859 int m_clickedY; //!< Last mouse click Y position, for centering and zooming the view
861 //----------------------------------------------
862 //NEW ATTRIBUTES FOR COMPATIBILITY WITH PPlotter
863 //----------------------------------------------
865 the max value in the x axis
870 the max value in the y axis
874 the min value in the x axis
879 the min value in the y axis
890 offset in pixels where the user has clicked
891 before changing the scale (in the actual function)
896 Offsets in real value according to the actual function
902 * The real value of the y-coord for the horizontal guide line
904 int real_guideLine_X;
906 * The real value of the y-coord for the vertical guide line
908 int real_guideLine_Y;
911 * Represents the condition for drawing or not the line guides, default color is red and assigned to draw them
915 Use to know which type of plotter is
923 //bitmap of functions
924 wxBitmap *_bitmap_functions;
927 //EED 2017-09-16 Migration wxWidgets 2.8 to 3.0
928 #if wxMAJOR_VERSION <= 2
929 DECLARE_CLASS(mpWindow)
931 wxDECLARE_DYNAMIC_CLASS(mpWindow);
934 DECLARE_EVENT_TABLE()
939 #endif // _MP_MATHPLOT_H_