JKQTPlotter trunk/v5.0.0
an extensive Qt5+Qt6 Plotter framework (including a feature-richt plotter widget, a speed-optimized, but limited variant and a LaTeX equation renderer!), written fully in C/C++ and without external dependencies
Loading...
Searching...
No Matches
jkqtpvectorfield.h
1/*
2 Copyright (c) 2008-2024 Jan W. Krieger (<jan@jkrieger.de>)
3
4
5
6 This software is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License (LGPL) as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License (LGPL) for more details.
15
16 You should have received a copy of the GNU Lesser General Public License (LGPL)
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef jkqtpvectorfield_H
21#define jkqtpvectorfield_H
22
23
24#include <QString>
25#include <QPainter>
26#include <QPair>
27#include <functional>
28#include "jkqtplotter/jkqtptools.h"
29#include "jkqtplotter/jkqtplotter_imexport.h"
30#include "jkqtplotter/jkqtpgraphsbase.h"
31#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
32
33// forward declarations
34class JKQTBasePlotter;
35class JKQTPlotter;
37class JKQTPDatastore;
38
39
40
41/*! \brief This graph plots a vector field, i.e. a set of vectors (dx,dy) or (angle,length) at positions (x,y).
42 This class immplements the most basic form of vector plot, i.e. the vector are drawn with a length
43 corresponding to their magnitude.
44 \ingroup jkqtplotter_vectorfieldgraphs
45
46 \note This type of plot is sometimes also refered to as <b>quiver plot</b> (e.g. in Matlab or matplotlib)
47
48 \image html JKQTPVectorFieldGraph.png
49
50 To achieve this, use code like this:
51 \code
52 // 1. setup a plotter window and get a pointer to the internal datastore (for convenience)
53 JKQTPlotter plot;
54 JKQTPDatastore* ds=plot.getDatastore();
55
56 // 2. make up some arbitrary data to be used for plotting
57 // this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y)*sqrt(x/3.0) and dy=sin(x)*sqrt(x/3.0)
58 const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
59 const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
60 const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
61
62 // 3. create JKQTPVectorFieldGraph to display the data:
63 JKQTPVectorFieldGraph* graph1=new JKQTPVectorFieldGraph(&plot);
64 graph1->setXYColumns(columnXY);
65 graph1->setDxColumn(columnDX);
66 graph1->setDyColumn(columnDY);
67 graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));
68
69 // 4. add the graphs to the plot, so it is actually displayed
70 plot.addGraph(graph1);
71 \endcode
72
73 You have several options to influence the way the vectors are drawn:
74 1. You can change the tip shape (and actually also the tail) of the vector by using the methods from
75 JKQTPGraphDecoratedLineStyleMixin, e.g. use JKQTPGraphDecoratedLineStyleMixin::setHeadDecoratorStyle()
76 to set another shape for the vector's tip, or modify JKQTPGraphDecoratedLineStyleMixin::setHeadDecoratorSizeFactor()
77 to modify the size of the vector's head. the vector line width, color etz. can be modified by the
78 methods from JKQTPGraphLineStyleMixin, like JKQTPGraphLineStyleMixin::setLineColor() or
79 JKQTPGraphLineStyleMixin::setLineWidth().
80 2. By default the length of the drawn vectors corresponds to the actual length of the vector data,
81 but is modified by an autoscaling algorithm that should prevent them from overlapping.
82 This behaviour can be changed by setVectorLengthMode() with the different options described in
83 VectorLengthMode.
84 3. By default, vector start at \c (x,y). But you can also make them be centered around or
85 point to \c (x,y) . This can be set by setAnchorPoint().
86 4. Using setVectorLineWidthMode(JKQTPVectorFieldGraph::AutoscaleLineWidthFromLength) you can also
87 scale the line width of each vector by the vector's length. This sometimes gives an easier to read
88 representation of the vector properties, especially if combined with
89 setVectorLengthMode(JKQTPVectorFieldGraph::IgnoreLength) :
90 \image html JKQTPVectorFieldGraphIgnoreLengthAutoscaleLineWidthFromLength.png
91 .
92
93 \see \ref JKQTPlotterVectorFieldExample , JKQTPGraphDecoratedLineStyleMixin , JKQTPXYAndVectorGraph and JKQTPParametrizedVectorFieldGraph for a user-colored alternative
94
95 */
97 Q_OBJECT
98 public:
99 /** \brief indicates the position of the point \c (x,y) relative to the vector */
101 AnchorBottom, //!< \brief this is the default: the vector starts at \c (x,y) \image html JKQTPVectorFieldGraphAnchorBottom.png
102 AnchorMid, //!< \brief the vector's mid is at \c (x,y) \image html JKQTPVectorFieldGraphAnchorMid.png
103 AnchorTip //!< \brief the vector ends at \c (x,y) \image html JKQTPVectorFieldGraphAnchorTip.png
104 };
105 Q_ENUM(VectorAnchorPoint)
106
107 /** \brief indicates how the drawn vector's length is calculated from the data
108 *
109 * \see documentation of m_vectorLengthMode for details
110 */
112 AutoscaleLength, //!< \brief this is the default: vector lengths are autoscaled, so they don't overlap (in first approximation) \image html JKQTPVectorFieldGraphAnchorBottom.png
113 LengthFromData, //!< \brief the vector's length is determined by the data directly \image html JKQTPVectorFieldGraphAnchorMid.png
114 IgnoreLength //!< \brief all vectors have the same length \image html JKQTPVectorFieldGraphAnchorTip.png
115 };
116 Q_ENUM(VectorLengthMode)
117
118 /** \brief describes how the line width scales with the vector properties (or not) */
120 DefaultVectorLineWidth, //!< \brief line width is equal to JKQTPGraphLineStyleMixin::getLineWidth() for all vectors \image html JKQTPVectorFieldGraphIgnoreLength.png
121 AutoscaleLineWidthFromLength, //!< \brief line width is determined from the vector length. The maximum line width is given by JKQTPGraphLineStyleMixin::getLineWidth() and the minim line width by getMinLineWidth() \image html JKQTPVectorFieldGraphAutoscaleLengthAutoscaleLineWidthFromLength.png
122
123
124 };
125 Q_ENUM(VectorLineWidthMode)
126
127 /** \brief class constructor */
128 explicit JKQTPVectorFieldGraph(JKQTBasePlotter* parent=nullptr);
129 /** \brief class constructor */
131
132 /** \copydoc JKQTPXYAndVectorGraph::draw() */
133 virtual void draw(JKQTPEnhancedPainter& painter) override;
134 /** \copydoc JKQTPXYAndVectorGraph::drawKeyMarker() */
135 virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
136 /** \copydoc JKQTPXYAndVectorGraph::getKeyLabelColor() */
137 virtual QColor getKeyLabelColor() const override;
138
139 /** \copydoc m_vectorLengthMode */
140 VectorLengthMode getVectorLengthMode() const;
141 /** \copydoc m_vectorLengthMode */
142 void setVectorLengthMode(VectorLengthMode newMode);
143
144 /** \copydoc m_autoscaleLengthFactor */
145 double getAutoscaleLengthFactor() const;
146 /** \copydoc m_autoscaleLengthFactor */
147 void setAutoscaleLengthFactor(double newAutoscaleLengthFactor);
148
149 /** \copydoc m_lengthScaleFactor */
150 double getLengthScaleFactor() const;
151 /** \copydoc m_lengthScaleFactor */
152 void setLengthScaleFactor(double newLengthScaleFactor);
153
154
155 /** \copydoc m_anchorPoint */
156 VectorAnchorPoint getAnchorPoint() const;
157 /** \copydoc m_anchorPoint */
158 void setAnchorPoint(VectorAnchorPoint newAnchorPoint);
159
160
161 /** \copydoc m_vectorLineWidthMode */
162 void setVectorLineWidthMode(VectorLineWidthMode m);
163 /** \copydoc m_vectorLineWidthMode */
164 VectorLineWidthMode getVectorLineWidthMode() const;
165 /** \copydoc m_minLineWidth */
166 void setMinLineWidth(double lw);
167 /** \copydoc m_minLineWidth */
168 double getMinLineWIdth() const;
169
170 Q_PROPERTY(VectorLengthMode vectorLengthMode READ getVectorLengthMode WRITE setVectorLengthMode )
171 Q_PROPERTY(bool autoscaleLengthFactor READ getAutoscaleLengthFactor WRITE setAutoscaleLengthFactor )
172 Q_PROPERTY(double lengthScaleFactor READ getLengthScaleFactor WRITE setLengthScaleFactor )
173 Q_PROPERTY(VectorAnchorPoint anchorPoint READ getAnchorPoint WRITE setAnchorPoint )
174 Q_PROPERTY(double minLineWidth READ getMinLineWIdth WRITE setMinLineWidth )
175 Q_PROPERTY(VectorLineWidthMode vectorLineWidthMode READ getVectorLineWidthMode WRITE setVectorLineWidthMode )
176 protected:
177 /** \brief internal color functor, a customization point for derived classes
178 *
179 * Overwrite this in a derived class to be able to color each vector differently */
180 virtual QColor getLocalVectorColor(int i,double x,double y,double dx,double dy) const;
181 /** \brief acess to internally calculated (before draw() actually draws) minimum vector length
182 */
183 inline double getMinVecLen() const { return m_minVecLen; };
184 /** \brief acess to internally calculated (before draw() actually draws) maximum vector length
185 */
186 inline double getMaxVecLen() const { return m_maxVecLen; };
187
188 private:
189 /** \brief indicates how the length of the drawn vectors are determined from the data
190 *
191 * Several modes are possible:
192 * - If \c == LengthFromData the vector is drawn from \c (x,y) to \c (x+dx,y+dy)*m_lengthScaleFactor.
193 * \image html JKQTPVectorFieldGraphAutoscaleLength.png
194 * - If \c == AutoscaleLength the vector is drawn to \c (x+dx,y+dy)*autoscale*m_autoscaleLengthFactor .
195 * The autoscaled length is calculated by a simple algorithm that uses the 90% quantile of vector length in the data \c q90VectorLength :
196 * \c autoscale=plotwidth/VectorPerWidth/q90VectorLength .
197 * \image html JKQTPVectorFieldGraphLengthFromData.png
198 * - If \c == IgnoreLength all vectors are drawn with the same length, which is determined from \c autoscale*m_autoscaleLengthFactor
199 * where \c autoscale is defined as above.
200 * \image html JKQTPVectorFieldGraphIgnoreLength.png
201 * .
202 *
203 * \see VectorLengthMode, setVectorLengthMode(), getVectorLengthMode(), m_lengthScaleFactor, m_autoscaleLengthFactor
204 */
206 /** \brief a scaling factor that can be used to modify the result of the autoscaling algorithm (m_vectorLengthMode \c ==AutoscaleLength)
207 *
208 * The vector length is further scaled by this value.
209 * \see m_vectorLengthMode, setAutoscaleFactor(), getAutoscaleFactor()
210 */
212 /** \brief if m_vectorLengthMode \c ==false, this is the scale-factor used to calculate the vector length
213 *
214 * \see setLengthScaleFactor(), getLengthScaleFactor(), m_vectorLengthMode
215 */
217 /** \brief defines where the vector is anchored
218 *
219 * \see VectorAnchorPoint, setAnchorPoint(), getAnchorPoint()
220 */
222 /** \brief determines how the line width of the vectors is derived.
223 *
224 * \note the available options are described with VectorLineWidthMode
225 *
226 * \see setVectorLineWidthMode(), getVectorLineWidthMode(), VectorLineWidthMode, m_minLineWidth
227 */
229 /** \brief minimum line-width in pt, used for some modes of m_vectorLineWidthMode
230 *
231 * \see setMinLineWidth(), getMinLineWidth(), m_vectorLineWidthMode
232 */
234
235 /** \brief internally calculated (before draw() actually draws) minimum vector length
236 * \internal
237 */
239 /** \brief internally calculated (before draw() actually draws) maximum vector length
240 * \internal
241 */
243
244};
245
246
247
248/*! \brief This graph plots a vector field, i.e. a set of vectors (dx,dy) or (angle,length) at positions (x,y).
249 This class is an extension of JKQTPVectorFieldGraph and additionally supports setting the line-color
250 from an additional data column.
251 \ingroup jkqtplotter_vectorfieldgraphs
252
253 \note This type of plot is sometimes also refered to as <b>quiver plot</b> (e.g. in Matlab or matplotlib)
254
255 \image html JKQTPParametrizedVectorFieldGraph.png
256
257 To achieve this, use code like this:
258 \code
259 // 1. setup a plotter window and get a pointer to the internal datastore (for convenience)
260 JKQTPlotter plot;
261 JKQTPDatastore* ds=plot.getDatastore();
262
263 // 2. make up some arbitrary data to be used for plotting
264 // this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y)*sqrt(x/3.0) and dy=sin(x)*sqrt(x/3.0)
265 const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
266 const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
267 const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
268
269 // 3. create JKQTPVectorFieldGraph to display the data:
270 JKQTPVectorFieldGraph* graph1=new JKQTPVectorFieldGraph(&plot);
271 graph1->setXYColumns(columnXY);
272 graph1->setDxColumn(columnDX);
273 graph1->setDyColumn(columnDY);
274 graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));
275
276 // 4. add the graphs to the plot, so it is actually displayed
277 plot.addGraph(graph1);
278 \endcode
279
280 Use setVectorColorMode() if you don't want to use a custom column, but just use the vector's magnitude/length or
281 rotation angle as parameter for the color.
282
283 \see \ref JKQTPParametrizedVectorFieldGraphExample , JKQTPVectorFieldGraph , JKQTPColorPaletteStyleAndToolsMixin
284
285 */
287 Q_OBJECT
288public:
289 /** \brief determines how the color of the vector is determined */
291 DefaultColor, //!< \brief no color-coding, just use getLineColor() \image html JKQTPParametrizedVectorFieldGraphDefaultColor.png
292 ColorFromMagnitude, //!< \brief color-coding by vector magnitude/length \image html JKQTPParametrizedVectorFieldGraphColorFromMagnitude.png
293 ColorFromAngle, //!< \brief color-coding by vector angle \image html JKQTPParametrizedVectorFieldGraphColorFromAngle.png
294 ColorFromCustomColumn //!< \brief color-coding from getColorColumn() column \image html JKQTPParametrizedVectorFieldGraph.png
295 };
296 Q_ENUM(VectorColorMode)
297
298 /** \brief class constructor */
300 /** \brief class constructor */
302
303 /** \copydoc JKQTPVectorFieldGraph::drawKeyMarker() */
304 virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
305 /** \copydoc JKQTPVectorFieldGraph::draw() */
306 virtual void draw(JKQTPEnhancedPainter& painter) override;
307
308 /** \copydoc JKQTPGraph::setParent() */
309 virtual void setParent(JKQTBasePlotter* parent) override;
310 /** \copydoc JKQTPGraph::getOutsideSize() */
311 virtual void getOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace) override;
312 /** \copydoc JKQTPGraph::drawOutside() */
313 virtual void drawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace) override;
314 /** \brief determine min/max data value of the image */
315 virtual void cbGetDataMinMax(double& imin, double& imax) override;
316 /** \copydoc JKQTPGraph::usesColumn() */
317 virtual bool usesColumn(int c) const override;
318
319
320 /** \copydoc m_colorColumn */
321 void setColorColumn(int __value);
322 /** \copydoc m_colorColumn */
323 int getColorColumn() const;
324 /** \copydoc m_colorColumn */
325 void setColorColumn (size_t __value);
326 /** \copydoc m_colorColumnContainsRGB */
327 void setColorColumnContainsRGB(bool __value);
328 /** \copydoc m_colorColumnContainsRGB */
329 bool getColorColumnContainsRGB() const;
330 /** \copydoc m_vectorColorMode */
331 void setVectorColorMode(VectorColorMode __value);
332 /** \copydoc m_vectorColorMode */
333 VectorColorMode getVectorColorMode() const;
334
335protected:
336 /** \copdydoc JKQTPVectorFieldGraph::getLocalVectorColor() */
337 virtual QColor getLocalVectorColor(int i,double x,double y,double dx,double dy) const override;
338private:
339 /** \brief this column contains the symbol color
340 *
341 * \see setColorColumn(), getColorColumn()
342 */
343 int m_colorColumn;
344 /** \brief if this is true, the value in the colorColumn is converted to an integer, representing a color in ARGB format (as in QRgb)
345 *
346 * \see setColorColumnContainsRGB(), getColorColumnContainsRGB()
347 */
348 bool m_colorColumnContainsRGB;
349 /** \brief internally used to store the range of the color column
350 * \internal
351 */
352 double m_intColMin;
353 /** \brief internally used to store the range of the color column
354 * \internal
355 */
356 double m_intColMax;
357 /** \brief indicates how color is determined from data (either from the vector or from m_colorColumn) */
358 VectorColorMode m_vectorColorMode;
359
360};
361
362#endif // jkqtpvectorfield_H
base class for 2D plotter classes (used by the plotter widget JKQTPlotter)
Definition jkqtpbaseplotter.h:394
if a class is derived from this class, it may use color bars
Definition jkqtpimagetools.h:44
this virtual class is the base for any type of coordinate axis, to be drawn by JKQTBasePlotter.
Definition jkqtpcoordinateaxes.h:181
This class manages data columns (with entries of type double ), used by JKQTPlotter/JKQTBasePlotter t...
Definition jkqtpdatastorage.h:282
this class extends the QPainter
Definition jkqtpenhancedpainter.h:33
This Mix-In class provides setter/getter methods, storage and other facilities for the graph line sty...
Definition jkqtpgraphsbasestylingmixins.h:303
This graph plots a vector field, i.e. a set of vectors (dx,dy) or (angle,length) at positions (x,...
Definition jkqtpvectorfield.h:286
VectorColorMode
determines how the color of the vector is determined
Definition jkqtpvectorfield.h:290
@ ColorFromAngle
color-coding by vector angle
Definition jkqtpvectorfield.h:293
@ DefaultColor
no color-coding, just use getLineColor()
Definition jkqtpvectorfield.h:291
@ ColorFromMagnitude
color-coding by vector magnitude/length
Definition jkqtpvectorfield.h:292
This graph plots a vector field, i.e. a set of vectors (dx,dy) or (angle,length) at positions (x,...
Definition jkqtpvectorfield.h:96
VectorLineWidthMode
describes how the line width scales with the vector properties (or not)
Definition jkqtpvectorfield.h:119
@ AutoscaleLineWidthFromLength
line width is determined from the vector length. The maximum line width is given by JKQTPGraphLineSty...
Definition jkqtpvectorfield.h:121
@ DefaultVectorLineWidth
line width is equal to JKQTPGraphLineStyleMixin::getLineWidth() for all vectors
Definition jkqtpvectorfield.h:120
VectorLengthMode m_vectorLengthMode
indicates how the length of the drawn vectors are determined from the data
Definition jkqtpvectorfield.h:205
double m_minLineWidth
minimum line-width in pt, used for some modes of m_vectorLineWidthMode
Definition jkqtpvectorfield.h:233
VectorAnchorPoint m_anchorPoint
defines where the vector is anchored
Definition jkqtpvectorfield.h:221
VectorAnchorPoint
indicates the position of the point (x,y) relative to the vector
Definition jkqtpvectorfield.h:100
@ AnchorMid
the vector's mid is at (x,y)
Definition jkqtpvectorfield.h:102
@ AnchorBottom
this is the default: the vector starts at (x,y)
Definition jkqtpvectorfield.h:101
double m_minVecLen
internally calculated (before draw() actually draws) minimum vector length
Definition jkqtpvectorfield.h:238
VectorLengthMode
indicates how the drawn vector's length is calculated from the data
Definition jkqtpvectorfield.h:111
@ AutoscaleLength
this is the default: vector lengths are autoscaled, so they don't overlap (in first approximation)
Definition jkqtpvectorfield.h:112
@ LengthFromData
the vector's length is determined by the data directly
Definition jkqtpvectorfield.h:113
VectorLineWidthMode m_vectorLineWidthMode
determines how the line width of the vectors is derived.
Definition jkqtpvectorfield.h:228
double getMaxVecLen() const
acess to internally calculated (before draw() actually draws) maximum vector length
Definition jkqtpvectorfield.h:186
double m_lengthScaleFactor
if m_vectorLengthMode ==false, this is the scale-factor used to calculate the vector length
Definition jkqtpvectorfield.h:216
double m_autoscaleLengthFactor
a scaling factor that can be used to modify the result of the autoscaling algorithm (m_vectorLengthMo...
Definition jkqtpvectorfield.h:211
double m_maxVecLen
internally calculated (before draw() actually draws) maximum vector length
Definition jkqtpvectorfield.h:242
This virtual JKQTPGraph descendent extends JKQTPXYGraph with two additional columns that encode for a...
Definition jkqtpgraphsbase.h:968
plotter widget for scientific plots (uses JKQTBasePlotter to do the actual drawing)
Definition jkqtplotter.h:364
#define JKQTPLOTTER_LIB_EXPORT
Definition jkqtplotter_imexport.h:89