1 /*************************************************************************************
2  *  Copyright (C) 2011 by Aleix Pol <aleixpol@kde.org>                               *
3  *  Copyright (C) 2012-2013 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com> *
4  *                                                                                   *
5  *  This program is free software; you can redistribute it and/or                    *
6  *  modify it under the terms of the GNU General Public License                      *
7  *  as published by the Free Software Foundation; either version 2                   *
8  *  of the License, or (at your option) any later version.                           *
9  *                                                                                   *
10  *  This program is distributed in the hope that it will be useful,                  *
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
13  *  GNU General Public License for more details.                                     *
14  *                                                                                   *
15  *  You should have received a copy of the GNU General Public License                *
16  *  along with this program; if not, write to the Free Software                      *
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
18  *************************************************************************************/
19 
20 #ifndef PLOTTER2D_H
21 #define PLOTTER2D_H
22 
23 #include <QRectF>
24 #include <QLineF>
25 #include <QString>
26 #include <QPair>
27 #include <QColor>
28 
29 #include "analitzaplotexport.h"
30 #include <analitzaplot/plottingenums.h>
31 
32 class QAbstractItemModel;
33 class QPainter;
34 class QPaintDevice;
35 class QModelIndex;
36 
37 namespace Analitza
38 {
39 class PlotItem;
40 class Plotter2DPrivate;
41 /**
42  * \class Plotter2D
43  *
44  * \ingroup AnalitzaPlotModule
45  *
46  * \brief Render 2D plots.
47  *
48  * This class uses QPainter as backend for drawing plots.
49  * The default value of showGrid is true.
50  * The default grid color is Qt::lightGray.
51  * The default background color is Qt::white.
52  * The default value of autoGridStyle is true.
53  */
54 
55 class ANALITZAPLOT_EXPORT Plotter2D
56 {
57     private: // private structs
58         struct GridInfo; // interval structure for carry current grid state information across interval methods
59 
60     public:
61         explicit Plotter2D(const QSizeF& size);
62         virtual ~Plotter2D();
63 
64         /** Sets whether we will draw the grid. */
65         void setShowGrid(bool show);
66         //only works if showgrid is true. for polar grid it affects to subdivision of angles/rays
67         void setShowMinorGrid(bool mt);
68 
69         /** Returns whether we have chosen to draw the grid. */
showGrid()70         bool showGrid() const {return m_showGrid; }
71 
72         /** Returns whether we have chosen to draw the minor grid. */
showMinorGrid()73         bool showMinorGrid() const {return m_showMinorGrid; }
74 
setGridColor(const QColor & color)75         void setGridColor(const QColor &color) { m_gridColor = color;  forceRepaint(); }
76 
77         //default Qt::lightGray
gridColor()78         QColor gridColor() const { return m_gridColor; }
79 
setBackgroundColor(const QColor & color)80         void setBackgroundColor(const QColor &color) { m_backgroundColor = color;  forceRepaint(); }
81 
82         // default Qt::white
backgroundColor()83         QColor backgroundColor() const { return m_backgroundColor; }
84 
85         /** If true then we ignore the grid style suggested by setGridStyleHint, if false then we use as grid style the hint. */
setAutoGridStyle(bool autogs)86         void setAutoGridStyle(bool autogs) { m_autoGridStyle = autogs; forceRepaint(); }
87 
88         /** Returns whether we will change automatically the grid style based on the curent plot. */
autoGridStyle()89         bool autoGridStyle() const { return m_autoGridStyle; }
90 
91         /** Sets the suggested grid style. Only works if autoGridStyle is false. Note that we only accept CoordinateSystem::Cartesian or CoordinateSystem::Polar. */
92         void setGridStyleHint(GridStyle suggestedgs);
93 
94         /** Sets whether it has to keep the aspect ratio (1:1 grid). */
95         void setKeepAspectRatio(bool ar);
96 
97         /** Sets whether it is keeping the aspect ratio (1:1 grid). */
keepAspectRatio()98         bool keepAspectRatio() const { return m_keepRatio; }
99 
100         /** Force the functions from @p start to @p end to be recalculated. */
101         void updateFunctions(const QModelIndex & parent, int start, int end);
102 
103         void setModel(QAbstractItemModel* f);
104         QAbstractItemModel* model() const;
105 
106         /** Sets the graph's viewport to @p v. */
107         void setViewport(const QRectF& vp, bool repaint=true);
108 
109         //TODO doc
110         //normlized current viewport, that includes scale information
currentViewport()111         QRectF currentViewport() const { return viewport; }
112 
113         //DEPRECATED
lastViewport()114         QRectF lastViewport() const { return currentViewport(); }
115 
116         /** Moves the viewport @p delta */
117         void moveViewport(const QPoint& delta);
118 
119         void setXAxisLabel(const QString &label);
120         void setYAxisLabel(const QString &label);
121 
122         //by default linear
setScaleMode(ScaleMode sm)123         void setScaleMode(ScaleMode sm) { m_scaleMode = sm; forceRepaint(); }
scaleMode()124         ScaleMode scaleMode() const { return m_scaleMode; }
125 
126         //default radiasn, this will afecto when scalemode is trig and for the angles in polargridmode
setAngleMode(AngleMode am)127         void setAngleMode(AngleMode am) { m_angleMode = am; forceRepaint(); }
angleMode()128         AngleMode angleMode() const { return m_angleMode; }
129 
setShowTicks(Qt::Orientations o)130         void setShowTicks(Qt::Orientations o) { m_showTicks = o; forceRepaint(); }
setShowTickLabels(Qt::Orientations o)131         void setShowTickLabels(Qt::Orientations o) { m_showTickLabels = o; forceRepaint(); }
132         //only works if showticks is true
setShowMinorTicks(bool mt)133         void setShowMinorTicks(bool mt) { m_showMinorTicks=mt; forceRepaint(); }
minorTicksShown()134         bool minorTicksShown() const { return m_showMinorTicks; }
135 
136         //these 2 only work when gridmode is polar, showpolar axis aumenta cuando esta lejos de origin
setShowPolarAxis(bool pt)137         void setShowPolarAxis(bool pt) { m_showPolarAxis = pt;  forceRepaint(); }
setShowPolarAngles(bool pt)138         void setShowPolarAngles(bool pt) { m_showPolarAngles = pt;  forceRepaint(); }
139 
setShowAxes(Qt::Orientations o)140         void setShowAxes(Qt::Orientations o) { m_showAxes = o; forceRepaint(); }
141 
ticksShown()142         Qt::Orientations ticksShown() const { return m_showTickLabels; }
143 
144         /** Zooms in to the Viewport center */
145         void zoomIn(bool repaint=true);
146 
147         /** Zooms out taken ref center too*/
148         void zoomOut(bool repaint=true);
149 
150     protected:
151         virtual void drawGrid(QPaintDevice *qpd);
152         virtual void drawFunctions(QPaintDevice *qpd);
153         virtual void forceRepaint() = 0;
154         virtual void viewportChanged() = 0;
155         virtual int currentFunction() const = 0;
156         virtual void modelChanged() = 0;
157         virtual void showGridChanged() = 0;
158 
159     protected: // utils
lastUserViewport()160         QRectF lastUserViewport() const { return userViewport; }
161         QRectF normalizeUserViewport(const QRectF &uvp); // from userViewport to viewport, this one uses current scale information
162         void updateScale(bool repaint);
163 
164         QPointF toWidget(const QPointF &) const;
165         QPointF fromWidget(const QPoint& p) const;
166         QPointF toViewport(const QPoint& mv) const;
167         QPair<QPointF, QString> calcImage(const QPointF& ndp) const;
168         QLineF slope(const QPointF& dp) const;
169 
170         QLineF toWidget(const QLineF &) const;
171         void setPaintedSize(const QSize& size);
172         void setDevicePixelRatio(qreal dpr);
173         void scaleViewport(qreal scale, const QPoint& center, bool repaint=true);
174 
175     private:
176         void drawAxes(QPainter* painter, GridStyle a) const;
177         void drawCircles(QPainter* painter, const GridInfo& gridinfo, GridStyle gridStyle) const;
178         void drawSquares(QPainter* painter, const GridInfo& gridinfo, GridStyle gridStyle) const;
179         void drawMainAxes(QPainter* painter) const;
180         void drawCartesianTickLabels(QPainter* painter, const GridInfo& gridinfo, CartesianAxis axis) const;
181         void drawPolarTickLabels(QPainter* painter, const GridInfo& gridinfo) const;
182         void drawGridTickLabels(QPainter* painter, const GridInfo& gridinfo, GridStyle gridStyle) const;
183         PlotItem *itemAt(int row) const;
width()184         int width() const { return m_size.width(); }
height()185         int height() const { return m_size.height(); }
186 
187         const GridInfo getGridInfo() const; // calculate correct grid params
188         const QColor computeSubGridColor() const;
189         const QString computeAngleLabelByFrac(unsigned int n, unsigned int d) const; // input npi/d return angle in m_angleMode
190         const QString computeAngleLabelByStep(unsigned int k, unsigned int step) const; // input n*step*pi return angle in m_angleMode
191 
192         bool m_showGrid;
193         bool m_showMinorGrid;
194         QColor m_gridColor;
195         QColor m_backgroundColor;
196         bool m_autoGridStyle;
197         GridStyle m_gridStyleHint;
198         //TODO set move auto tick labels
199 
200         double rang_x, rang_y;
201         bool m_keepRatio;
202         bool m_dirty; // or m_updated; como ahora contamos con setmodel, es necesario que se actualicen los datos antes de pintar, es necesario que no sea dirty
203         QRectF viewport; // normalized viewport (with scale information), this one is the current viewport (used in currentViewport)
204         QRectF userViewport; // raw viewport that user sets by setViewport, so we need to normalized userViewport into viewport to include scale and aspect radio information
205         QSizeF m_size;
206 
207         friend class Plotter2DPrivate;
208         Plotter2DPrivate* const d;
209 
210         AngleMode m_angleMode;
211         ScaleMode m_scaleMode;
212         Qt::Orientations m_showTicks;
213         Qt::Orientations m_showTickLabels;
214         bool m_showMinorTicks;
215         Qt::Orientations m_showAxes;
216         bool m_showPolarAxis;
217         bool m_showPolarAngles;
218         QString m_axisXLabel;
219         QString m_axisYLabel;
220 
221     private: // constants
222         static const QColor m_axeColor;
223         static const QColor m_derivativeColor;
224         static const QString PiSymbol;
225         static const QString DegreeSymbol;
226         static const QString GradianSymbol;
227         static const double Pi6; // pi/6
228         static const double Pi12; // pi/12
229         static const double Pi36; // pi/36
230         static const double ZoomInFactor;
231         static const double ZoomOutFactor;
232 };
233 
234 }
235 
236 #endif // PLOTTER2D_H
237