mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-25 01:51:49 +08:00
- cleanup of class-hierarchy of evaluated functions
- added slots for several properties of evaluated functions - updated examples
This commit is contained in:
parent
414e12920e
commit
f77bc97ca5
@ -23,6 +23,7 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
|
||||
<li>removed the usage of some deprecated functions and objects (e.g. QMatrix)</li>
|
||||
<li>improved: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)</li>
|
||||
<li>improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)</li>
|
||||
<li>improved: reworked class hirarchy of parsed function plots and declared several setters as slots.</li>
|
||||
<li>new: added geometric plot objects JKQTPGeoArrow to draw arrows (aka lines with added line-end decorators, also extended JKQTPGeoLine, JKQTPGeoInfiniteLine, JKQTPGeoPolyLines to draw line-end decorator (aka arrows)</li>
|
||||
<li>new: all geometric objects can either be drawn as graphic element (i.e. lines are straight line, even on non-linear axes), or as mathematical curve (i.e. on non-linear axes, lines become the appropriate curve representing the linear function, connecting the given start/end-points). The only exceptions are ellipses (and the derived arcs,pies,chords), which are always drawn as mathematical curves</li>
|
||||
<li>new: a new graph class JKQTPXYFunctionLineGraph draws parametric 2D curves ( \f$ [x,y] = f(t) \f$ ), see \ref JKQTPlotterEvalCurves for an example</li>
|
||||
|
@ -1,6 +1,8 @@
|
||||
# Example (JKQTPlotter): Plotting Parametric Mathematical Curves as Line Graphs {#JKQTPlotterEvalCurves}
|
||||
## Basics
|
||||
This project (see `./examples/evalcurve/`) demonstrates how to plot mathematical functions as line graphs. The functions may be defined as static C functions, C++ functors or c++ inline functions.
|
||||
This project (see `./examples/evalcurve/`) demonstrates how to plot mathematical functions as line graphs. The functions may be defined as static C functions, C++ functors or c++ inline functions. The functions may simply depend on the parameter `t`, or on `t` and a vector of parameters.
|
||||
|
||||
The class uses an adaptive algorithm, which determines by the local slope, at how many points (or how close points) the functor has to be evaluated.
|
||||
|
||||
[TOC]
|
||||
|
||||
@ -9,24 +11,55 @@ The example shows how to plot a simple C++ inline function:
|
||||
|
||||
```.cpp
|
||||
JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot);
|
||||
func1->setPlotFunctionFunctor([](double t) -> QPointF {
|
||||
const double a=5;
|
||||
const double b=4;
|
||||
const double delta=JKQTPSTATISTICS_PI/4.0;
|
||||
return QPointF(sin(a*t+delta), sin(b*t));
|
||||
func1->setPlotFunctionFunctor([](double t) ->QPointF {
|
||||
return QPointF(
|
||||
sin(t)*(exp(cos(t))-2.0*cos(4.0*t)-jkqtp_pow5(sin(t/12.0))),
|
||||
cos(t)*(exp(cos(t))-2.0*cos(4.0*t)-jkqtp_pow5(sin(t/12.0)))
|
||||
);
|
||||
});
|
||||
func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$");
|
||||
func1->setTRange(0, 12.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function: \"Butterfly Curve\"");
|
||||
plot->addGraph(func1);
|
||||
```
|
||||
|
||||
Note that here a functor is defined, which calculates the points on a [Lissajous Curve](https://en.wikipedia.org/wiki/Lissajous_curve), i.e. a function mapping a parameter `t` to a two-dimensional point `QPointF` with `x=sin(a*t+delta)`and `y=sin(b*t)`. This function is evaluated on a range of values for `t`, set by
|
||||
Note that here a functor is defined, which calculates the points on a [Butterfly Curve](https://en.wikipedia.org/wiki/Butterfly_curve_(transcendental)), i.e. a function mapping a parameter `t` to a two-dimensional point `QPointF` with complex functions for x and y. This function is evaluated on a range of values for `t`, set by
|
||||
|
||||
```.cpp
|
||||
func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
```
|
||||
|
||||
The class uses an adaptive algorithm, which determines by the local slope, at how many points (or how close points) the functor has to be evaluated.
|
||||
# Simple C++ inline function with Parameters
|
||||
`JKQTPXYFunctionLineGraph` allows to use more complex functors alternatively: These depend on the variable `t`and a vector of parameters. Here is an example:
|
||||
|
||||
```.cpp
|
||||
func2->setPlotFunctionFunctor([](double t, const QVector<double>& params) ->QPointF {
|
||||
return QPointF(
|
||||
3.0*sin(params[0]*t+params[2])+8.0,
|
||||
3.0*sin(params[1]*t)
|
||||
);
|
||||
});
|
||||
// now we define the 3 parameters of the function
|
||||
func2->setParamsV(5, 4, JKQTPSTATISTICS_PI/4.0);
|
||||
// and define the range over which to evaluate
|
||||
func2->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$");
|
||||
plot->addGraph(func1);
|
||||
```
|
||||
|
||||
In the functor we can use the entries in the vector `param` as function parameters. The values in this vector are defined by
|
||||
|
||||
```.cpp
|
||||
// now we define the 3 parameters of the function
|
||||
func2->setParamsV(5, 4, JKQTPSTATISTICS_PI/4.0);
|
||||
```
|
||||
|
||||
Alternatively they can also be taken from a column in the internal datastore. Then you have to call:
|
||||
|
||||
```.cpp
|
||||
func2->setParameterColumn(ColumnID);
|
||||
```
|
||||
|
||||
instead, where `ColumnID` is the ID of the column with the parameter values.
|
||||
|
||||
# Screenshot
|
||||
|
||||
@ -36,7 +69,6 @@ This code snippets above result in a plot like this:
|
||||
|
||||
# Notes
|
||||
|
||||
Just as shown in [examples/functionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) for JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph, different types of functions can be used to plot. Either simple C++ inline functions, that take a `double t` and return a `QPointF`, or functions that additionally take a parameter vector `void* params`. In that case, the parameters may be provided from different sources, as described in [examples/functionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) .
|
||||
|
||||
This example describes how to draw 2D parametric curves. For (simpler) 1D-functions f(x) or f(y), see [examples/functionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) .
|
||||
|
||||
|
||||
|
@ -27,14 +27,34 @@ int main(int argc, char* argv[])
|
||||
// the function is defined as C++ inline function
|
||||
JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot);
|
||||
func1->setPlotFunctionFunctor([](double t) ->QPointF {
|
||||
const double a=5;
|
||||
const double b=4;
|
||||
const double delta=JKQTPSTATISTICS_PI/4.0;
|
||||
return QPointF(sin(a*t+delta), sin(b*t));
|
||||
return QPointF(
|
||||
sin(t)*(exp(cos(t))-2.0*cos(4.0*t)-jkqtp_pow5(sin(t/12.0))),
|
||||
cos(t)*(exp(cos(t))-2.0*cos(4.0*t)-jkqtp_pow5(sin(t/12.0)))
|
||||
);
|
||||
});
|
||||
func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$");
|
||||
func1->setTRange(0, 12.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function: \"Butterfly Curve\"");
|
||||
plot->addGraph(func1);
|
||||
|
||||
|
||||
|
||||
// 3. a second JKQTPXYFunctionLineGraph object shows how to use functions that
|
||||
// also take a parameter vector, in addition to the dependent variable t
|
||||
JKQTPXYFunctionLineGraph* func2=new JKQTPXYFunctionLineGraph(plot);
|
||||
func2->setPlotFunctionFunctor([](double t, const QVector<double>& params) ->QPointF {
|
||||
return QPointF(
|
||||
3.0*sin(params[0]*t+params[2])+8.0,
|
||||
3.0*sin(params[1]*t)
|
||||
);
|
||||
});
|
||||
// now we define the 3 parameters of the function
|
||||
func2->setParamsV(5, 4, JKQTPSTATISTICS_PI/4.0);
|
||||
// and define the range over which to evaluate
|
||||
func2->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
func2->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$");
|
||||
plot->addGraph(func2);
|
||||
|
||||
|
||||
// 8. set some axis properties (we use LaTeX for nice equation rendering)
|
||||
plot->getXAxis()->setAxisLabel(QObject::tr("x-axis"));
|
||||
plot->getYAxis()->setAxisLabel(QObject::tr("y-axis"));
|
||||
@ -42,7 +62,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
|
||||
// 4. scale the plot so the graph is contained
|
||||
plot->setXY(-1.1,1.1,-1.1,1.1);
|
||||
plot->setXY(-3,12,-3.2,3.2);
|
||||
|
||||
// show window and make it a decent size
|
||||
mainWin.show();
|
||||
|
@ -108,3 +108,6 @@ All examples above use the graph class `JKQTPXFunctionLineGraph`, which plots a
|
||||
![functionplot_fy](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/functionplot_fy.png)
|
||||
|
||||
|
||||
This example describes how to draw 1D functions. For an example of how to draw 2D parametric curves `[x,y]=f(t)`, see [examples/evalcurve](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/evalcurve) .
|
||||
|
||||
|
||||
|
@ -290,12 +290,22 @@ inline T jkqtp_sqr(const T& v) {
|
||||
\ingroup jkqtptools_math_basic
|
||||
|
||||
*/
|
||||
template <class T>
|
||||
inline T jkqtp_pow4(T x) {
|
||||
template <class T>
|
||||
inline T jkqtp_pow4(T x) {
|
||||
const T xx=x*x;
|
||||
return xx*xx;
|
||||
}
|
||||
|
||||
/*! \brief 5-th power of a number
|
||||
\ingroup jkqtptools_math_basic
|
||||
|
||||
*/
|
||||
template <class T>
|
||||
inline T jkqtp_pow5(T x) {
|
||||
const T xx=x*x;
|
||||
return xx*xx*x;
|
||||
}
|
||||
|
||||
/*! \brief cube of a number
|
||||
\ingroup jkqtptools_math_basic
|
||||
|
||||
|
@ -31,29 +31,22 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTBasePlotter* parent):
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase(parent)
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(JKQTBasePlotter* parent):
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphBase(parent),
|
||||
drawLine(true),
|
||||
fillCurve(false),
|
||||
drawErrorPolygons(false),
|
||||
drawErrorLines(false)
|
||||
{
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
drawLine=true;
|
||||
fillCurve=false;
|
||||
|
||||
initLineStyle(parent, parentPlotStyle);
|
||||
initFillStyle(parent, parentPlotStyle);
|
||||
|
||||
drawErrorPolygons=false;
|
||||
drawErrorLines=false;
|
||||
errorParams=nullptr;
|
||||
errorColor=getLineColor().lighter();
|
||||
errorFillColor=getLineColor().lighter();
|
||||
errorStyle=Qt::SolidLine;
|
||||
errorLineWidth=1;
|
||||
errorFillStyle=Qt::SolidPattern;
|
||||
|
||||
errorParameterColumn=-1;
|
||||
|
||||
|
||||
if (parent && parentPlotStyle>=0) { // get style settings from parent object
|
||||
//std::cout<<"got style settings from parent: "<<parentPlotStyle<<std::endl;
|
||||
@ -66,120 +59,29 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTBasePlotter* parent):
|
||||
errorFillColor.setAlphaF(0.5);
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPlotter* parent):
|
||||
JKQTPXFunctionLineGraph(parent->getPlotter())
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(JKQTPlotter* parent):
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(parent)
|
||||
{
|
||||
title=title_;
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=f;
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(f, title_, parent->getPlotter())
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(parent)
|
||||
{
|
||||
title=title_;
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=std::move(f);
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(std::move(f), title_, parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(parent)
|
||||
{
|
||||
title=title_;
|
||||
functionType=type;
|
||||
setParams(params);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(type, params, title, parent->getPlotter())
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::~JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXFunctionLineGraph::setDrawLine(bool __value)
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setDrawLine(bool __value)
|
||||
{
|
||||
this->drawLine = __value;
|
||||
}
|
||||
|
||||
bool JKQTPXFunctionLineGraph::getDrawLine() const
|
||||
bool JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getDrawLine() const
|
||||
{
|
||||
return this->drawLine;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpPlotFunctionType &__value)
|
||||
{
|
||||
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
plotFunction = __value;
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimplePlotFunctionType &__value)
|
||||
{
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=__value;
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__value)
|
||||
{
|
||||
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
plotFunction = std::move(__value);
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType &&__value)
|
||||
{
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=std::move(__value);
|
||||
functionType=SpecialFunction::UserFunction;
|
||||
|
||||
data.clear();
|
||||
}
|
||||
|
||||
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getPlotFunctionFunctor() const
|
||||
{
|
||||
return plotFunction;
|
||||
}
|
||||
|
||||
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getSimplePlotFunction() const
|
||||
{
|
||||
return simplePlotFunction;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePen(painter, parent);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
@ -195,73 +97,110 @@ void JKQTPXFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRect
|
||||
|
||||
}
|
||||
|
||||
QColor JKQTPXFunctionLineGraph::getKeyLabelColor() const {
|
||||
QColor JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getKeyLabelColor() const {
|
||||
return getLineColor();
|
||||
}
|
||||
|
||||
bool JKQTPXFunctionLineGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero)
|
||||
{
|
||||
smallestGreaterZero=minx=maxx=0; return false;
|
||||
|
||||
QBrush JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorBrush(JKQTPEnhancedPainter& /*painter*/) const {
|
||||
QBrush b;
|
||||
b.setColor(errorFillColor);
|
||||
b.setStyle(errorFillStyle);
|
||||
return b;
|
||||
}
|
||||
|
||||
bool JKQTPXFunctionLineGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero)
|
||||
{
|
||||
smallestGreaterZero=miny=maxy=0; return false;
|
||||
QPen JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
|
||||
QPen p;
|
||||
p.setColor(errorColor);
|
||||
p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
|
||||
p.setStyle(errorStyle);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
p.setCapStyle(Qt::RoundCap);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::createPlotData(bool collectParams) {
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setErrorLineColor(const QColor &__value)
|
||||
{
|
||||
this->errorColor = __value;
|
||||
}
|
||||
|
||||
QColor JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorLineColor() const
|
||||
{
|
||||
return this->errorColor;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setErrorFillColor(const QColor &__value)
|
||||
{
|
||||
this->errorFillColor = __value;
|
||||
}
|
||||
|
||||
QColor JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorFillColor() const
|
||||
{
|
||||
return this->errorFillColor;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setErrorFillStyle(Qt::BrushStyle __value)
|
||||
{
|
||||
this->errorFillStyle = __value;
|
||||
}
|
||||
|
||||
Qt::BrushStyle JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorFillStyle() const
|
||||
{
|
||||
return this->errorFillStyle;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setErrorLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->errorStyle = __value;
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorLineStyle() const
|
||||
{
|
||||
return this->errorStyle;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setErrorLineWidth(double __value)
|
||||
{
|
||||
this->errorLineWidth = __value;
|
||||
}
|
||||
|
||||
double JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getErrorLineWidth() const
|
||||
{
|
||||
return this->errorLineWidth;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setColor(QColor c)
|
||||
{
|
||||
setLineColor(c);
|
||||
c.setAlphaF(0.5);
|
||||
setHighlightingLineColor(c);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setDrawErrorPolygons(bool __value)
|
||||
{
|
||||
this->drawErrorPolygons = __value;
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getDrawErrorPolygons() const
|
||||
{
|
||||
return this->drawErrorPolygons;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::setDrawErrorLines(bool __value)
|
||||
{
|
||||
this->drawErrorLines = __value;
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::getDrawErrorLines() const
|
||||
{
|
||||
return this->drawErrorLines;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawXGraph(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPXFunctionLineGraph[%1]::createPlotData()").arg(title));
|
||||
#endif
|
||||
data.clear();
|
||||
if (collectParams) collectParameters();
|
||||
|
||||
if (parent==nullptr) return;
|
||||
if (!plotFunction && !simplePlotFunction) return;
|
||||
|
||||
jkqtpSimplePlotFunctionType func;
|
||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) func=simplePlotFunction;
|
||||
|
||||
const double xmin=parent->getXMin();
|
||||
const double xmax=parent->getXMax();
|
||||
|
||||
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double x) -> QPointF { return plot->transform(x, func(x)); }, this, std::placeholders::_1);
|
||||
|
||||
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||
data=evaluator.evaluate(xmin, xmax);
|
||||
data=JKQTPSimplyfyLineSegemnts(data, dataCleanupMaxAllowedAngleDegree);
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::collectParameters()
|
||||
{
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase::collectParameters();
|
||||
|
||||
if (parent && errorParameterColumn>=0) {
|
||||
ierrorparams.clear();
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax= static_cast<int>(datastore->getRows(errorParameterColumn));
|
||||
|
||||
for (int i=imin; i<imax; i++) {
|
||||
double xv=datastore->get(errorParameterColumn,i);
|
||||
ierrorparams<<xv;
|
||||
}
|
||||
int i=ierrorparams.size()-1;
|
||||
while (i>=0 && !JKQTPIsOKFloat(ierrorparams[i])) {
|
||||
ierrorparams.remove(i,1);
|
||||
i--;
|
||||
}
|
||||
|
||||
errorParams=&ierrorparams;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPXFunctionLineGraph::draw");
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawXGraph");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
@ -271,6 +210,8 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
createPlotData();
|
||||
//qDebug()<<"plot data created\n";
|
||||
|
||||
auto errorPlotFunction=buildErrorFunctorSpec();
|
||||
|
||||
drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
@ -308,11 +249,11 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
|
||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
||||
double xv=backtransformX(x);
|
||||
double yv=backtransformY(y);
|
||||
const double xv=backtransformX(x);
|
||||
const double yv=backtransformY(y);
|
||||
double ype=0, yme=0;
|
||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||
double e=errorPlotFunction(xv, getInternalErrorParams());
|
||||
const double e=errorPlotFunction(xv).y();
|
||||
ype=transformY(yv+e);
|
||||
yme=transformY(yv-e);
|
||||
ype=qBound(yami, ype, yama);
|
||||
@ -384,73 +325,9 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
//std::cout<<"plot done\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPlotter *parent):
|
||||
JKQTPYFunctionLineGraph(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(f, title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(f, title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(std::move(f), title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(std::move(f), title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(type, params, title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPXFunctionLineGraph(type, params, title_, parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawYGraph(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::draw");
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::drawYGraph");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
@ -460,6 +337,8 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
createPlotData();
|
||||
//std::cout<<"plot data created\n";
|
||||
|
||||
auto errorPlotFunction=buildErrorFunctorSpec();
|
||||
|
||||
drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
@ -497,11 +376,11 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
|
||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
||||
double xv=backtransformX(x);
|
||||
double yv=backtransformY(y);
|
||||
const double xv=backtransformX(x);
|
||||
const double yv=backtransformY(y);
|
||||
double xpe=0, xme=0;
|
||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||
double e=errorPlotFunction(yv, getInternalErrorParams());
|
||||
const double e=errorPlotFunction(yv).x();
|
||||
xpe=transformX(xv+e);
|
||||
xme=transformX(xv-e);
|
||||
xpe=qBound(xami, xpe, xama);
|
||||
@ -573,124 +452,80 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
}
|
||||
|
||||
|
||||
void JKQTPYFunctionLineGraph::createPlotData(bool collectParams) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(JKQTBasePlotter* parent):
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(JKQTPlotter* parent):
|
||||
JKQTPFunctorLineGraphBase(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
title=title_;
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=f;
|
||||
data.clear();
|
||||
if (collectParams) collectParameters();
|
||||
|
||||
if (parent==nullptr) return;
|
||||
if (!plotFunction && !simplePlotFunction) return;
|
||||
|
||||
jkqtpSimplePlotFunctionType func;
|
||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) func=simplePlotFunction;
|
||||
|
||||
const double ymin=parent->getYMin();
|
||||
const double ymax=parent->getYMax();
|
||||
|
||||
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double y) -> QPointF { return plot->transform(func(y), y); }, this, std::placeholders::_1);
|
||||
|
||||
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||
data=evaluator.evaluate(ymin, ymax);
|
||||
data=JKQTPSimplyfyLineSegemnts(data, dataCleanupMaxAllowedAngleDegree);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QBrush JKQTPXFunctionLineGraph::getErrorBrush(JKQTPEnhancedPainter& /*painter*/) const {
|
||||
QBrush b;
|
||||
b.setColor(errorFillColor);
|
||||
b.setStyle(errorFillStyle);
|
||||
return b;
|
||||
}
|
||||
|
||||
QPen JKQTPXFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
|
||||
QPen p;
|
||||
p.setColor(errorColor);
|
||||
p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
|
||||
p.setStyle(errorStyle);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
p.setCapStyle(Qt::RoundCap);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorParams(const QVector<double> &errorParams)
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(f, title_, parent->getPlotter())
|
||||
{
|
||||
ierrorparams=errorParams;
|
||||
setErrorParams(&ierrorparams);
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorParameterColumn(int __value)
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
this->errorParameterColumn = __value;
|
||||
title=title_;
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=std::move(f);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
int JKQTPXFunctionLineGraph::getErrorParameterColumn() const
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(std::move(f), title_, parent->getPlotter())
|
||||
{
|
||||
return this->errorParameterColumn;
|
||||
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorParameterColumn(size_t __value) {
|
||||
this->errorParameterColumn = static_cast<int>(__value);
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorLineColor(const QColor &__value)
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(JKQTPFunctorLineGraphBase::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
this->errorColor = __value;
|
||||
title=title_;
|
||||
setSpecialFunction(type);
|
||||
setParams(params);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
QColor JKQTPXFunctionLineGraph::getErrorLineColor() const
|
||||
JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(JKQTPFunctorLineGraphBase::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(type, params, title, parent->getPlotter())
|
||||
{
|
||||
return this->errorColor;
|
||||
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorFillColor(const QColor &__value)
|
||||
{
|
||||
this->errorFillColor = __value;
|
||||
|
||||
JKQTPFunctorLineGraphBase::~JKQTPFunctorLineGraphBase() {
|
||||
|
||||
}
|
||||
|
||||
QColor JKQTPXFunctionLineGraph::getErrorFillColor() const
|
||||
void JKQTPFunctorLineGraphBase::setSpecialFunction(JKQTPFunctorLineGraphBase::SpecialFunction function)
|
||||
{
|
||||
return this->errorFillColor;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorFillStyle(Qt::BrushStyle __value)
|
||||
{
|
||||
this->errorFillStyle = __value;
|
||||
}
|
||||
|
||||
Qt::BrushStyle JKQTPXFunctionLineGraph::getErrorFillStyle() const
|
||||
{
|
||||
return this->errorFillStyle;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorLineStyle(Qt::PenStyle __value)
|
||||
{
|
||||
this->errorStyle = __value;
|
||||
}
|
||||
|
||||
Qt::PenStyle JKQTPXFunctionLineGraph::getErrorLineStyle() const
|
||||
{
|
||||
return this->errorStyle;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorLineWidth(double __value)
|
||||
{
|
||||
this->errorLineWidth = __value;
|
||||
}
|
||||
|
||||
double JKQTPXFunctionLineGraph::getErrorLineWidth() const
|
||||
{
|
||||
return this->errorLineWidth;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setSpecialFunction(JKQTPXFunctionLineGraph::SpecialFunction function)
|
||||
{
|
||||
if (function==JKQTPXFunctionLineGraph::Polynomial) {
|
||||
if (function==JKQTPFunctorLineGraphBase::Polynomial) {
|
||||
setPlotFunctionFunctor([](double x, const QVector<double>& param) {
|
||||
double res=0;
|
||||
if (param.size()>0) {
|
||||
@ -705,7 +540,7 @@ void JKQTPXFunctionLineGraph::setSpecialFunction(JKQTPXFunctionLineGraph::Specia
|
||||
return res;
|
||||
});
|
||||
}
|
||||
else if (function==JKQTPXFunctionLineGraph::Exponential) setPlotFunctionFunctor([](double x, const QVector<double>& param) {
|
||||
else if (function==JKQTPFunctorLineGraphBase::Exponential) setPlotFunctionFunctor([](double x, const QVector<double>& param) {
|
||||
double res=0;
|
||||
if (param.size()>=3) {
|
||||
res=param.value(0,0)+param.value(1,0)*exp(x/param.value(2,0));
|
||||
@ -714,7 +549,7 @@ void JKQTPXFunctionLineGraph::setSpecialFunction(JKQTPXFunctionLineGraph::Specia
|
||||
}
|
||||
return res;
|
||||
});
|
||||
else if (function==JKQTPXFunctionLineGraph::PowerLaw) setPlotFunctionFunctor([](double x, const QVector<double>& param) {
|
||||
else if (function==JKQTPFunctorLineGraphBase::PowerLaw) setPlotFunctionFunctor([](double x, const QVector<double>& param) {
|
||||
double res=0;
|
||||
if (param.size()>=3) {
|
||||
res=param.value(0,0)+param.value(1,0)*pow(x, param.value(2,1));
|
||||
@ -728,84 +563,279 @@ void JKQTPXFunctionLineGraph::setSpecialFunction(JKQTPXFunctionLineGraph::Specia
|
||||
else throw std::runtime_error("unknown special function type");
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::SpecialFunction JKQTPXFunctionLineGraph::getFunctionType() const
|
||||
{
|
||||
return functionType;
|
||||
}
|
||||
|
||||
QVector<double> JKQTPXFunctionLineGraph::getInternalErrorParams() const {
|
||||
return ierrorparams;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setDrawErrorPolygons(bool __value)
|
||||
{
|
||||
this->drawErrorPolygons = __value;
|
||||
}
|
||||
|
||||
bool JKQTPXFunctionLineGraph::getDrawErrorPolygons() const
|
||||
{
|
||||
return this->drawErrorPolygons;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setDrawErrorLines(bool __value)
|
||||
{
|
||||
this->drawErrorLines = __value;
|
||||
}
|
||||
|
||||
bool JKQTPXFunctionLineGraph::getDrawErrorLines() const
|
||||
{
|
||||
return this->drawErrorLines;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpPlotFunctionType &__value)
|
||||
void JKQTPFunctorLineGraphBase::setErrorPlotFunction(const jkqtpPlotFunctionType &__value)
|
||||
{
|
||||
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
errorPlotFunction=__value;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpPlotFunctionType &&__value)
|
||||
void JKQTPFunctorLineGraphBase::setErrorPlotFunction(jkqtpPlotFunctionType &&__value)
|
||||
{
|
||||
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
errorPlotFunction = std::move(__value);
|
||||
data.clear();
|
||||
}
|
||||
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getErrorPlotFunction() const
|
||||
jkqtpPlotFunctionType JKQTPFunctorLineGraphBase::getErrorPlotFunction() const
|
||||
{
|
||||
return errorPlotFunction;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpSimplePlotFunctionType &__value)
|
||||
void JKQTPFunctorLineGraphBase::setErrorPlotFunction(const jkqtpSimplePlotFunctionType &__value)
|
||||
{
|
||||
errorPlotFunction=jkqtpPlotFunctionType();
|
||||
errorSimplePlotFunction=__value;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
|
||||
void JKQTPFunctorLineGraphBase::setErrorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
|
||||
{
|
||||
errorPlotFunction=jkqtpPlotFunctionType();
|
||||
errorSimplePlotFunction = std::move(__value);
|
||||
data.clear();
|
||||
}
|
||||
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getErrorSimplePlotFunction() const
|
||||
|
||||
jkqtpSimplePlotFunctionType JKQTPFunctorLineGraphBase::getErrorSimplePlotFunction() const
|
||||
{
|
||||
return errorSimplePlotFunction;
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::setErrorParams(void *__value)
|
||||
void JKQTPFunctorLineGraphBase::setPlotFunctionFunctor(const jkqtpPlotFunctionType &__value)
|
||||
{
|
||||
this->errorParams = __value;
|
||||
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
plotFunction = __value;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void *JKQTPXFunctionLineGraph::getErrorParams() const
|
||||
void JKQTPFunctorLineGraphBase::setPlotFunctionFunctor(const jkqtpSimplePlotFunctionType &__value)
|
||||
{
|
||||
return this->errorParams;
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=__value;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPFunctorLineGraphBase::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__value)
|
||||
{
|
||||
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||
plotFunction = std::move(__value);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void JKQTPFunctorLineGraphBase::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType &&__value)
|
||||
{
|
||||
plotFunction=jkqtpPlotFunctionType();
|
||||
simplePlotFunction=std::move(__value);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
jkqtpPlotFunctionType JKQTPFunctorLineGraphBase::getPlotFunctionFunctor() const
|
||||
{
|
||||
return plotFunction;
|
||||
}
|
||||
|
||||
jkqtpSimplePlotFunctionType JKQTPFunctorLineGraphBase::getSimplePlotFunction() const
|
||||
{
|
||||
return simplePlotFunction;
|
||||
}
|
||||
|
||||
bool JKQTPFunctorLineGraphBase::isSimplePlotFunction() const
|
||||
{
|
||||
return !static_cast<bool>(plotFunction) && static_cast<bool>(simplePlotFunction);
|
||||
}
|
||||
|
||||
|
||||
bool JKQTPXFunctionLineGraph::usesColumn(int c) const
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTBasePlotter* parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
return JKQTPEvaluatedFunctionWithParamsGraphBase::usesColumn(c)||(c==errorParameterColumn);
|
||||
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPlotter* parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(f, title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(f, title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(std::move(f), title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(std::move(f), title_, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(type, params, title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(type, params, title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
||||
|
||||
}
|
||||
|
||||
void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
drawXGraph(painter);
|
||||
}
|
||||
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec JKQTPXFunctionLineGraph::buildPlotFunctorSpec()
|
||||
{
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec spec;
|
||||
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
if (!plotFunction && !simplePlotFunction) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
// range over which to evaluate func
|
||||
spec.range_start=parent->getXMin();
|
||||
spec.range_end=parent->getXMax();
|
||||
|
||||
// the actual function to use
|
||||
if (plotFunction) spec.func=std::bind([&](double x, const QVector<double>& p) -> QPointF { return QPointF(x, plotFunction(x, p)); }, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) spec.func=[&](double x) -> QPointF { return QPointF(x, simplePlotFunction(x)); };
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::function<QPointF (double)> JKQTPXFunctionLineGraph::buildErrorFunctorSpec()
|
||||
{
|
||||
std::function<QPointF (double)> spec;
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
if (!plotFunction && !simplePlotFunction) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
// the actual function to use
|
||||
if (errorPlotFunction) spec=std::bind([&](double x, const QVector<double>& p) -> QPointF { return QPointF(0, errorPlotFunction(x, p)); }, std::placeholders::_1, getInternalParams());
|
||||
else if (errorSimplePlotFunction) spec=[&](double x) -> QPointF { return QPointF(0, errorSimplePlotFunction(x)); };
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPlotter *parent):
|
||||
JKQTPYFunctionLineGraph(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(f, title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(f, title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(std::move(f), title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(std::move(f), title, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(type, params, title_, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTPlotter *parent):
|
||||
JKQTPFunctorLineGraphBase(type, params, title_, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
drawYGraph(painter);
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec JKQTPYFunctionLineGraph::buildPlotFunctorSpec()
|
||||
{
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec spec;
|
||||
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
if (!plotFunction && !simplePlotFunction) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
// range over which to evaluate func
|
||||
spec.range_start=parent->getYMin();
|
||||
spec.range_end=parent->getYMax();
|
||||
|
||||
// the actual function to use
|
||||
if (plotFunction) spec.func=std::bind([&](double y, const QVector<double>& p) -> QPointF { return QPointF(plotFunction(y, p), y); }, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) spec.func=[&](double y) -> QPointF { return QPointF(simplePlotFunction(y), y); };
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::function<QPointF (double)> JKQTPYFunctionLineGraph::buildErrorFunctorSpec()
|
||||
{
|
||||
std::function<QPointF (double)> spec;
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
if (!plotFunction && !simplePlotFunction) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
// the actual function to use
|
||||
if (errorPlotFunction) spec=std::bind([&](double y, const QVector<double>& p) -> QPointF { return QPointF(errorPlotFunction(y, p), 0); }, std::placeholders::_1, getInternalParams());
|
||||
else if (errorSimplePlotFunction) spec=[&](double y) -> QPointF { return QPointF(errorSimplePlotFunction(y), 0); };
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -33,6 +33,118 @@
|
||||
#define jkqtpgraphsevaluatedfunction_H
|
||||
|
||||
|
||||
/** \brief This class extends JKQTPEvaluatedFunctionWithErrorsGraphBase with functions to draw the graphs and
|
||||
* set the drawing style
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* \note Since this class is meant as a base for both f(x)- and f(y)-functions, it cannot
|
||||
* implememt JKQTPGraph::draw(). Therefore it provides two implementations drawXGraph()
|
||||
* and drawYGraph() and the user has to decide in the concrete graph class, which one to call
|
||||
* (or whether to do the drawing completely different).
|
||||
*
|
||||
* \see e.g. JKQTPXFunctionLineGraph for a concrete implementation
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase: public JKQTPEvaluatedFunctionWithErrorsGraphBase, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(JKQTBasePlotter* parent=nullptr);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(JKQTPlotter* parent);
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase() override;
|
||||
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
/*! \copydoc drawLine */
|
||||
bool getDrawLine() const;
|
||||
|
||||
|
||||
/*! \copydoc drawErrorPolygons */
|
||||
bool getDrawErrorPolygons() const;
|
||||
/*! \copydoc drawErrorLines */
|
||||
bool getDrawErrorLines() const;
|
||||
/*! \copydoc errorColor */
|
||||
virtual QColor getErrorLineColor() const;
|
||||
/*! \copydoc errorFillColor */
|
||||
virtual QColor getErrorFillColor() const;
|
||||
/*! \copydoc errorFillStyle */
|
||||
virtual Qt::BrushStyle getErrorFillStyle() const;
|
||||
/*! \copydoc errorStyle */
|
||||
virtual Qt::PenStyle getErrorLineStyle() const;
|
||||
/*! \copydoc errorLineWidth */
|
||||
virtual double getErrorLineWidth() const;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
/*! \brief set color, fill color and error color at the same time */
|
||||
void setColor(QColor c);
|
||||
|
||||
/*! \copydoc drawLine */
|
||||
void setDrawLine(bool __value);
|
||||
/*! \copydoc drawErrorPolygons */
|
||||
void setDrawErrorPolygons(bool __value);
|
||||
/*! \copydoc drawErrorLines */
|
||||
void setDrawErrorLines(bool __value);
|
||||
/*! \copydoc errorColor */
|
||||
virtual void setErrorLineColor(const QColor & __value);
|
||||
/*! \copydoc errorFillColor */
|
||||
virtual void setErrorFillColor(const QColor & __value);
|
||||
/*! \copydoc errorFillStyle */
|
||||
virtual void setErrorFillStyle(Qt::BrushStyle __value);
|
||||
/*! \copydoc errorStyle */
|
||||
virtual void setErrorLineStyle(Qt::PenStyle __value);
|
||||
/*! \copydoc errorLineWidth */
|
||||
virtual void setErrorLineWidth(double __value);
|
||||
|
||||
protected:
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
void drawXGraph(JKQTPEnhancedPainter& painter);
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
void drawYGraph(JKQTPEnhancedPainter& painter);
|
||||
|
||||
|
||||
|
||||
|
||||
/** \brief indicates whether to draw a line or not */
|
||||
bool drawLine;
|
||||
/** \brief indicates whether to fill the space between the curve and the x-axis */
|
||||
bool fillCurve;
|
||||
|
||||
|
||||
/** \brief indicates whether an error polygon should be drawn */
|
||||
bool drawErrorPolygons;
|
||||
/** \brief indicates whether error lines should be drawn */
|
||||
bool drawErrorLines;
|
||||
|
||||
|
||||
|
||||
/** \brief color of the error graph */
|
||||
QColor errorColor;
|
||||
/** \brief color of the error graph fill */
|
||||
QColor errorFillColor;
|
||||
/** \brief linestyle of the error graph lines */
|
||||
Qt::PenStyle errorStyle;
|
||||
/** \brief width (pixels) of the error graph */
|
||||
double errorLineWidth;
|
||||
/** \brief fill style, if the error curve should be filled */
|
||||
Qt::BrushStyle errorFillStyle;
|
||||
|
||||
|
||||
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const;
|
||||
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! \brief type of functions that may be plotted by JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph
|
||||
@ -54,84 +166,43 @@ typedef std::function<double(double, const QVector<double>&)> jkqtpPlotFunctionT
|
||||
typedef std::function<double(double)> jkqtpSimplePlotFunctionType;
|
||||
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
|
||||
\ingroup jkqtplotter_functiongraphs
|
||||
|
||||
This class uses the intelligent plotting algorithm for functions, implemented in JKQTPAdaptiveFunctionGraphEvaluator.
|
||||
It starts by sampling the function at minSamples positions. Then each function interval is bisected recursively if
|
||||
necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
|
||||
and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added
|
||||
to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f]
|
||||
In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
|
||||
distance to the other points. This helps to prevent beats when sampling periodic functions.
|
||||
|
||||
Finally the obtained data is cleaned up to reduce the amount of points, by deleting a point, when it leads to an
|
||||
angle between consecutive line-segments of less than dataCleanupMaxAllowedAngleDegree.
|
||||
|
||||
The following image shows some example graphs:
|
||||
|
||||
\image html plot_functionplots.png
|
||||
|
||||
\see \ref JKQTPlotterFunctionPlots, JKQTPAdaptiveFunctionGraphEvaluator, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression()
|
||||
/** \brief extends JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase with the capabilities to define functions from C++-functors
|
||||
* of type jkqtpSimplePlotFunctionType or jkqtpPlotFunctionType
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* \see JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph for a concrete implementation
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPEvaluatedFunctionWithParamsGraphBase, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPFunctorLineGraphBase: public JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum SpecialFunction {
|
||||
Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
|
||||
Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
|
||||
Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
|
||||
PowerLaw, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
|
||||
|
||||
UserFunction, /*!< \brief no special function but the function is provided by the user */
|
||||
};
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(JKQTBasePlotter* parent=nullptr);
|
||||
JKQTPFunctorLineGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(JKQTPlotter* parent);
|
||||
JKQTPFunctorLineGraphBase(JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
JKQTPFunctorLineGraphBase(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTPlotter* parent);
|
||||
JKQTPFunctorLineGraphBase(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
JKQTPFunctorLineGraphBase(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
||||
JKQTPFunctorLineGraphBase(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTBasePlotter* parent);
|
||||
JKQTPFunctorLineGraphBase(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTBasePlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTPlotter* parent);
|
||||
JKQTPFunctorLineGraphBase(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTPlotter* parent);
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPXFunctionLineGraph() override;
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
/** \brief get the maximum and minimum x-value of the graph
|
||||
*
|
||||
* This functions returns 0 for both parameters, so that the plotter uses the predefined
|
||||
* min and max values.
|
||||
*/
|
||||
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
||||
/** \brief get the maximum and minimum y-value of the graph
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
/*! \brief set color, fill color and error color at the same time */
|
||||
void setColor(QColor c);
|
||||
|
||||
/*! \copydoc drawLine */
|
||||
void setDrawLine(bool __value);
|
||||
/*! \copydoc drawLine */
|
||||
bool getDrawLine() const;
|
||||
virtual ~JKQTPFunctorLineGraphBase() override;
|
||||
|
||||
/** \brief sets a functor to be plotted
|
||||
*
|
||||
@ -153,23 +224,20 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPEvaluatedFunct
|
||||
* \see simplePlotFunction
|
||||
*/
|
||||
virtual void setPlotFunctionFunctor (const jkqtpSimplePlotFunctionType & __value);
|
||||
/*! \copydoc plotFunction */ \
|
||||
/*! \copydoc plotFunction
|
||||
*
|
||||
* \see isSimplePlotFunction() */ \
|
||||
virtual jkqtpPlotFunctionType getPlotFunctionFunctor () const;
|
||||
/*! \copydoc simplePlotFunction */ \
|
||||
/*! \copydoc simplePlotFunction
|
||||
*
|
||||
* \see isSimplePlotFunction() */ \
|
||||
virtual jkqtpSimplePlotFunctionType getSimplePlotFunction () const;
|
||||
|
||||
/** \brief returns whether the plot function was defined as a jkqtpSimpleParametricCurveFunctionType (\c true ) or
|
||||
* a jkqtpParametricCurveFunctionType (\c false ) */
|
||||
bool isSimplePlotFunction() const;
|
||||
|
||||
/** \brief returns the currently set internal parameter vector */
|
||||
QVector<double> getInternalErrorParams() const;
|
||||
|
||||
/*! \copydoc drawErrorPolygons */
|
||||
void setDrawErrorPolygons(bool __value);
|
||||
/*! \copydoc drawErrorPolygons */
|
||||
bool getDrawErrorPolygons() const;
|
||||
/*! \copydoc drawErrorLines */
|
||||
void setDrawErrorLines(bool __value);
|
||||
/*! \copydoc drawErrorLines */
|
||||
bool getDrawErrorLines() const;
|
||||
/** \brief sets a functor to be used for calculating errors
|
||||
*
|
||||
* \see errorPlotFunction
|
||||
@ -194,100 +262,73 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPEvaluatedFunct
|
||||
virtual void setErrorPlotFunction (const jkqtpSimplePlotFunctionType & __value);
|
||||
/*! \copydoc errorSimplePlotFunction */ \
|
||||
virtual jkqtpSimplePlotFunctionType getErrorSimplePlotFunction () const;
|
||||
/*! \copydoc errorParams */
|
||||
virtual void setErrorParams(void* __value);
|
||||
/*! \copydoc errorParams */
|
||||
void *getErrorParams() const;
|
||||
/** \brief sets the error params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
void setErrorParams(const QVector<double>& errorParams);
|
||||
/*! \copydoc errorParameterColumn */
|
||||
void setErrorParameterColumn(int __value);
|
||||
/*! \copydoc errorParameterColumn */
|
||||
int getErrorParameterColumn() const;
|
||||
/*! \copydoc errorParameterColumn */
|
||||
void setErrorParameterColumn (size_t __value);
|
||||
|
||||
/*! \copydoc errorColor */
|
||||
virtual void setErrorLineColor(const QColor & __value);
|
||||
/*! \copydoc errorColor */
|
||||
virtual QColor getErrorLineColor() const;
|
||||
/*! \copydoc errorFillColor */
|
||||
virtual void setErrorFillColor(const QColor & __value);
|
||||
/*! \copydoc errorFillColor */
|
||||
virtual QColor getErrorFillColor() const;
|
||||
/*! \copydoc errorFillStyle */
|
||||
virtual void setErrorFillStyle(Qt::BrushStyle __value);
|
||||
/*! \copydoc errorFillStyle */
|
||||
virtual Qt::BrushStyle getErrorFillStyle() const;
|
||||
/*! \copydoc errorStyle */
|
||||
virtual void setErrorLineStyle(Qt::PenStyle __value);
|
||||
/*! \copydoc errorStyle */
|
||||
virtual Qt::PenStyle getErrorLineStyle() const;
|
||||
/*! \copydoc errorLineWidth */
|
||||
virtual void setErrorLineWidth(double __value);
|
||||
/*! \copydoc errorLineWidth */
|
||||
virtual double getErrorLineWidth() const;
|
||||
|
||||
/** \copydoc JKQTPGraph::usesColumn() */
|
||||
virtual bool usesColumn(int c) const override;
|
||||
|
||||
|
||||
/** \brief sets function to the given special function */
|
||||
void setSpecialFunction(SpecialFunction function);
|
||||
/** \brief returns, which special function is set (or if any is set) */
|
||||
SpecialFunction getFunctionType() const;
|
||||
protected:
|
||||
/** \brief ensure that current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams and ierrorparams */
|
||||
virtual void collectParameters() override;
|
||||
|
||||
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData( bool collectParams=true) override;
|
||||
|
||||
|
||||
/** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the error plot function */
|
||||
int errorParameterColumn;
|
||||
|
||||
/** \brief indicates whether to draw a line or not */
|
||||
bool drawLine;
|
||||
/** \brief indicates whether to fill the space between the curve and the x-axis */
|
||||
bool fillCurve;
|
||||
/** \brief the function to be plotted */
|
||||
jkqtpPlotFunctionType plotFunction;
|
||||
/** \brief a simple function to be plotted, simplified form without parameters */
|
||||
jkqtpSimplePlotFunctionType simplePlotFunction;
|
||||
/** \brief indicates whether a special function is set (and if so, which one), or a user-supplied function */
|
||||
SpecialFunction functionType;
|
||||
|
||||
|
||||
/** \brief indicates whether an error polygon should be drawn */
|
||||
bool drawErrorPolygons;
|
||||
/** \brief indicates whether error lines should be drawn */
|
||||
bool drawErrorLines;
|
||||
/** \brief this function calculates the error at a given position */
|
||||
jkqtpPlotFunctionType errorPlotFunction;
|
||||
/** \brief this function calculates the error at a given position, simplified form without parameters */
|
||||
jkqtpSimplePlotFunctionType errorSimplePlotFunction;
|
||||
/** \brief parameters for errorFunction */
|
||||
void* errorParams;
|
||||
};
|
||||
|
||||
|
||||
/** \brief color of the error graph */
|
||||
QColor errorColor;
|
||||
/** \brief color of the error graph fill */
|
||||
QColor errorFillColor;
|
||||
/** \brief linestyle of the error graph lines */
|
||||
Qt::PenStyle errorStyle;
|
||||
/** \brief width (pixels) of the error graph */
|
||||
double errorLineWidth;
|
||||
/** \brief fill style, if the error curve should be filled */
|
||||
Qt::BrushStyle errorFillStyle;
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
|
||||
\ingroup jkqtplotter_functiongraphs
|
||||
|
||||
This class uses the intelligent plotting algorithm for functions, implemented in JKQTPAdaptiveFunctionGraphEvaluator.
|
||||
|
||||
The following image shows some example graphs:
|
||||
|
||||
\image html plot_functionplots.png
|
||||
|
||||
\see \ref JKQTPlotterFunctionPlots, JKQTPAdaptiveFunctionGraphEvaluator, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression()
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPFunctorLineGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const;
|
||||
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
|
||||
/** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||
QVector<double> ierrorparams;
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(JKQTBasePlotter* parent=nullptr);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTBasePlotter* parent);
|
||||
/** \brief class constructor */
|
||||
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTPlotter* parent);
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPXFunctionLineGraph() override;
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
|
||||
protected:
|
||||
|
||||
/** \copydoc JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec() */
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() override;
|
||||
|
||||
/** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
|
||||
virtual std::function<QPointF(double)> buildErrorFunctorSpec() override;
|
||||
|
||||
};
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
|
||||
@ -299,7 +340,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPEvaluatedFunct
|
||||
|
||||
\see \ref JKQTPlotterFunctionPlots , JKQTPXFunctionLineGraph, JKQTPXYFunctionLineGraph
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineGraph {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPFunctorLineGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
@ -323,8 +364,11 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineG
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
protected:
|
||||
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData( bool collectParams=true) override;
|
||||
/** \copydoc JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec() */
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() override;
|
||||
|
||||
/** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
|
||||
virtual std::function<QPointF(double)> buildErrorFunctorSpec() override;
|
||||
|
||||
};
|
||||
|
||||
|
@ -35,16 +35,17 @@
|
||||
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::JKQTPEvaluatedFunctionGraphBase(JKQTBasePlotter* parent):
|
||||
JKQTPGraph(parent)
|
||||
JKQTPGraph(parent),
|
||||
parameterColumn(-1),
|
||||
minSamples(50),
|
||||
maxRefinementDegree(5),
|
||||
slopeTolerance(0.005),
|
||||
minPixelPerSample(32),
|
||||
dataCleanupMaxAllowedAngleDegree(0.2),
|
||||
displaySamplePoints(false)
|
||||
{
|
||||
minSamples=50;
|
||||
maxRefinementDegree=5;
|
||||
slopeTolerance=0.005;
|
||||
minPixelPerSample=32;
|
||||
dataCleanupMaxAllowedAngleDegree=0.2;
|
||||
displaySamplePoints=false;
|
||||
data.clear();
|
||||
|
||||
iparams.clear();
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::JKQTPEvaluatedFunctionGraphBase(JKQTPlotter* parent):
|
||||
@ -127,6 +128,24 @@ void JKQTPEvaluatedFunctionGraphBase::setDisplaySamplePoints(bool __value)
|
||||
this->displaySamplePoints = __value;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionGraphBase::createPlotData(bool collectParams)
|
||||
{
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPEvaluatedFunctionWithErrorsGraphBase[%1]::createPlotData()").arg(title));
|
||||
#endif
|
||||
data.clear();
|
||||
if (collectParams) collectParameters();
|
||||
PlotFunctorSpec plotfunc= buildPlotFunctorSpec();
|
||||
|
||||
if (plotfunc.isValid()) {
|
||||
std::function<QPointF(double)> fTransformedFunc= std::bind([plotfunc](const JKQTPPlotElement* plot, double t) -> QPointF { return plot->transform(plotfunc.func(t)); }, this, std::placeholders::_1);
|
||||
|
||||
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||
data=evaluator.evaluate(plotfunc.range_start, plotfunc.range_end);
|
||||
data=JKQTPSimplyfyLineSegemnts(data, dataCleanupMaxAllowedAngleDegree);
|
||||
}
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionGraphBase::getDisplaySamplePoints() const
|
||||
{
|
||||
return this->displaySamplePoints;
|
||||
@ -181,25 +200,7 @@ bool JKQTPEvaluatedFunctionGraphBase::getYMinMax(double &miny, double &maxy, dou
|
||||
}
|
||||
|
||||
|
||||
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase::JKQTPEvaluatedFunctionWithParamsGraphBase(JKQTBasePlotter *parent):
|
||||
parameterColumn(-1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase::JKQTPEvaluatedFunctionWithParamsGraphBase(JKQTPlotter *parent):
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase::~JKQTPEvaluatedFunctionWithParamsGraphBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::collectParameters()
|
||||
void JKQTPEvaluatedFunctionGraphBase::collectParameters()
|
||||
{
|
||||
if (parent && parameterColumn>=0) {
|
||||
iparams.clear();
|
||||
@ -221,67 +222,195 @@ void JKQTPEvaluatedFunctionWithParamsGraphBase::collectParameters()
|
||||
}
|
||||
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParams(const QVector<double> ¶ms)
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParams(const QVector<double> ¶ms)
|
||||
{
|
||||
iparams=params;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setCopiedParams(const double *params, int N)
|
||||
void JKQTPEvaluatedFunctionGraphBase::setCopiedParams(const double *params, int N)
|
||||
{
|
||||
QVector<double> v;
|
||||
for (int i=0; i<N; i++) { v<<params[i]; }
|
||||
setParams(v);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParamsV(double p1) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParamsV(double p1) {
|
||||
QVector<double> p;
|
||||
p<<p1;
|
||||
setParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParamsV(double p1, double p2) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParamsV(double p1, double p2) {
|
||||
QVector<double> p;
|
||||
p<<p1<<p2;
|
||||
setParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParamsV(double p1, double p2, double p3) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParamsV(double p1, double p2, double p3) {
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3;
|
||||
setParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParamsV(double p1, double p2, double p3, double p4) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParamsV(double p1, double p2, double p3, double p4) {
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3<<p4;
|
||||
setParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParamsV(double p1, double p2, double p3, double p4, double p5) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParamsV(double p1, double p2, double p3, double p4, double p5) {
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3<<p4<<p5;
|
||||
setParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParameterColumn(int __value)
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParameterColumn(int __value)
|
||||
{
|
||||
this->parameterColumn = __value;
|
||||
}
|
||||
|
||||
int JKQTPEvaluatedFunctionWithParamsGraphBase::getParameterColumn() const
|
||||
int JKQTPEvaluatedFunctionGraphBase::getParameterColumn() const
|
||||
{
|
||||
return this->parameterColumn;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithParamsGraphBase::setParameterColumn(size_t __value) {
|
||||
void JKQTPEvaluatedFunctionGraphBase::setParameterColumn(size_t __value) {
|
||||
this->parameterColumn = static_cast<int>(__value);
|
||||
}
|
||||
|
||||
QVector<double> JKQTPEvaluatedFunctionWithParamsGraphBase::getInternalParams() const {
|
||||
const QVector<double>& JKQTPEvaluatedFunctionGraphBase::getInternalParams() const {
|
||||
return iparams;
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionWithParamsGraphBase::usesColumn(int c) const
|
||||
QVector<double> &JKQTPEvaluatedFunctionGraphBase::getInternalParams()
|
||||
{
|
||||
return iparams;
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionGraphBase::usesColumn(int c) const
|
||||
{
|
||||
return (c==parameterColumn);
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec::PlotFunctorSpec():
|
||||
func(),
|
||||
range_start(0),
|
||||
range_end(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec::isValid() const
|
||||
{
|
||||
return static_cast<bool>(func) && (fabs(range_end-range_start)>0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphBase::JKQTPEvaluatedFunctionWithErrorsGraphBase(JKQTBasePlotter *parent):
|
||||
JKQTPEvaluatedFunctionGraphBase(parent),
|
||||
errorParameterColumn(-1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphBase::JKQTPEvaluatedFunctionWithErrorsGraphBase(JKQTPlotter *parent):
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphBase(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphBase::~JKQTPEvaluatedFunctionWithErrorsGraphBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const QVector<double>& JKQTPEvaluatedFunctionWithErrorsGraphBase::getInternalErrorParams() const {
|
||||
return ierrorparams;
|
||||
}
|
||||
|
||||
QVector<double>& JKQTPEvaluatedFunctionWithErrorsGraphBase::getInternalErrorParams() {
|
||||
return ierrorparams;
|
||||
}
|
||||
|
||||
bool JKQTPEvaluatedFunctionWithErrorsGraphBase::usesColumn(int c) const
|
||||
{
|
||||
return JKQTPEvaluatedFunctionGraphBase::usesColumn(c)||(c==errorParameterColumn);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParams(const QVector<double> &errorParams)
|
||||
{
|
||||
ierrorparams=errorParams;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParameterColumn(int __value)
|
||||
{
|
||||
this->errorParameterColumn = __value;
|
||||
}
|
||||
|
||||
int JKQTPEvaluatedFunctionWithErrorsGraphBase::getErrorParameterColumn() const
|
||||
{
|
||||
return this->errorParameterColumn;
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParameterColumn(size_t __value) {
|
||||
this->errorParameterColumn = static_cast<int>(__value);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1)
|
||||
{
|
||||
QVector<double> p;
|
||||
p<<p1;
|
||||
setErrorParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1, double p2)
|
||||
{
|
||||
QVector<double> p;
|
||||
p<<p1<<p2;
|
||||
setErrorParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1, double p2, double p3)
|
||||
{
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3;
|
||||
setErrorParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1, double p2, double p3, double p4)
|
||||
{
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3<<p4;
|
||||
setErrorParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1, double p2, double p3, double p4, double p5)
|
||||
{
|
||||
QVector<double> p;
|
||||
p<<p1<<p2<<p3<<p4<<p5;
|
||||
setErrorParams(p);
|
||||
}
|
||||
|
||||
void JKQTPEvaluatedFunctionWithErrorsGraphBase::collectParameters()
|
||||
{
|
||||
JKQTPEvaluatedFunctionGraphBase::collectParameters();
|
||||
|
||||
if (parent && errorParameterColumn>=0) {
|
||||
ierrorparams.clear();
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax= static_cast<int>(datastore->getRows(errorParameterColumn));
|
||||
|
||||
for (int i=imin; i<imax; i++) {
|
||||
double xv=datastore->get(errorParameterColumn,i);
|
||||
ierrorparams<<xv;
|
||||
}
|
||||
int i=ierrorparams.size()-1;
|
||||
while (i>=0 && !JKQTPIsOKFloat(ierrorparams[i])) {
|
||||
ierrorparams.remove(i,1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,26 @@
|
||||
|
||||
|
||||
|
||||
/** \brief Base class for graph classes that evaluate a mathematical function (e.g. defined as a C-fucntion),
|
||||
/** \brief Base class for graph classes that evaluate a mathematical function (e.g. defined as a C-function),
|
||||
* using an adaptive plotting algorithm from JKQTPAdaptiveFunctionGraphEvaluator
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* This class always plots a general 2D-graph \f$ [x,y]=\vec{f}(t) \f$ , which is calculated in dependence of
|
||||
* a parameter \f$ t \f$ . This parametrization is general enough to cover the cases of parametric function, as well as
|
||||
* x- and y-dependent function graphs:
|
||||
* - plot a function \f$ f(x) \f$ i.e. the plot points will be \f$ [x, f(x)] \f$
|
||||
* and the value rage will be the x-axis range. This is implemented by e.g. JKQTPXFunctionLineGraph.
|
||||
* - plot a function \f$ f(y) \f$ i.e. the plot points will be \f$ [f(y), y] \f$
|
||||
* and the value rage will be the y-axis range. This is implemented by e.g. JKQTPYFunctionLineGraph.
|
||||
* - plot a function \f$ [x,y]=\vec{f}(t) \f$ i.e. the plot points will be \f$ \vec{f}(t) \f$
|
||||
* and the value rage will be a user-defined range for \f$ gt \f$.
|
||||
* This is implemented by e.g. JKQTPXYFunctionLineGraph.
|
||||
* .
|
||||
*
|
||||
* In order to implement a special cas, one has to override/implement buildPlotFunctorSpec(), which
|
||||
* returns a functor and a value-range that can represent the cases above.
|
||||
*
|
||||
*
|
||||
* This class uses the intelligent plotting algorithm for functions, implemented in JKQTPAdaptiveFunctionGraphEvaluator.
|
||||
* It starts by sampling the function at minSamples positions. Then each function interval is bisected recursively if
|
||||
* necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
|
||||
@ -50,6 +66,9 @@
|
||||
* angle between consecutive line-segments of less than dataCleanupMaxAllowedAngleDegree.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \see JKQTPAdaptiveFunctionGraphEvaluator, JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionGraphBase: public JKQTPGraph {
|
||||
@ -75,6 +94,21 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionGraphBase: public JKQTPGraph
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
/** \brief sets the params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
virtual void setParams(const QVector<double>& params);
|
||||
/** \brief sets the params from a copy of the given array of length \a N */
|
||||
void setCopiedParams(const double* params, int N);
|
||||
|
||||
/** \brief returns the currently set internal parameter vector */
|
||||
const QVector<double>& getInternalParams() const;
|
||||
/** \brief returns the currently set internal parameter vector */
|
||||
QVector<double>& getInternalParams();
|
||||
/** \copydoc parameterColumn */
|
||||
int getParameterColumn() const;
|
||||
|
||||
/** \copydoc JKQTPGraph::usesColumn() */
|
||||
virtual bool usesColumn(int c) const override;
|
||||
|
||||
|
||||
/** \copydoc minSamples */
|
||||
unsigned int getMinSamples() const;
|
||||
@ -102,12 +136,73 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionGraphBase: public JKQTPGraph
|
||||
/** \copydoc displaySamplePoints */
|
||||
void setDisplaySamplePoints(bool __value);
|
||||
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1} */
|
||||
void setParamsV(double p1);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2} */
|
||||
void setParamsV(double p1, double p2);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3} */
|
||||
void setParamsV(double p1, double p2, double p3);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4} */
|
||||
void setParamsV(double p1, double p2, double p3, double p4);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4,p5} */
|
||||
void setParamsV(double p1, double p2, double p3, double p4, double p5);
|
||||
|
||||
/** \copydoc parameterColumn */
|
||||
void setParameterColumn(int __value);
|
||||
/** \copydoc parameterColumn */
|
||||
void setParameterColumn (size_t __value);
|
||||
|
||||
protected:
|
||||
/** \brief plot data calculated by createPlotData(), i.e. the datapoints \f$ \mbox{transform}\left(x, y=f(x, \vec{p})\right) \f$ to be plotted */
|
||||
QVector<QPointF> data;
|
||||
/** \brief specifies an internal plot functor \see buildPlotFunctor() */
|
||||
struct PlotFunctorSpec {
|
||||
/** brief construct an in-valid PlotFunctorSpec ... will become valid, by assigning a non-zero range and a plot-function */
|
||||
PlotFunctorSpec();
|
||||
/** \brief calculates the points \f$ [x,y] \f$ on the function graph, in dependence on
|
||||
* a dependent parameter variable, could be e.g. \f$ [x, f(x)] \f$ for plotting
|
||||
* a function \f$ f(x) \f$ over the x-axis. */
|
||||
std::function<QPointF(double)> func;
|
||||
/** \brief lower bound for the dependent parameter variable of func */
|
||||
double range_start;
|
||||
/** \brief upper bound for the dependent parameter variable of func */
|
||||
double range_end;
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
/** \brief this function returns a functor that is used to generate the plot data
|
||||
* in coordinate space, based on a range of the dependent variable in coordinate space.
|
||||
* In addition it also contains the value range over which to evaluate the functor PlotFunctorSpec::func
|
||||
*
|
||||
* This function has to be overridden by each class. Depending on the way that class defines
|
||||
* the actual plot function, this function has to compose its return type in different ways.
|
||||
* The three most common ways are:
|
||||
* - plot a function \f$ f(x) \f$ i.e. the plot points will be \f$ [x, f(x)] \f$
|
||||
* and the value rage will be the x-axis range. This is implemented by e.g. JKQTPXFunctionLineGraph.
|
||||
* - plot a function \f$ f(y) \f$ i.e. the plot points will be \f$ [f(y), y] \f$
|
||||
* and the value rage will be the y-axis range. This is implemented by e.g. JKQTPYFunctionLineGraph.
|
||||
* - plot a function \f$ [x,y]=\vec{f}(t) \f$ i.e. the plot points will be \f$ \vec{f}(t) \f$
|
||||
* and the value rage will be a user-defined range for \f$ gt \f$.
|
||||
* This is implemented by e.g. JKQTPXYFunctionLineGraph.
|
||||
* .
|
||||
*/
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() =0;
|
||||
|
||||
/** \brief ensure that current function parameters for a plot function (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams */
|
||||
virtual void collectParameters();
|
||||
|
||||
/** \brief draw all the sample points in data as small symbols */
|
||||
void drawSamplePoints(JKQTPEnhancedPainter &painter, QColor graphColor);
|
||||
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData( bool collectParams=true) =0;
|
||||
virtual void createPlotData( bool collectParams=true) ;
|
||||
|
||||
/** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the plot function */
|
||||
int parameterColumn;
|
||||
|
||||
/** \brief internal storage for the current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||
QVector<double> iparams;
|
||||
|
||||
/** \brief plot data calculated by createPlotData(), i.e. the datapoints \f$ \mbox{transform}\left(x, y=f(x, \vec{p})\right) \f$ to be plotted */
|
||||
QVector<QPointF> data;
|
||||
|
||||
/** \brief the minimum number of points to evaluate the function at */
|
||||
unsigned int minSamples;
|
||||
@ -127,66 +222,75 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionGraphBase: public JKQTPGraph
|
||||
double dataCleanupMaxAllowedAngleDegree;
|
||||
/** \brief if true [default: off] display the points where the function has been sampled */
|
||||
bool displaySamplePoints;
|
||||
|
||||
/** \brief draw all the sample points in data as small symbols */
|
||||
void drawSamplePoints(JKQTPEnhancedPainter &painter, QColor graphColor);
|
||||
};
|
||||
|
||||
|
||||
/** \brief extends JKQTPEvaluatedFunctionGraphBase with a set of functions that support function parameters
|
||||
/** \brief extends JKQTPEvaluatedFunctionGraphBase with some basic properties (e.g. function parameters)
|
||||
* for a second function that calculates an error (for drawing error indicators)
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* When implementing this, you will have to implement buildErrorFunctorSpec() in addition to
|
||||
* JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec()!
|
||||
*
|
||||
* \see JKQTPEvaluatedFunctionGraphBase
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionWithParamsGraphBase: public JKQTPEvaluatedFunctionGraphBase {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPEvaluatedFunctionWithErrorsGraphBase: public JKQTPEvaluatedFunctionGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
explicit JKQTPEvaluatedFunctionWithParamsGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
explicit JKQTPEvaluatedFunctionWithErrorsGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
explicit JKQTPEvaluatedFunctionWithParamsGraphBase(JKQTPlotter* parent);
|
||||
explicit JKQTPEvaluatedFunctionWithErrorsGraphBase(JKQTPlotter* parent);
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPEvaluatedFunctionWithParamsGraphBase();
|
||||
virtual ~JKQTPEvaluatedFunctionWithErrorsGraphBase();
|
||||
|
||||
|
||||
/** \brief sets the params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
virtual void setParams(const QVector<double>& params);
|
||||
/** \brief sets the params from a copy of the given array of length \a N */
|
||||
void setCopiedParams(const double* params, int N);
|
||||
/** \copydoc errorParameterColumn */
|
||||
int getErrorParameterColumn() const;
|
||||
|
||||
/** \brief returns the currently set internal parameter vector */
|
||||
QVector<double> getInternalParams() const;
|
||||
/** \copydoc parameterColumn */
|
||||
int getParameterColumn() const;
|
||||
const QVector<double>& getInternalErrorParams() const;
|
||||
/** \brief returns the currently set internal parameter vector */
|
||||
QVector<double>& getInternalErrorParams();
|
||||
|
||||
/** \copydoc JKQTPGraph::usesColumn() */
|
||||
virtual bool usesColumn(int c) const override;
|
||||
|
||||
public slots:
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1} */
|
||||
void setParamsV(double p1);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2} */
|
||||
void setParamsV(double p1, double p2);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3} */
|
||||
void setParamsV(double p1, double p2, double p3);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4} */
|
||||
void setParamsV(double p1, double p2, double p3, double p4);
|
||||
/** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4,p5} */
|
||||
void setParamsV(double p1, double p2, double p3, double p4, double p5);
|
||||
/** \brief sets the error params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
void setErrorParams(const QVector<double>& errorParams);
|
||||
/** \copydoc errorParameterColumn */
|
||||
void setErrorParameterColumn(int __value);
|
||||
/** \copydoc errorParameterColumn */
|
||||
void setErrorParameterColumn (size_t __value);
|
||||
|
||||
/** \brief set the internal error function parameters to {p1} */
|
||||
void setErrorParamsV(double p1);
|
||||
/** \brief set the internal error function parameters to {p1,p2} */
|
||||
void setErrorParamsV(double p1, double p2);
|
||||
/** \brief set the internal error function parameters to {p1,p2,p3} */
|
||||
void setErrorParamsV(double p1, double p2, double p3);
|
||||
/** \brief set the internal error function parameters to {p1,p2,p3,p4} */
|
||||
void setErrorParamsV(double p1, double p2, double p3, double p4);
|
||||
/** \brief set the internal error function parameters to {p1,p2,p3,p4,p5} */
|
||||
void setErrorParamsV(double p1, double p2, double p3, double p4, double p5);
|
||||
|
||||
/** \copydoc parameterColumn */
|
||||
void setParameterColumn(int __value);
|
||||
/** \copydoc parameterColumn */
|
||||
void setParameterColumn (size_t __value);
|
||||
protected:
|
||||
/** \brief ensure that current function parameters for a plot function (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams */
|
||||
virtual void collectParameters();
|
||||
/** \brief ensure that current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams and ierrorparams */
|
||||
virtual void collectParameters() override;
|
||||
/** \brief same as JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec(), but for error functions.
|
||||
*
|
||||
* The functor, returned by this function should calculate the error of the function (in x- and y-direction)
|
||||
* for every value \f$ t \f$ of the actual function.
|
||||
*
|
||||
* The parameter range is the same as for JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec()
|
||||
*
|
||||
* \see JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec()
|
||||
*/
|
||||
virtual std::function<QPointF(double)> buildErrorFunctorSpec() =0;
|
||||
|
||||
/** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the plot function */
|
||||
int parameterColumn;
|
||||
|
||||
/** \brief internal storage for the current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||
QVector<double> iparams;
|
||||
/** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the error plot function */
|
||||
int errorParameterColumn;
|
||||
/** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||
QVector<double> ierrorparams;
|
||||
};
|
||||
|
||||
|
||||
|
@ -33,14 +33,125 @@
|
||||
|
||||
|
||||
|
||||
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(JKQTBasePlotter* parent):
|
||||
JKQTPEvaluatedFunctionWithParamsGraphBase(parent)
|
||||
JKQTPXYFunctionLineGraphBase::JKQTPXYFunctionLineGraphBase(JKQTBasePlotter* parent):
|
||||
JKQTPEvaluatedFunctionGraphBase(parent),
|
||||
tmin(0.0),
|
||||
tmax(1.0)
|
||||
{
|
||||
tmin=0.0;
|
||||
tmax=1.0;
|
||||
|
||||
initLineStyle(parent, parentPlotStyle);
|
||||
setMaxRefinementDegree(8);
|
||||
}
|
||||
|
||||
JKQTPXYFunctionLineGraphBase::JKQTPXYFunctionLineGraphBase(JKQTPlotter* parent):
|
||||
JKQTPXYFunctionLineGraphBase(parent->getPlotter())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JKQTPXYFunctionLineGraphBase::~JKQTPXYFunctionLineGraphBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePen(painter, parent);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
p.setCapStyle(Qt::RoundCap);
|
||||
QPen np(Qt::NoPen);
|
||||
const double y=rect.top()+rect.height()/2.0;
|
||||
painter.setPen(np);
|
||||
painter.setPen(p);
|
||||
painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
|
||||
}
|
||||
|
||||
QColor JKQTPXYFunctionLineGraphBase::getKeyLabelColor() const {
|
||||
return getLineColor();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPXYFunctionLineGraph::draw");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
if (datastore==nullptr) return;
|
||||
|
||||
//qDebug()<<"start plot\n";
|
||||
createPlotData();
|
||||
//qDebug()<<"plot data created\n";
|
||||
|
||||
drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
QPen p=getLinePen(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
|
||||
|
||||
{
|
||||
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(p);
|
||||
painter.drawPolyline(data);
|
||||
}
|
||||
|
||||
|
||||
if (displaySamplePoints) drawSamplePoints(painter, getLineColor());
|
||||
}
|
||||
drawErrorsAfter(painter);
|
||||
//std::cout<<"plot done\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
double JKQTPXYFunctionLineGraphBase::getTMin() const
|
||||
{
|
||||
return tmin;
|
||||
}
|
||||
|
||||
double JKQTPXYFunctionLineGraphBase::getTMax() const
|
||||
{
|
||||
return tmax;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::setTMin(double val)
|
||||
{
|
||||
tmin=val;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::setTMax(double val)
|
||||
{
|
||||
tmax=val;
|
||||
}
|
||||
|
||||
QPair<double, double> JKQTPXYFunctionLineGraphBase::getTRange() const
|
||||
{
|
||||
return QPair<double, double>(tmin,tmax);
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::setTRange(double tmin_, double tmax_)
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraphBase::setTRange(const QPair<double, double> &range)
|
||||
{
|
||||
tmin=range.first;
|
||||
tmax=range.second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(JKQTBasePlotter* parent):
|
||||
JKQTPXYFunctionLineGraphBase(parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(JKQTPlotter* parent):
|
||||
@ -54,10 +165,9 @@ JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCu
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
title=title_;
|
||||
setTitle(title_);
|
||||
plotFunction=jkqtpParametricCurveFunctionType();
|
||||
simplePlotFunction=f;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCurveFunctionType &f, const QString &title_, double tmin_, double tmax_, JKQTPlotter *parent):
|
||||
@ -72,7 +182,7 @@ JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpSimpleParametricCurveFun
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
title=title_;
|
||||
setTitle(title_);
|
||||
plotFunction=jkqtpParametricCurveFunctionType();
|
||||
simplePlotFunction=std::move(f);
|
||||
data.clear();
|
||||
@ -89,7 +199,7 @@ JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpParametricCurveFunctionT
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
title=title_;
|
||||
setTitle(title_);
|
||||
simplePlotFunction=jkqtpSimpleParametricCurveFunctionType();
|
||||
plotFunction=std::move(f);
|
||||
data.clear();
|
||||
@ -106,7 +216,7 @@ JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFun
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
title=title_;
|
||||
setTitle(title_);
|
||||
simplePlotFunction=jkqtpSimpleParametricCurveFunctionType();
|
||||
plotFunction=std::move(f);
|
||||
data.clear();
|
||||
@ -119,7 +229,7 @@ JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFun
|
||||
}
|
||||
|
||||
JKQTPXYFunctionLineGraph::~JKQTPXYFunctionLineGraph() {
|
||||
data.clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -162,115 +272,26 @@ jkqtpSimpleParametricCurveFunctionType JKQTPXYFunctionLineGraph::getSimplePlotFu
|
||||
return simplePlotFunction;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXYFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePen(painter, parent);
|
||||
p.setJoinStyle(Qt::RoundJoin);
|
||||
p.setCapStyle(Qt::RoundCap);
|
||||
QPen np(Qt::NoPen);
|
||||
const double y=rect.top()+rect.height()/2.0;
|
||||
painter.setPen(np);
|
||||
painter.setPen(p);
|
||||
painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
|
||||
}
|
||||
|
||||
QColor JKQTPXYFunctionLineGraph::getKeyLabelColor() const {
|
||||
return getLineColor();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXYFunctionLineGraph::createPlotData(bool collectParams) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPXYFunctionLineGraph[%1]::createPlotData()").arg(title));
|
||||
#endif
|
||||
data.clear();
|
||||
if (collectParams) collectParameters();
|
||||
|
||||
if (parent==nullptr) return;
|
||||
if (!plotFunction && !simplePlotFunction) return;
|
||||
|
||||
jkqtpSimpleParametricCurveFunctionType func;
|
||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) func=simplePlotFunction;
|
||||
|
||||
jkqtpSimpleParametricCurveFunctionType fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double t) -> QPointF { return plot->transform(func(t)); }, this, std::placeholders::_1);
|
||||
|
||||
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||
data=evaluator.evaluate(tmin, tmax);
|
||||
data=JKQTPSimplyfyLineSegemnts(data, dataCleanupMaxAllowedAngleDegree);
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPXYFunctionLineGraph::draw");
|
||||
#endif
|
||||
if (parent==nullptr) return;
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
if (datastore==nullptr) return;
|
||||
|
||||
//qDebug()<<"start plot\n";
|
||||
createPlotData();
|
||||
//qDebug()<<"plot data created\n";
|
||||
|
||||
drawErrorsBefore(painter);
|
||||
{
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
QPen p=getLinePen(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
|
||||
|
||||
{
|
||||
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
||||
painter.setPen(p);
|
||||
painter.drawPolyline(data);
|
||||
}
|
||||
|
||||
|
||||
if (displaySamplePoints) drawSamplePoints(painter, getLineColor());
|
||||
}
|
||||
drawErrorsAfter(painter);
|
||||
//std::cout<<"plot done\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
double JKQTPXYFunctionLineGraph::getTMin() const
|
||||
bool JKQTPXYFunctionLineGraph::isSimplePlotFunction() const
|
||||
{
|
||||
return tmin;
|
||||
return !static_cast<bool>(plotFunction) && static_cast<bool>(simplePlotFunction);
|
||||
}
|
||||
|
||||
double JKQTPXYFunctionLineGraph::getTMax() const
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec JKQTPXYFunctionLineGraph::buildPlotFunctorSpec()
|
||||
{
|
||||
return tmax;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraph::setTMin(double val)
|
||||
{
|
||||
tmin=val;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraph::setTMax(double val)
|
||||
{
|
||||
tmax=val;
|
||||
}
|
||||
|
||||
QPair<double, double> JKQTPXYFunctionLineGraph::getTRange() const
|
||||
{
|
||||
return QPair<double, double>(tmin,tmax);
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraph::setTRange(double tmin_, double tmax_)
|
||||
{
|
||||
tmin=tmin_;
|
||||
tmax=tmax_;
|
||||
}
|
||||
|
||||
void JKQTPXYFunctionLineGraph::setTRange(const QPair<double, double> &range)
|
||||
{
|
||||
tmin=range.first;
|
||||
tmax=range.second;
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec spec;
|
||||
|
||||
if (!plotFunction && !simplePlotFunction) return spec; // return invalid spec!
|
||||
|
||||
// range over which to evaluate func
|
||||
spec.range_start=tmin;
|
||||
spec.range_end=tmax;
|
||||
|
||||
// the actual function to use
|
||||
if (plotFunction) spec.func=std::bind(plotFunction, std::placeholders::_1, getInternalParams());
|
||||
else if (simplePlotFunction) spec.func=simplePlotFunction;
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
@ -33,62 +33,136 @@
|
||||
#define jkqtpevaluatedparametriccurve_H
|
||||
|
||||
|
||||
/** \brief Base class for line plots where the data is taken from a user supplied function \f$ [x,y]=f(t) \f$
|
||||
* The function is evaluated on a user-specified range \f$ t \in \left[t_\text{min}, t_\text{max}\right] \f$
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* This class uses the intelligent plotting algorithm for functions, implemented in JKQTPAdaptiveFunctionGraphEvaluator.
|
||||
* It starts by sampling the function at minSamples positions. Then each function interval is bisected recursively if
|
||||
* necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
|
||||
* and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added
|
||||
* to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f]
|
||||
* In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
|
||||
* distance to the other points. This helps to prevent beats when sampling periodic functions.
|
||||
*
|
||||
* Finally the obtained data is cleaned up to reduce the amount of points, by deleting a point, when it leads to an
|
||||
* angle between consecutive line-segments of less than dataCleanupMaxAllowedAngleDegree.
|
||||
*
|
||||
*
|
||||
* \see JKQTPXYFunctionLineGraphBase for a concrete implementation with C++-functors as functions
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXYFunctionLineGraphBase: public JKQTPEvaluatedFunctionGraphBase, public JKQTPGraphLineStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXYFunctionLineGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXYFunctionLineGraphBase(JKQTPlotter* parent);
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPXYFunctionLineGraphBase() override;
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
|
||||
/*! \brief type of functions that may be plotted by JKQTPXYFunctionLineGraph
|
||||
\ingroup jkqtplotter_functiongraphs
|
||||
/** \brief returns the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
QPair<double,double> getTRange() const;
|
||||
/** \copydoc tmin */
|
||||
double getTMin() const;
|
||||
/** \copydoc tmax */
|
||||
double getTMax() const;
|
||||
|
||||
This is the type of functions \f$ [x,y]=f(t, \vec{p}) \f$ that may be plottet by JKQTPXYFunctionLineGraph.
|
||||
It is possible to supply parameters \f$ \vec{p} \f$ to the function that
|
||||
influence its result. Parameters are given as a pointer to some memory location. The function has to
|
||||
know on its own how to interpret these.
|
||||
public slots:
|
||||
/** \copydoc tmin */
|
||||
void setTMin(double val);
|
||||
/** \copydoc tmax */
|
||||
void setTMax(double val);
|
||||
/** \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
void setTRange(double tmin_, double tmax_);
|
||||
/** \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
void setTRange(const QPair<double,double>& range);
|
||||
protected:
|
||||
|
||||
/** \brief lower bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 0
|
||||
*
|
||||
* \see getTMin(), getTMax(), setTMin(), setTMax(), setTRange(), getTRange() */
|
||||
double tmin;
|
||||
/** \brief upper bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 1
|
||||
*
|
||||
* \see getTMin(), getTMax(), setTMin(), setTMax(), setTRange(), getTRange() */
|
||||
double tmax;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \brief type of functions that may be plotted by JKQTPXYFunctionLineGraph
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* This is the type of functions \f$ [x,y]=f(t, \vec{p}) \f$ that may be plottet by JKQTPXYFunctionLineGraph.
|
||||
* It is possible to supply parameters \f$ \vec{p} \f$ to the function that
|
||||
* influence its result. Parameters are given as a pointer to some memory location. The function has to
|
||||
* know on its own how to interpret these.
|
||||
*/
|
||||
typedef std::function<QPointF(double, const QVector<double>)> jkqtpParametricCurveFunctionType;
|
||||
|
||||
/*! \brief simplified type of functions (without parameters) that may be plotted by JKQTPXYFunctionLineGraph
|
||||
\ingroup jkqtplotter_functiongraphs
|
||||
|
||||
This is the type of functions \f$ [x,y]=f(t) \f$ that may be plottet by JKQTPXYFunctionLineGraph
|
||||
and JKQTPYFunctionLineGraph.
|
||||
/** \brief simplified type of functions (without parameters) that may be plotted by JKQTPXYFunctionLineGraph
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* This is the type of functions \f$ [x,y]=f(t) \f$ that may be plottet by JKQTPXYFunctionLineGraph
|
||||
* and JKQTPYFunctionLineGraph.
|
||||
*/
|
||||
typedef std::function<QPointF(double)> jkqtpSimpleParametricCurveFunctionType;
|
||||
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ [x,y]=f(t) \f$
|
||||
The function is evaluated on a user-specified range \f$ t \in \left[t_\text{min}, t_\text{max}\right] \f$
|
||||
\ingroup jkqtplotter_functiongraphs
|
||||
|
||||
This class uses the intelligent plotting algorithm for functions, implemented in JKQTPAdaptiveFunctionGraphEvaluator.
|
||||
It starts by sampling the function at minSamples positions. Then each function interval is bisected recursively if
|
||||
necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
|
||||
and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added
|
||||
to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f]
|
||||
In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
|
||||
distance to the other points. This helps to prevent beats when sampling periodic functions.
|
||||
|
||||
Finally the obtained data is cleaned up to reduce the amount of points, by deleting a point, when it leads to an
|
||||
angle between consecutive line-segments of less than dataCleanupMaxAllowedAngleDegree.
|
||||
|
||||
the following image shows a Lissajou's fugure drawn with this function
|
||||
|
||||
\image html plot_evalcurve.png
|
||||
|
||||
The source code for this example is:
|
||||
\code
|
||||
JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot);
|
||||
func1->setPlotFunctionFunctor([](double t) -> QPointF {
|
||||
const double a=5;
|
||||
const double b=4;
|
||||
const double delta=JKQTPSTATISTICS_PI/4.0;
|
||||
return QPointF(sin(a*t+delta), sin(b*t));
|
||||
});
|
||||
func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$");
|
||||
\endcode
|
||||
|
||||
\see \ref JKQTPlotterEvalCurves , JKQTPAdaptiveFunctionGraphEvaluator, JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph
|
||||
/** \brief This implements line plots where the data is taken from a user supplied function \f$ [x,y]=f(t) \f$
|
||||
* The function is evaluated on a user-specified range \f$ t \in \left[t_\text{min}, t_\text{max}\right] \f$
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* \see JKQTPXYFunctionLineGraphBase for details on the used plotting algorithm
|
||||
*
|
||||
* The following image shows a Lissajou's fugure drawn with this function
|
||||
*
|
||||
* \image html plot_evalcurve.png
|
||||
*
|
||||
* The source code for this example is:
|
||||
* \code
|
||||
* JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot);
|
||||
* // here we define the C++-functor for [x,y]=f(t)
|
||||
* func1->setPlotFunctionFunctor([](double t) -> QPointF {
|
||||
* const double a=5;
|
||||
* const double b=4;
|
||||
* const double delta=JKQTPSTATISTICS_PI/4.0;
|
||||
* return QPointF(sin(a*t+delta), sin(b*t));
|
||||
* });
|
||||
* // and define the range over which to evaluate
|
||||
* func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
* \endcode
|
||||
*
|
||||
* The source code for the same example, but using functions that also get a parameter vector:
|
||||
* \code
|
||||
* JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot);
|
||||
* // here we define the C++-functor for [x,y]=f(t)
|
||||
* func1->setPlotFunctionFunctor([](double t, const QVector<double>& params) -> QPointF {
|
||||
* return QPointF(3.0*sin(params[0]*t+params[2])+8.0, 3.0*sin(params[1]*t));
|
||||
* });
|
||||
* // now we define the 3 parameters of the function
|
||||
* // parameters are a, b, delta, as in the example above (in that order)
|
||||
* func1->setParamsV(5, 4, JKQTPSTATISTICS_PI/4.0);
|
||||
* // and define the range over which to evaluate
|
||||
* func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI);
|
||||
* \endcode
|
||||
*
|
||||
* \see \ref JKQTPlotterEvalCurves , JKQTPAdaptiveFunctionGraphEvaluator, JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXYFunctionLineGraph: public JKQTPEvaluatedFunctionWithParamsGraphBase, public JKQTPGraphLineStyleMixin {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXYFunctionLineGraph: public JKQTPXYFunctionLineGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@ -117,60 +191,44 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXYFunctionLineGraph: public JKQTPEvaluatedFunc
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPXYFunctionLineGraph() override;
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
/** \brief sets a functor to be plotted
|
||||
*
|
||||
* \see plotFunction
|
||||
*/
|
||||
virtual void setPlotFunctionFunctor (jkqtpParametricCurveFunctionType && __value);
|
||||
void setPlotFunctionFunctor (jkqtpParametricCurveFunctionType && __value);
|
||||
/** \brief sets a functor to be plotted
|
||||
*
|
||||
* \see plotFunction
|
||||
*/
|
||||
virtual void setPlotFunctionFunctor (const jkqtpParametricCurveFunctionType & __value);
|
||||
void setPlotFunctionFunctor (const jkqtpParametricCurveFunctionType & __value);
|
||||
/** \brief sets a functor to be plotted
|
||||
*
|
||||
* \see simplePlotFunction
|
||||
*/
|
||||
virtual void setPlotFunctionFunctor (jkqtpSimpleParametricCurveFunctionType && __value);
|
||||
void setPlotFunctionFunctor (jkqtpSimpleParametricCurveFunctionType && __value);
|
||||
/** \brief sets a functor to be plotted
|
||||
*
|
||||
* \see simplePlotFunction
|
||||
*/
|
||||
virtual void setPlotFunctionFunctor (const jkqtpSimpleParametricCurveFunctionType & __value);
|
||||
/*! \copydoc plotFunction */ \
|
||||
virtual jkqtpParametricCurveFunctionType getPlotFunctionFunctor () const;
|
||||
/*! \copydoc simplePlotFunction */ \
|
||||
virtual jkqtpSimpleParametricCurveFunctionType getSimplePlotFunction () const;
|
||||
void setPlotFunctionFunctor (const jkqtpSimpleParametricCurveFunctionType & __value);
|
||||
/** \copydoc plotFunction
|
||||
*
|
||||
* \see isSimplePlotFunction() */
|
||||
jkqtpParametricCurveFunctionType getPlotFunctionFunctor () const;
|
||||
/** \copydoc simplePlotFunction
|
||||
*
|
||||
* \see isSimplePlotFunction() */
|
||||
jkqtpSimpleParametricCurveFunctionType getSimplePlotFunction () const;
|
||||
|
||||
/** \brief returns whether the plot function was defined as a jkqtpSimpleParametricCurveFunctionType (\c true ) or
|
||||
* a jkqtpParametricCurveFunctionType (\c false ) */
|
||||
bool isSimplePlotFunction() const;
|
||||
|
||||
|
||||
/*! \copydoc tmin */
|
||||
double getTMin() const;
|
||||
/*! \copydoc tmax */
|
||||
double getTMax() const;
|
||||
/*! \copydoc tmin */
|
||||
void setTMin(double val);
|
||||
/*! \copydoc tmax */
|
||||
void setTMax(double val);
|
||||
/*! \brief returns the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
QPair<double,double> getTRange() const;
|
||||
/*! \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
void setTRange(double tmin_, double tmax_);
|
||||
/*! \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */
|
||||
void setTRange(const QPair<double,double>& range);
|
||||
protected:
|
||||
/** \brief lower bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 0 */
|
||||
double tmin;
|
||||
/** \brief upper bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 1 */
|
||||
double tmax;
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData( bool collectParams=true) override;
|
||||
/** \copydoc JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec() */
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() override;
|
||||
|
||||
|
||||
/** \brief the function to be plotted */
|
||||
|
@ -27,131 +27,73 @@
|
||||
#include <QElapsedTimer>
|
||||
#include <utility>
|
||||
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(JKQTBasePlotter *parent):
|
||||
JKQTPXFunctionLineGraph(parent)
|
||||
JKQTPParsedFunctionLineGraphBase::JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName_, const QString& function_, JKQTBasePlotter *parent):
|
||||
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase(parent),
|
||||
dependentVariableName(dependentVariableName_),
|
||||
function(function_)
|
||||
{
|
||||
fdata.parser=new JKQTPMathParser();
|
||||
fdata.parser=std::make_shared<JKQTPMathParser>();
|
||||
fdata.node=nullptr;
|
||||
fdata.varcount=0;
|
||||
function="";
|
||||
parameterColumn=-1;
|
||||
setPlotFunctionFunctor(jkqtpPlotFunctionType(std::bind(&JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &fdata)));
|
||||
|
||||
efdata.parser=new JKQTPMathParser();
|
||||
|
||||
efdata.parser=std::make_shared<JKQTPMathParser>();
|
||||
efdata.node=nullptr;
|
||||
efdata.varcount=0;
|
||||
errorFunction="";
|
||||
errorParameterColumn=-1;
|
||||
setErrorPlotFunction(jkqtpPlotFunctionType(std::bind(&JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &efdata)));
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(JKQTPlotter *parent):
|
||||
JKQTPXParsedFunctionLineGraph(parent->getPlotter())
|
||||
JKQTPParsedFunctionLineGraphBase::JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, const QString& function, JKQTPlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(dependentVariableName, function, parent->getPlotter())
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::~JKQTPXParsedFunctionLineGraph()
|
||||
JKQTPParsedFunctionLineGraphBase::JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, JKQTBasePlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(dependentVariableName, QString(), parent)
|
||||
{
|
||||
if (fdata.node) delete fdata.node;
|
||||
delete fdata.parser;
|
||||
if (efdata.node) delete efdata.node;
|
||||
delete efdata.parser;
|
||||
}
|
||||
|
||||
void JKQTPXParsedFunctionLineGraph::setFunction(const QString &__value)
|
||||
JKQTPParsedFunctionLineGraphBase::JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, JKQTPlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(dependentVariableName, QString(), parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
JKQTPParsedFunctionLineGraphBase::~JKQTPParsedFunctionLineGraphBase()
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPParsedFunctionLineGraphBase::setFunction(const QString &__value)
|
||||
{
|
||||
this->function = __value;
|
||||
}
|
||||
|
||||
QString JKQTPXParsedFunctionLineGraph::getFunction() const
|
||||
QString JKQTPParsedFunctionLineGraphBase::getFunction() const
|
||||
{
|
||||
return this->function;
|
||||
}
|
||||
|
||||
void JKQTPXParsedFunctionLineGraph::setErrorFunction(const QString &__value)
|
||||
void JKQTPParsedFunctionLineGraphBase::setErrorFunction(const QString &__value)
|
||||
{
|
||||
this->errorFunction = __value;
|
||||
}
|
||||
|
||||
QString JKQTPXParsedFunctionLineGraph::getErrorFunction() const
|
||||
QString JKQTPParsedFunctionLineGraphBase::getErrorFunction() const
|
||||
{
|
||||
return this->errorFunction;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPXParsedFunctionLineGraph::createPlotData(bool /*collectParams*/)
|
||||
QString JKQTPParsedFunctionLineGraphBase::getDependentVariableName() const
|
||||
{
|
||||
collectParameters();
|
||||
|
||||
//QElapsedTimer timer;
|
||||
//timer.start();
|
||||
for (int i=0; i<fdata.varcount; i++) {
|
||||
fdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
fdata.varcount=0;
|
||||
try {
|
||||
for (const auto& p: getInternalParams()) {
|
||||
fdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(fdata.varcount+1), p);
|
||||
fdata.varcount=fdata.varcount+1;
|
||||
}
|
||||
fdata.parser->addVariableDouble(std::string("x"), 0.0);
|
||||
if (fdata.node) delete fdata.node;
|
||||
//qint64 t=timer.elapsed();
|
||||
|
||||
|
||||
//qDebug()<<"createPlotData(): adding variables: "<<t<<"ms";
|
||||
fdata.node=fdata.parser->parse(function.toStdString());
|
||||
//qDebug()<<"createPlotData(): parsing: "<<timer.elapsed()-t<<"ms";
|
||||
} catch(std::exception& E) {
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
//qint64 t0=timer.elapsed();
|
||||
for (int i=0; i<efdata.varcount; i++) {
|
||||
efdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
efdata.varcount=0;
|
||||
try {
|
||||
QVector<double>* errorParameters=static_cast<QVector<double>*>(errorParams);
|
||||
if (errorParameters) {
|
||||
for (int i=0; i<errorParameters->size(); i++) {
|
||||
efdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(efdata.varcount+1), errorParameters->at(i));
|
||||
efdata.varcount=efdata.varcount+1;
|
||||
}
|
||||
}
|
||||
efdata.parser->addVariableDouble(std::string("x"), 0.0);
|
||||
if (efdata.node) delete efdata.node;
|
||||
//qint64 t=timer.elapsed();
|
||||
//qDebug()<<"createPlotData(): adding variables: "<<t-t0<<"ms";
|
||||
efdata.node=efdata.parser->parse(errorFunction.toStdString());
|
||||
//qDebug()<<"createPlotData(): parsing: "<<timer.elapsed()-t<<"ms";
|
||||
} catch(std::exception& /*E*/) {
|
||||
//qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
setPlotFunctionFunctor(jkqtpPlotFunctionType(std::bind(&JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &fdata)));
|
||||
setErrorPlotFunction(jkqtpPlotFunctionType(std::bind(&JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &efdata)));
|
||||
|
||||
//qint64 t=timer.elapsed();
|
||||
JKQTPXFunctionLineGraph::createPlotData(false);
|
||||
//qDebug()<<"createPlotData(): JKQTPXFunctionLineGraph::createPlotData(): "<<timer.elapsed()-t<<"ms";
|
||||
|
||||
/*int count=0;
|
||||
doublePair* d=data;
|
||||
while (d!=nullptr) {
|
||||
count++;
|
||||
d=d->next;
|
||||
}
|
||||
qDebug()<<"refined to "<<count<<" daatapoints";*/
|
||||
return dependentVariableName;
|
||||
}
|
||||
|
||||
|
||||
double JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction(double x, const QVector<double>& /*data*/, JKQTPXParsedFunctionLineGraphFunctionData *fdata) {
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunctionData* d=fdata;//static_cast<JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunctionData*>(data);
|
||||
double JKQTPParsedFunctionLineGraphBase::evaluateParsedFunction(double t, ParsedFunctionLineGraphFunctionData *fdata) {
|
||||
JKQTPParsedFunctionLineGraphBase::ParsedFunctionLineGraphFunctionData* d=fdata;//static_cast<JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunctionData*>(data);
|
||||
if (d && d->parser && d->node) {
|
||||
try {
|
||||
d->parser->addVariableDouble("x", x);
|
||||
d->parser->addVariableDouble(d->dependentVariableName.toStdString(), t);
|
||||
JKQTPMathParser::jkmpResult r=d->node->evaluate();
|
||||
|
||||
if (r.isValid) {
|
||||
@ -162,8 +104,8 @@ double JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction(doub
|
||||
}
|
||||
}
|
||||
} catch(std::exception& E) {
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
/*ok= QMessageBox::critical(this, tr("QuickFit-table"),
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
/*ok= QMessageBox::critical(this, tr("QuickFit-table"),
|
||||
tr("An error occured while parsing the expression '%1' in cell (row, column)=(%3, %4):\n%2\n\n\"OK\" will still go on evaluating\n\"Cancel\" will cancel evaluation for the rest of the cells.").arg(dlgMathExpression->getExpression()).arg(E.what()).arg(row).arg(column),
|
||||
QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Ok)==QMessageBox::Ok;*/
|
||||
|
||||
@ -186,79 +128,152 @@ double JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunction(doub
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(JKQTBasePlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("x"), parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(JKQTPlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("x"), parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(const QString& function, JKQTBasePlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("x"), function, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraph(const QString& function, JKQTPlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("x"), function, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPXParsedFunctionLineGraph::~JKQTPXParsedFunctionLineGraph()
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPXParsedFunctionLineGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
drawXGraph(painter);
|
||||
}
|
||||
|
||||
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec JKQTPXParsedFunctionLineGraph::buildPlotFunctorSpec()
|
||||
{
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec spec;
|
||||
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
for (int i=0; i<fdata.varcount; i++) {
|
||||
fdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
fdata.varcount=0;
|
||||
try {
|
||||
for (const auto& p: getInternalParams()) {
|
||||
fdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(fdata.varcount+1), p);
|
||||
fdata.varcount=fdata.varcount+1;
|
||||
}
|
||||
fdata.dependentVariableName=getDependentVariableName();
|
||||
fdata.parser->addVariableDouble(getDependentVariableName().toStdString(), 0.0);
|
||||
fdata.node=std::shared_ptr<JKQTPMathParser::jkmpNode>(fdata.parser->parse(function.toStdString()));
|
||||
} catch(std::exception& E) {
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
jkqtpSimplePlotFunctionType plotFunction=std::bind(&JKQTPXParsedFunctionLineGraph::evaluateParsedFunction, std::placeholders::_1, &fdata);
|
||||
// the actual function to use
|
||||
spec.func=std::bind([=](double x) -> QPointF { return QPointF(0, plotFunction(x)); }, std::placeholders::_1);
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::function<QPointF (double)> JKQTPXParsedFunctionLineGraph::buildErrorFunctorSpec()
|
||||
{
|
||||
std::function<QPointF (double)> spec;
|
||||
|
||||
for (int i=0; i<efdata.varcount; i++) {
|
||||
efdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
efdata.varcount=0;
|
||||
try {
|
||||
for (const auto& p: getInternalErrorParams()) {
|
||||
efdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(efdata.varcount+1), p);
|
||||
efdata.varcount=efdata.varcount+1;
|
||||
}
|
||||
efdata.dependentVariableName=getDependentVariableName();
|
||||
efdata.parser->addVariableDouble(getDependentVariableName().toStdString(), 0.0);
|
||||
efdata.node=std::shared_ptr<JKQTPMathParser::jkmpNode>(efdata.parser->parse(errorFunction.toStdString()));
|
||||
} catch(std::exception& /*E*/) {
|
||||
//qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
jkqtpSimplePlotFunctionType errorPlotFunction=std::bind(&JKQTPXParsedFunctionLineGraph::evaluateParsedFunction, std::placeholders::_1, &efdata);
|
||||
// the actual function to use
|
||||
spec=std::bind([=](double x) -> QPointF { return QPointF(0, errorPlotFunction(x)); }, std::placeholders::_1);
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraph(JKQTBasePlotter *parent):
|
||||
JKQTPYFunctionLineGraph(parent)
|
||||
JKQTPParsedFunctionLineGraphBase(QString("y"), parent)
|
||||
{
|
||||
fdata.parser=new JKQTPMathParser();
|
||||
fdata.node=nullptr;
|
||||
fdata.varcount=0;
|
||||
function="";
|
||||
parameterColumn=-1;
|
||||
setPlotFunctionFunctor(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &fdata)));
|
||||
|
||||
efdata.parser=new JKQTPMathParser();
|
||||
efdata.node=nullptr;
|
||||
efdata.varcount=0;
|
||||
errorFunction="";
|
||||
errorParameterColumn=-1;
|
||||
setErrorPlotFunction(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &efdata)));
|
||||
}
|
||||
|
||||
JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraph(JKQTPlotter *parent):
|
||||
JKQTPYFunctionLineGraph(parent)
|
||||
JKQTPParsedFunctionLineGraphBase(QString("y"), parent)
|
||||
{
|
||||
fdata.parser=new JKQTPMathParser();
|
||||
fdata.node=nullptr;
|
||||
fdata.varcount=0;
|
||||
function="";
|
||||
parameterColumn=-1;
|
||||
setPlotFunctionFunctor(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &fdata)));
|
||||
}
|
||||
|
||||
efdata.parser=new JKQTPMathParser();
|
||||
efdata.node=nullptr;
|
||||
efdata.varcount=0;
|
||||
errorFunction="";
|
||||
errorParameterColumn=-1;
|
||||
setErrorPlotFunction(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &efdata)));
|
||||
JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraph(const QString& function, JKQTBasePlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("y"), function, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraph(const QString& function, JKQTPlotter *parent):
|
||||
JKQTPParsedFunctionLineGraphBase(QString("y"), function, parent)
|
||||
{
|
||||
}
|
||||
|
||||
JKQTPYParsedFunctionLineGraph::~JKQTPYParsedFunctionLineGraph()
|
||||
{
|
||||
if (fdata.node) delete fdata.node;
|
||||
delete fdata.parser;
|
||||
if (efdata.node) delete efdata.node;
|
||||
delete efdata.parser;
|
||||
}
|
||||
|
||||
void JKQTPYParsedFunctionLineGraph::setFunction(const QString &__value)
|
||||
void JKQTPYParsedFunctionLineGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
this->function = __value;
|
||||
drawYGraph(painter);
|
||||
}
|
||||
|
||||
QString JKQTPYParsedFunctionLineGraph::getFunction() const
|
||||
{
|
||||
return this->function;
|
||||
}
|
||||
|
||||
void JKQTPYParsedFunctionLineGraph::setErrorFunction(const QString &__value)
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec JKQTPYParsedFunctionLineGraph::buildPlotFunctorSpec()
|
||||
{
|
||||
this->errorFunction = __value;
|
||||
}
|
||||
JKQTPEvaluatedFunctionGraphBase::PlotFunctorSpec spec;
|
||||
|
||||
QString JKQTPYParsedFunctionLineGraph::getErrorFunction() const
|
||||
{
|
||||
return this->errorFunction;
|
||||
}
|
||||
if (parent==nullptr) return spec; // return an invalid PlotFunctorSpec
|
||||
|
||||
void JKQTPYParsedFunctionLineGraph::createPlotData(bool /*collectParams*/)
|
||||
{
|
||||
collectParameters();
|
||||
|
||||
//QElapsedTimer timer;
|
||||
//timer.start();
|
||||
for (int i=0; i<fdata.varcount; i++) {
|
||||
fdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
@ -268,82 +283,47 @@ void JKQTPYParsedFunctionLineGraph::createPlotData(bool /*collectParams*/)
|
||||
fdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(fdata.varcount+1), p);
|
||||
fdata.varcount=fdata.varcount+1;
|
||||
}
|
||||
fdata.parser->addVariableDouble(std::string("x"), 0.0);
|
||||
fdata.parser->addVariableDouble(std::string("y"), 0.0);
|
||||
if (fdata.node) delete fdata.node;
|
||||
//qint64 t=timer.elapsed();
|
||||
|
||||
|
||||
//qDebug()<<"createPlotData(): adding variables: "<<t<<"ms";
|
||||
fdata.node=fdata.parser->parse(function.toStdString());
|
||||
//qDebug()<<"createPlotData(): parsing: "<<timer.elapsed()-t<<"ms";
|
||||
fdata.dependentVariableName=getDependentVariableName();
|
||||
fdata.parser->addVariableDouble(getDependentVariableName().toStdString(), 0.0);
|
||||
fdata.node=std::shared_ptr<JKQTPMathParser::jkmpNode>(fdata.parser->parse(function.toStdString()));
|
||||
} catch(std::exception& E) {
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
//qint64 t0=timer.elapsed();
|
||||
jkqtpSimplePlotFunctionType plotFunction=std::bind(&JKQTPXParsedFunctionLineGraph::evaluateParsedFunction, std::placeholders::_1, &fdata);
|
||||
// the actual function to use
|
||||
spec.func=std::bind([=](double y) -> QPointF { return QPointF(plotFunction(y), 0); }, std::placeholders::_1);
|
||||
|
||||
// range over which to evaluate func
|
||||
spec.range_start=parent->getXMin();
|
||||
spec.range_end=parent->getXMax();
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
std::function<QPointF (double)> JKQTPYParsedFunctionLineGraph::buildErrorFunctorSpec()
|
||||
{
|
||||
std::function<QPointF (double)> spec;
|
||||
|
||||
for (int i=0; i<efdata.varcount; i++) {
|
||||
efdata.parser->deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
|
||||
}
|
||||
efdata.varcount=0;
|
||||
try {
|
||||
QVector<double>* errorParameters=static_cast<QVector<double>*>(errorParams);
|
||||
if (errorParameters) {
|
||||
for (int i=0; i<errorParameters->size(); i++) {
|
||||
efdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(efdata.varcount+1), errorParameters->at(i));
|
||||
efdata.varcount=efdata.varcount+1;
|
||||
}
|
||||
for (const auto& p: getInternalErrorParams()) {
|
||||
efdata.parser->addVariableDouble(std::string("p")+jkqtp_inttostr(efdata.varcount+1), p);
|
||||
efdata.varcount=efdata.varcount+1;
|
||||
}
|
||||
efdata.parser->addVariableDouble(std::string("x"), 0.0);
|
||||
efdata.parser->addVariableDouble(std::string("y"), 0.0);
|
||||
if (efdata.node) delete efdata.node;
|
||||
//qint64 t=timer.elapsed();
|
||||
//qDebug()<<"createPlotData(): adding variables: "<<t-t0<<"ms";
|
||||
efdata.node=efdata.parser->parse(errorFunction.toStdString());
|
||||
//qDebug()<<"createPlotData(): parsing: "<<timer.elapsed()-t<<"ms";
|
||||
} catch(std::exception& E) {
|
||||
qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
efdata.dependentVariableName=getDependentVariableName();
|
||||
efdata.parser->addVariableDouble(getDependentVariableName().toStdString(), 0.0);
|
||||
efdata.node=std::shared_ptr<JKQTPMathParser::jkmpNode>(efdata.parser->parse(errorFunction.toStdString()));
|
||||
} catch(std::exception& /*E*/) {
|
||||
//qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
}
|
||||
|
||||
setPlotFunctionFunctor(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &fdata)));
|
||||
setErrorPlotFunction(jkqtpPlotFunctionType(std::bind(&JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction, std::placeholders::_1, std::placeholders::_2, &efdata)));
|
||||
|
||||
//qint64 t=timer.elapsed();
|
||||
JKQTPYFunctionLineGraph::createPlotData(false);
|
||||
//qDebug()<<"createPlotData(): JKQTPYFunctionLineGraph::createPlotData(): "<<timer.elapsed()-t<<"ms";
|
||||
|
||||
/*int count=0;
|
||||
doublePair* d=data;
|
||||
while (d!=nullptr) {
|
||||
count++;
|
||||
d=d->next;
|
||||
}
|
||||
qDebug()<<"refined to "<<count<<" daatapoints";*/
|
||||
}
|
||||
|
||||
double JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunction(double x, const QVector<double> & /*data*/, JKQTPYParsedFunctionLineGraphFunctionData *fdata) {
|
||||
JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunctionData* d=fdata;//static_cast<JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunctionData*>(data);
|
||||
if (d && d->parser && d->node) {
|
||||
try {
|
||||
d->parser->addVariableDouble("x", x);
|
||||
d->parser->addVariableDouble("y", x);
|
||||
JKQTPMathParser::jkmpResult r=d->node->evaluate();
|
||||
|
||||
if (r.isValid) {
|
||||
if (r.type==JKQTPMathParser::jkmpBool) {
|
||||
return r.boolean?1.0:0.0;
|
||||
} else if (r.type==JKQTPMathParser::jkmpDouble) {
|
||||
return r.num;
|
||||
}
|
||||
}
|
||||
} catch(std::exception& /*E*/) {
|
||||
//qDebug()<<QString("parser error: %1").arg(E.what());
|
||||
/*ok= QMessageBox::critical(this, tr("QuickFit-table"),
|
||||
tr("An error occured while parsing the expression '%1' in cell (row, column)=(%3, %4):\n%2\n\n\"OK\" will still go on evaluating\n\"Cancel\" will cancel evaluation for the rest of the cells.").arg(dlgMathExpression->getExpression()).arg(E.what()).arg(row).arg(column),
|
||||
QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Ok)==QMessageBox::Ok;*/
|
||||
|
||||
}
|
||||
}
|
||||
return NAN;
|
||||
jkqtpSimplePlotFunctionType errorPlotFunction=std::bind(&JKQTPXParsedFunctionLineGraph::evaluateParsedFunction, std::placeholders::_1, &efdata);
|
||||
// the actual function to use
|
||||
spec=std::bind([=](double y) -> QPointF { return QPointF(errorPlotFunction(y), 0); }, std::placeholders::_1);
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
@ -34,6 +34,74 @@ class JKQTBasePlotter;
|
||||
class JKQTPlotter;
|
||||
|
||||
|
||||
/** \brief extends JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase with the capabilities to define functions from strings
|
||||
* that are parsed by JKQTPMathParser
|
||||
* \ingroup jkqtplotter_functiongraphs
|
||||
*
|
||||
* \see JKQTPXParsedFunctionLineGraph and JKQTPYParsedFunctionLineGraph for a concrete implementation, see also JKQTPMathParser
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPParsedFunctionLineGraphBase: public JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, JKQTPlotter* parent);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, const QString& function, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPParsedFunctionLineGraphBase(const QString& dependentVariableName, const QString& function, JKQTPlotter* parent);
|
||||
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPParsedFunctionLineGraphBase() override;
|
||||
|
||||
/** \copydoc function */
|
||||
QString getFunction() const;
|
||||
|
||||
/** \copydoc errorFunction */
|
||||
QString getErrorFunction() const;
|
||||
/** \copydoc dependentVariableName */
|
||||
QString getDependentVariableName() const;
|
||||
|
||||
public slots:
|
||||
/** \copydoc errorFunction */
|
||||
void setErrorFunction(const QString & __value);
|
||||
/** \copydoc function */
|
||||
void setFunction(const QString & __value);
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief INTERNAL data structure combining a JKQTPMathParser and a JKQTPMathParser::jkmpNode
|
||||
*/
|
||||
struct ParsedFunctionLineGraphFunctionData {
|
||||
std::shared_ptr<JKQTPMathParser> parser;
|
||||
std::shared_ptr<JKQTPMathParser::jkmpNode> node;
|
||||
int varcount;
|
||||
QString dependentVariableName;
|
||||
};
|
||||
|
||||
/** \brief nache of the dependent variable (e.g. x for a function f(x) ) */
|
||||
QString dependentVariableName;
|
||||
|
||||
/** \brief the function to be evaluated for the plot. Use \c x as the free variable, e.g. \c "x^2+2" */
|
||||
QString function;
|
||||
/** \brief parser data structure for function */
|
||||
ParsedFunctionLineGraphFunctionData fdata;
|
||||
|
||||
/** \brief the function to be evaluated to add error indicators to the graph. This function is evaluated to an error for every x. Use \c x as the free variable, e.g. \c "x^2+2". */
|
||||
QString errorFunction;
|
||||
/** \brief parser data structure for errorFunction */
|
||||
ParsedFunctionLineGraphFunctionData efdata;
|
||||
|
||||
/** \brief implements the actual plot function */
|
||||
static double evaluateParsedFunction(double x, ParsedFunctionLineGraphFunctionData* fdata) ;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$ The function is defined as a string and parsed by JKMathParser
|
||||
\ingroup jkqtplotter_parsedFgraphs
|
||||
@ -45,7 +113,7 @@ class JKQTPlotter;
|
||||
|
||||
\see \ref JKQTPlotterParsedFunctionPlot, JKQTPMathParser
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPXFunctionLineGraph {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPParsedFunctionLineGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@ -55,49 +123,26 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPXFunctio
|
||||
/** \brief class constructor */
|
||||
JKQTPXParsedFunctionLineGraph(JKQTPlotter* parent);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPXParsedFunctionLineGraph(const QString& function, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPXParsedFunctionLineGraph(const QString& function, JKQTPlotter* parent);
|
||||
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPXParsedFunctionLineGraph() override;
|
||||
|
||||
/*! \copydoc function */
|
||||
void setFunction(const QString & __value);
|
||||
/*! \copydoc function */
|
||||
QString getFunction() const;
|
||||
|
||||
/*! \copydoc errorFunction */
|
||||
void setErrorFunction(const QString & __value);
|
||||
/*! \copydoc errorFunction */
|
||||
QString getErrorFunction() const;
|
||||
|
||||
/** \brief INTERNAL data structure
|
||||
* \internal
|
||||
*/
|
||||
struct JKQTPXParsedFunctionLineGraphFunctionData {
|
||||
JKQTPMathParser* parser;
|
||||
JKQTPMathParser::jkmpNode* node;
|
||||
int varcount;
|
||||
};
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
|
||||
protected:
|
||||
/** \brief the function to be evaluated for the plot. Use \c x as the free variable, e.g. \c "x^2+2" */
|
||||
QString function;
|
||||
JKQTPXParsedFunctionLineGraphFunctionData fdata;
|
||||
|
||||
/** \brief the function to be evaluated to add error indicators to the graph. This function is evaluated to an error for every x. Use \c x as the free variable, e.g. \c "x^2+2". */
|
||||
QString errorFunction;
|
||||
JKQTPXParsedFunctionLineGraphFunctionData efdata;
|
||||
|
||||
// hide functions that should not be used in this class!
|
||||
using JKQTPXFunctionLineGraph::setPlotFunctionFunctor;
|
||||
using JKQTPXFunctionLineGraph::setParams;
|
||||
using JKQTPXFunctionLineGraph::setErrorPlotFunction;
|
||||
using JKQTPXFunctionLineGraph::setErrorParams;
|
||||
/** \copydoc JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec() */
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() override;
|
||||
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData(bool collectParams=true) override;
|
||||
|
||||
/** \brief implements the actual plot function */
|
||||
static double JKQTPXParsedFunctionLineGraphFunction(double x, const QVector<double> &data, JKQTPXParsedFunctionLineGraphFunctionData* fdata) ;
|
||||
/** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
|
||||
virtual std::function<QPointF(double)> buildErrorFunctorSpec() override;
|
||||
};
|
||||
|
||||
|
||||
@ -114,7 +159,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPXFunctio
|
||||
\see \ref JKQTPlotterParsedFunctionPlot, JKQTPMathParser
|
||||
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPYParsedFunctionLineGraph: public JKQTPYFunctionLineGraph {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPYParsedFunctionLineGraph: public JKQTPParsedFunctionLineGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@ -124,47 +169,25 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPYParsedFunctionLineGraph: public JKQTPYFunctio
|
||||
/** \brief class constructor */
|
||||
JKQTPYParsedFunctionLineGraph(JKQTPlotter* parent);
|
||||
|
||||
/** \brief class constructor */
|
||||
JKQTPYParsedFunctionLineGraph(const QString& function, JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPYParsedFunctionLineGraph(const QString& function, JKQTPlotter* parent);
|
||||
|
||||
|
||||
/** \brief class destructor */
|
||||
virtual ~JKQTPYParsedFunctionLineGraph() override;
|
||||
|
||||
/*! \copydoc function */
|
||||
void setFunction(const QString & __value);
|
||||
/*! \copydoc function */
|
||||
QString getFunction() const;
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
|
||||
/*! \copydoc errorFunction */
|
||||
void setErrorFunction(const QString & __value);
|
||||
/*! \copydoc errorFunction */
|
||||
QString getErrorFunction() const;
|
||||
|
||||
/** \brief INTERNAL data structure
|
||||
* \internal
|
||||
*/
|
||||
struct JKQTPYParsedFunctionLineGraphFunctionData {
|
||||
JKQTPMathParser* parser;
|
||||
JKQTPMathParser::jkmpNode* node;
|
||||
int varcount;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** \brief the function to be evaluated for the plot. Use \c x as the free variable, e.g. \c "x^2+2" */
|
||||
QString function;
|
||||
JKQTPYParsedFunctionLineGraphFunctionData fdata;
|
||||
|
||||
/** \brief the function to be evaluated to add error indicators to the graph. This function is evaluated to an error for every x. Use \c x as the free variable, e.g. \c "x^2+2". */
|
||||
QString errorFunction;
|
||||
JKQTPYParsedFunctionLineGraphFunctionData efdata;
|
||||
/** \copydoc JKQTPEvaluatedFunctionGraphBase::buildPlotFunctorSpec() */
|
||||
virtual PlotFunctorSpec buildPlotFunctorSpec() override;
|
||||
|
||||
// hide functions that should not be used in this class!
|
||||
using JKQTPXFunctionLineGraph::setPlotFunctionFunctor;
|
||||
using JKQTPXFunctionLineGraph::setParams;
|
||||
using JKQTPXFunctionLineGraph::setErrorPlotFunction;
|
||||
using JKQTPXFunctionLineGraph::setErrorParams;
|
||||
|
||||
/** \brief fill the data array with data from the function plotFunction */
|
||||
virtual void createPlotData(bool collectParams=true) override;
|
||||
/** \brief implements the actual plot function */
|
||||
static double JKQTPYParsedFunctionLineGraphFunction(double x, const QVector<double>& data, JKQTPYParsedFunctionLineGraphFunctionData* fdata);
|
||||
/** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
|
||||
virtual std::function<QPointF(double)> buildErrorFunctorSpec() override;
|
||||
};
|
||||
#endif // jkqtpgraphsparsedfunction_H
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 127 KiB |
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 22 KiB |
Loading…
Reference in New Issue
Block a user