replace JKQTPVectorFieldGraph::setAutoscaleLengthFactor() by an enum-property JKQTPVectorFieldGraph::setVectorLengthMode() and added a mode that ignores the length completely, the vectorfield example was also modified to better show this new property
@ -274,7 +274,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
||||
boxplot/JKQTPBoxplotVerticalGraph,JKQTPBoxplotHorizontalGraph/--iteratefunctorsteps--iteratefunctorsteps_suppressinitial--smallscreenshotplot
|
||||
second_axis/JKQTBasePlotter_addSecondaryYAxis,JKQTBasePlotter_addSecondaryXAxis
|
||||
graphlabels/JKQTPGLabelAwayFromXAxis,JKQTPGLabelAwayFromYAxis,JKQTPGLabelTowardsXAxis,JKQTPGLabelTowardsYAxis,JKQTPGLabelAboveData,JKQTPGLabelRightHandSide,JKQTPGLabelBelowData,JKQTPGLabelLeftHandSide,JKQTPGLSimpleBox,JKQTPGLSimpleBoxVertical,JKQTPGLSimpleBoxAndLine,JKQTPGLSimpleBoxAndLineVertical,JKQTPGLSimpleBoxAndLineONLYLABELS,JKQTPGLSimpleBoxAndLineONLYLABELSVertical/--iteratefunctorsteps--smallscreenshotplot
|
||||
vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip/--iteratefunctorsteps
|
||||
vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip,JKQTPVectorFieldGraphAutoscaleLength,JKQTPVectorFieldGraphLengthFromData,JKQTPVectorFieldGraphIgnoreLength/--iteratefunctorsteps
|
||||
)
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 52 KiB |
BIN
doc/images/JKQTPVectorFieldGraphAutoscaleLength.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
doc/images/JKQTPVectorFieldGraphIgnoreLength.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
doc/images/JKQTPVectorFieldGraphLengthFromData.png
Normal file
After Width: | Height: | Size: 70 KiB |
@ -11,17 +11,17 @@ Here is a short summary of the important parts of the code:
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. make up some arbitrary data to be used for plotting
|
||||
// this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y) and dy=sin(x)
|
||||
// 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)
|
||||
const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x); });
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
|
||||
|
||||
// 3. create JKQTPVectorFieldGraph to display the data:
|
||||
JKQTPVectorFieldGraph* graph1=new JKQTPVectorFieldGraph(&plot);
|
||||
graph1->setXYColumns(columnXY);
|
||||
graph1->setDxColumn(columnDX);
|
||||
graph1->setDyColumn(columnDY);
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y), \\cos(x)\\bigr]^\\mathrm{T}$"));
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));
|
||||
|
||||
// 4. add the graphs to the plot, so it is actually displayed
|
||||
plot.addGraph(graph1);
|
||||
@ -33,3 +33,23 @@ The result looks like this:
|
||||
![vectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/vectorfield.png)
|
||||
|
||||
|
||||
By default, the length of the drawn vector is determined from the actual length in the data via an autoscaling algorithm that is supposed to prevent the vectors from overlapping.
|
||||
But you can modify this behaviour by adding a line
|
||||
|
||||
```.cpp
|
||||
graph1->setVectorLengthMode(JKQTPVectorFieldGraph::LengthFromData);
|
||||
```
|
||||
|
||||
which will use the given lengths directly (only scaled by an optional factor defined by JKQTPVectorFieldGraph::setLengthScaleFactor() ). The result then looks like this:
|
||||
|
||||
![vectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPVectorFieldGraphLengthFromData.png)
|
||||
|
||||
Alternatively you can also set
|
||||
|
||||
```.cpp
|
||||
graph1->setVectorLengthMode(JKQTPVectorFieldGraph::IgnoreLength);
|
||||
```
|
||||
|
||||
which will draw all vectors with the same length. You can scale this length by setting JKQTPVectorFieldGraph::setAutoscaleLengthFactor() ). The result then looks like this:
|
||||
|
||||
![vectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPVectorFieldGraphIgnoreLength.png)
|
||||
|
@ -32,10 +32,10 @@ int main(int argc, char* argv[])
|
||||
|
||||
|
||||
// 2. make up some arbitrary data to be used for plotting
|
||||
// this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y) and dy=sin(x)
|
||||
// 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)
|
||||
const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x); });
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
|
||||
|
||||
|
||||
// 3. create JKQTPVectorFieldGraph to display the data:
|
||||
@ -43,7 +43,7 @@ int main(int argc, char* argv[])
|
||||
graph1->setXYColumns(columnXY);
|
||||
graph1->setDxColumn(columnDX);
|
||||
graph1->setDyColumn(columnDY);
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y), \\cos(x)\\bigr]^\\mathrm{T}$"));
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));
|
||||
|
||||
// 4. add the graphs to the plot, so it is actually displayed
|
||||
plot.addGraph(graph1);
|
||||
@ -78,7 +78,23 @@ int main(int argc, char* argv[])
|
||||
|
||||
app.addExportStepFunctor([&](){
|
||||
graph1->setAnchorPoint(JKQTPVectorFieldGraph::AnchorTip);
|
||||
plot.redrawPlot();
|
||||
plot.redrawPlot();
|
||||
});
|
||||
|
||||
app.addExportStepFunctor([&](){
|
||||
graph1->setAnchorPoint(JKQTPVectorFieldGraph::AnchorBottom);
|
||||
graph1->setVectorLengthMode(JKQTPVectorFieldGraph::AutoscaleLength);
|
||||
plot.redrawPlot();
|
||||
});
|
||||
app.addExportStepFunctor([&](){
|
||||
graph1->setAnchorPoint(JKQTPVectorFieldGraph::AnchorBottom);
|
||||
graph1->setVectorLengthMode(JKQTPVectorFieldGraph::LengthFromData);
|
||||
plot.redrawPlot();
|
||||
});
|
||||
app.addExportStepFunctor([&](){
|
||||
graph1->setAnchorPoint(JKQTPVectorFieldGraph::AnchorBottom);
|
||||
graph1->setVectorLengthMode(JKQTPVectorFieldGraph::IgnoreLength);
|
||||
plot.redrawPlot();
|
||||
});
|
||||
|
||||
return app.exec();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include "jkqtcommon/jkqtpdrawingtools.h"
|
||||
#include "jkqtmath/jkqtpstatisticstools.h"
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
|
||||
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
|
||||
@ -33,9 +34,9 @@
|
||||
|
||||
JKQTPVectorFieldGraph::JKQTPVectorFieldGraph(JKQTBasePlotter *parent):
|
||||
JKQTPXYAndVectorGraph(parent),
|
||||
m_autoscaleLength(true),
|
||||
m_autoscaleLengthFactor(0.9),
|
||||
m_lengthScaleFactor(1),
|
||||
m_vectorLengthMode(AutoscaleLength),
|
||||
m_autoscaleLengthFactor(0.8),
|
||||
m_lengthScaleFactor(1.0),
|
||||
m_anchorPoint(AnchorBottom)
|
||||
{
|
||||
initDecoratedLineStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Default);
|
||||
@ -72,17 +73,21 @@ void JKQTPVectorFieldGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
double scale=1;
|
||||
if (getIndexRange(imin, imax)) {
|
||||
// first determine (auto-scale) factor
|
||||
if (m_autoscaleLength) {
|
||||
if (m_vectorLengthMode==AutoscaleLength || m_vectorLengthMode==IgnoreLength) {
|
||||
double avgVecLength=0;
|
||||
double NDatapoints=0;
|
||||
double xmin=0, xmax=0,ymin=0,ymax=0;
|
||||
QVector<double> lengths;
|
||||
lengths.reserve(imax-imin);
|
||||
for (int iii=imin; iii<imax; iii++) {
|
||||
const int i=qBound(imin, getDataIndex(iii), imax);
|
||||
const double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
|
||||
const double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
||||
const QPointF vecv=getVectorDxDy(i);
|
||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(vecv)) {
|
||||
avgVecLength+=sqrt(jkqtp_sqr(vecv.x())+jkqtp_sqr(vecv.y()));
|
||||
const double l=sqrt(jkqtp_sqr(vecv.x())+jkqtp_sqr(vecv.y()));
|
||||
lengths<<l;
|
||||
avgVecLength+=l;
|
||||
if (NDatapoints==0) {
|
||||
xmin=xmax=xv;
|
||||
ymin=ymax=yv;
|
||||
@ -95,10 +100,12 @@ void JKQTPVectorFieldGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
NDatapoints++;
|
||||
}
|
||||
}
|
||||
avgVecLength/=NDatapoints;
|
||||
//avgVecLength/=NDatapoints;
|
||||
avgVecLength=jkqtpstatQuantile(lengths.begin(), lengths.end(), 0.9);
|
||||
const double plotsize=qMax(fabs(xmax-xmin),fabs(ymax-ymin));
|
||||
const double aproxNPerSide=sqrt(NDatapoints);
|
||||
scale=plotsize/aproxNPerSide/avgVecLength*m_autoscaleLengthFactor;
|
||||
if (m_vectorLengthMode==IgnoreLength) scale=plotsize/aproxNPerSide*m_autoscaleLengthFactor; // we can assume that the elngths of all vectors have been normalized beforehand
|
||||
else scale=plotsize/aproxNPerSide/avgVecLength*m_autoscaleLengthFactor;
|
||||
} else {
|
||||
scale=m_lengthScaleFactor;
|
||||
}
|
||||
@ -110,7 +117,15 @@ void JKQTPVectorFieldGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
const double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
||||
const double x=transformX(xv);
|
||||
const double y=transformY(yv);
|
||||
const QPointF vecv=getVectorDxDy(i);
|
||||
const QPointF vecv=[&]() {
|
||||
QPointF vec=getVectorDxDy(i);
|
||||
if (m_vectorLengthMode==IgnoreLength) {
|
||||
const double veclen=sqrt(jkqtp_sqr(vec.x())+jkqtp_sqr(vec.y()));
|
||||
if (qFuzzyIsNull(veclen)) vec=QPointF(0,0);
|
||||
else vec/=veclen; // normalize vector
|
||||
}
|
||||
return vec;
|
||||
}();
|
||||
const QLineF l=[&]() {
|
||||
switch (m_anchorPoint) {
|
||||
case AnchorBottom: return QLineF(x,y,transformX(xv+scale*vecv.x()),transformY(yv+scale*vecv.y()));
|
||||
@ -119,7 +134,7 @@ void JKQTPVectorFieldGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
}
|
||||
return QLineF(JKQTP_NAN,JKQTP_NAN,JKQTP_NAN,JKQTP_NAN);
|
||||
}();
|
||||
if (JKQTPIsOKFloat(l)) {
|
||||
if (JKQTPIsOKFloat(l) && l.length()>0) {
|
||||
JKQTPPlotDecoratedLine(painter,l, getTailDecoratorStyle(), calcTailDecoratorSize(p.widthF()), getHeadDecoratorStyle(), calcHeadDecoratorSize(p.widthF()));
|
||||
}
|
||||
}
|
||||
@ -144,14 +159,14 @@ QColor JKQTPVectorFieldGraph::getKeyLabelColor() const
|
||||
return getLineColor();
|
||||
}
|
||||
|
||||
bool JKQTPVectorFieldGraph::getAutoscaleLength() const
|
||||
JKQTPVectorFieldGraph::VectorLengthMode JKQTPVectorFieldGraph::getVectorLengthMode() const
|
||||
{
|
||||
return m_autoscaleLength;
|
||||
return m_vectorLengthMode;
|
||||
}
|
||||
|
||||
void JKQTPVectorFieldGraph::setAutoscaleLength(bool newAutoscaleLength)
|
||||
void JKQTPVectorFieldGraph::setVectorLengthMode(VectorLengthMode newMode)
|
||||
{
|
||||
m_autoscaleLength = newAutoscaleLength;
|
||||
m_vectorLengthMode = newMode;
|
||||
}
|
||||
|
||||
double JKQTPVectorFieldGraph::getAutoscaleLengthFactor() const
|
||||
|
@ -43,7 +43,7 @@ class JKQTPDatastore;
|
||||
corresponding to their magnitude.
|
||||
\ingroup jkqtplotter_vectorfieldgraphs
|
||||
|
||||
\note This type of plot is sometimes also refered to as quiver plot (e.g. in Matlab or matplotlib)
|
||||
\note This type of plot is sometimes also refered to as <b>quiver plot</b> (e.g. in Matlab or matplotlib)
|
||||
|
||||
\image html JKQTPVectorFieldGraph.png
|
||||
|
||||
@ -54,35 +54,62 @@ class JKQTPDatastore;
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. make up some arbitrary data to be used for plotting
|
||||
// this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y) and dy=sin(x)
|
||||
// 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)
|
||||
const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x); });
|
||||
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
|
||||
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
|
||||
|
||||
// 3. create JKQTPVectorFieldGraph to display the data:
|
||||
JKQTPVectorFieldGraph* graph1=new JKQTPVectorFieldGraph(&plot);
|
||||
graph1->setXYColumns(columnXY);
|
||||
graph1->setDxColumn(columnDX);
|
||||
graph1->setDyColumn(columnDY);
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y), \\cos(x)\\bigr]^\\mathrm{T}$"));
|
||||
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));
|
||||
|
||||
// 4. add the graphs to the plot, so it is actually displayed
|
||||
plot.addGraph(graph1);
|
||||
\endcode
|
||||
|
||||
You have several options to influence the way the vectors are drawn:
|
||||
1. You can change the tip shape (and actually also the tail) of the vector by using the methods from
|
||||
JKQTPGraphDecoratedLineStyleMixin, e.g. use JKQTPGraphDecoratedLineStyleMixin::setHeadDecoratorStyle()
|
||||
to set another shape for the vector's tip, or modify JKQTPGraphDecoratedLineStyleMixin::setHeadDecoratorSizeFactor()
|
||||
to modify the size of the vector's head. the vector line width, color etz. can be modified by the
|
||||
methods from JKQTPGraphLineStyleMixin, like JKQTPGraphLineStyleMixin::setLineColor() or
|
||||
JKQTPGraphLineStyleMixin::setLineWidth().
|
||||
2. By default the length of the drawn vectors corresponds to the actual length of the vector data,
|
||||
but is modified by an autoscaling algorithm that should prevent them from overlapping.
|
||||
This behaviour can be changed by setVectorLengthMode() with the different options described in
|
||||
VectorLengthMode.
|
||||
3. By default, vector start at \c (x,y). But you can also make them be centered around or
|
||||
point to \c (x,y) . This can be set by setAnchorPoint().
|
||||
.
|
||||
|
||||
\see \ref JKQTPlotterVectorFieldExample , JKQTPGraphDecoratedLineStyleMixin , JKQTPXYAndVectorGraph
|
||||
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPVectorFieldGraph: public JKQTPXYAndVectorGraph, public JKQTPGraphDecoratedLineStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief indicates the position of the point \c (x,y) relative to the vector */
|
||||
enum VectorAnchorPoint {
|
||||
AnchorBottom, //!< \brief this is the default: the vector starts at (x,y) \image html JKQTPVectorFieldGraphAnchorBottom.png
|
||||
AnchorMid, //!< \brief the vector's mid is at (x,y) \image html JKQTPVectorFieldGraphAnchorMid.png
|
||||
AnchorTip //!< \brief the vector ends at (x,y) \image html JKQTPVectorFieldGraphAnchorTip.png
|
||||
AnchorBottom, //!< \brief this is the default: the vector starts at \c (x,y) \image html JKQTPVectorFieldGraphAnchorBottom.png
|
||||
AnchorMid, //!< \brief the vector's mid is at \c (x,y) \image html JKQTPVectorFieldGraphAnchorMid.png
|
||||
AnchorTip //!< \brief the vector ends at \c (x,y) \image html JKQTPVectorFieldGraphAnchorTip.png
|
||||
};
|
||||
Q_ENUM(VectorAnchorPoint)
|
||||
|
||||
/** \brief indicates how the drawn vector's length is calculated from the data
|
||||
*
|
||||
* \see documentation of m_vectorLengthMode for details
|
||||
*/
|
||||
enum VectorLengthMode {
|
||||
AutoscaleLength, //!< \brief this is the default: vector lengths are autoscaled, so they don't overlap (in first approximation) \image html JKQTPVectorFieldGraphAnchorBottom.png
|
||||
LengthFromData, //!< \brief the vector's length is determined by the data directly \image html JKQTPVectorFieldGraphAnchorMid.png
|
||||
IgnoreLength //!< \brief all vectors have the same length \image html JKQTPVectorFieldGraphAnchorTip.png
|
||||
};
|
||||
Q_ENUM(VectorLengthMode)
|
||||
|
||||
/** \brief class constructor */
|
||||
explicit JKQTPVectorFieldGraph(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
@ -95,10 +122,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVectorFieldGraph: public JKQTPXYAndVectorGraph
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
/** \copydoc m_autoscaleLength */
|
||||
bool getAutoscaleLength() const;
|
||||
/** \copydoc m_autoscaleLength */
|
||||
void setAutoscaleLength(bool newAutoscaleLength);
|
||||
/** \copydoc m_vectorLengthMode */
|
||||
VectorLengthMode getVectorLengthMode() const;
|
||||
/** \copydoc m_vectorLengthMode */
|
||||
void setVectorLengthMode(VectorLengthMode newMode);
|
||||
|
||||
/** \copydoc m_autoscaleLengthFactor */
|
||||
double getAutoscaleLengthFactor() const;
|
||||
@ -116,31 +143,38 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVectorFieldGraph: public JKQTPXYAndVectorGraph
|
||||
/** \copydoc m_anchorPoint */
|
||||
void setAnchorPoint(VectorAnchorPoint newAnchorPoint);
|
||||
|
||||
Q_PROPERTY(bool autoscaleLength READ getAutoscaleLength WRITE setAutoscaleLength )
|
||||
Q_PROPERTY(VectorLengthMode vectorLengthMode READ getVectorLengthMode WRITE setVectorLengthMode )
|
||||
Q_PROPERTY(bool autoscaleLengthFactor READ getAutoscaleLengthFactor WRITE setAutoscaleLengthFactor )
|
||||
Q_PROPERTY(double lengthScaleFactor READ getLengthScaleFactor WRITE setLengthScaleFactor )
|
||||
Q_PROPERTY(VectorAnchorPoint anchorPoint READ getAnchorPoint WRITE setAnchorPoint )
|
||||
protected:
|
||||
private:
|
||||
/** \brief enables or disables the autoscaling of vector lengths
|
||||
/** \brief indicates how the length of the drawn vectors are determined from the data
|
||||
*
|
||||
* If disabled (\c false ) the vector is drawn from \c (x,y) to \c (x+dx,y+dy)*m_lengthScaleFactor ,
|
||||
* otherweise to \c (x+dx,y+dy)*autoscale*m_autoscaleLengthFactor .
|
||||
* The autoscaled length is calculated by a siple algorithm that uses the average vector length in the data:
|
||||
* \c autoscale=plotwidth/VectorPerWidth/avgVectorLength .
|
||||
* Several modes are possible:
|
||||
* - If \c == LengthFromData the vector is drawn from \c (x,y) to \c (x+dx,y+dy)*m_lengthScaleFactor.
|
||||
* \image html JKQTPVectorFieldGraphAutoscaleLength.png
|
||||
* - If \c == AutoscaleLength the vector is drawn to \c (x+dx,y+dy)*autoscale*m_autoscaleLengthFactor .
|
||||
* The autoscaled length is calculated by a simple algorithm that uses the 90% quantile of vector length in the data \c q90VectorLength :
|
||||
* \c autoscale=plotwidth/VectorPerWidth/q90VectorLength .
|
||||
* \image html JKQTPVectorFieldGraphLengthFromData.png
|
||||
* - If \c == IgnoreLength all vectors are drawn with the same length, which is determined from \c autoscale*m_autoscaleLengthFactor
|
||||
* where \c autoscale is defined as above.
|
||||
* \image html JKQTPVectorFieldGraphIgnoreLength.png
|
||||
* .
|
||||
*
|
||||
* \see m_autoscaleFactor, m_autoscaleLengthFactor, setAutoscaleLength(), getAutoscaleLength()
|
||||
* \see VectorLengthMode, setVectorLengthMode(), getVectorLengthMode(), m_autoscaleFactor, m_autoscaleLengthFactor
|
||||
*/
|
||||
bool m_autoscaleLength;
|
||||
/** \brief a scaling factor that can be used to modify the result of the autoscaling algorithm (m_autoscaleLength \c ==true)
|
||||
VectorLengthMode m_vectorLengthMode;
|
||||
/** \brief a scaling factor that can be used to modify the result of the autoscaling algorithm (m_vectorLengthMode \c ==AutoscaleLength)
|
||||
*
|
||||
* The vector length is further scaled by this value.
|
||||
* \see m_autoscaleLength, setAutoscaleFactor(), getAutoscaleFactor()
|
||||
* \see m_vectorLengthMode, setAutoscaleFactor(), getAutoscaleFactor()
|
||||
*/
|
||||
double m_autoscaleLengthFactor;
|
||||
/** \brief if m_autoscaleLength \c ==false, this is the scale-factor used to calculate the vector length
|
||||
/** \brief if m_vectorLengthMode \c ==false, this is the scale-factor used to calculate the vector length
|
||||
*
|
||||
* \see setLengthScaleFactor(), getLengthScaleFactor(), m_autoscaleLength
|
||||
* \see setLengthScaleFactor(), getLengthScaleFactor(), m_vectorLengthMode
|
||||
*/
|
||||
double m_lengthScaleFactor;
|
||||
/** \brief defines where the vector is anchored
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 15 KiB |