diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox
index 5b55d92c04..eeb0b137b5 100644
--- a/doc/dox/whatsnew.dox
+++ b/doc/dox/whatsnew.dox
@@ -23,6 +23,7 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
removed the usage of some deprecated functions and objects (e.g. QMatrix)
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)
improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)
+ improved: reworked class hirarchy of parsed function plots and declared several setters as slots.
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)
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
new: a new graph class JKQTPXYFunctionLineGraph draws parametric 2D curves ( \f$ [x,y] = f(t) \f$ ), see \ref JKQTPlotterEvalCurves for an example
diff --git a/examples/evalcurve/README.md b/examples/evalcurve/README.md
index a0ac644885..5106946a14 100644
--- a/examples/evalcurve/README.md
+++ b/examples/evalcurve/README.md
@@ -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& 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) .
diff --git a/examples/evalcurve/evalcurve.cpp b/examples/evalcurve/evalcurve.cpp
index 11c82eed45..c22db16202 100644
--- a/examples/evalcurve/evalcurve.cpp
+++ b/examples/evalcurve/evalcurve.cpp
@@ -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& 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();
diff --git a/examples/functionplot/README.md b/examples/functionplot/README.md
index e854a10b58..bd4367ce52 100644
--- a/examples/functionplot/README.md
+++ b/examples/functionplot/README.md
@@ -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) .
+
+
diff --git a/lib/jkqtcommon/jkqtpmathtools.h b/lib/jkqtcommon/jkqtpmathtools.h
index b8cd839d32..36d544165b 100644
--- a/lib/jkqtcommon/jkqtpmathtools.h
+++ b/lib/jkqtcommon/jkqtpmathtools.h
@@ -290,12 +290,22 @@ inline T jkqtp_sqr(const T& v) {
\ingroup jkqtptools_math_basic
*/
-template
-inline T jkqtp_pow4(T x) {
+ template
+ 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
+inline T jkqtp_pow5(T x) {
+ const T xx=x*x;
+ return xx*xx*x;
+}
+
/*! \brief cube of a number
\ingroup jkqtptools_math_basic
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.cpp b/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.cpp
index 4f25373fee..e676f6f8e0 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.cpp
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.cpp
@@ -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: "<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 ¶ms, const QString &title_, JKQTBasePlotter *parent):
- JKQTPXFunctionLineGraph(parent)
-{
- title=title_;
- functionType=type;
- setParams(params);
- data.clear();
-}
-
-JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector ¶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 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(datastore->getRows(errorParameterColumn));
-
- for (int i=imin; iget(errorParameterColumn,i);
- ierrorparams<=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) = ( "<(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 ¶ms, const QString &title_, JKQTBasePlotter *parent):
- JKQTPXFunctionLineGraph(type, params, title_, parent)
-{
-}
-
-JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector ¶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) = ( "<(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 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 &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(__value);
-}
-
-void JKQTPXFunctionLineGraph::setErrorLineColor(const QColor &__value)
+JKQTPFunctorLineGraphBase::JKQTPFunctorLineGraphBase(JKQTPFunctorLineGraphBase::SpecialFunction type, const QVector ¶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 ¶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& 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& param) {
+ else if (function==JKQTPFunctorLineGraphBase::Exponential) setPlotFunctionFunctor([](double x, const QVector& 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& param) {
+ else if (function==JKQTPFunctorLineGraphBase::PowerLaw) setPlotFunctionFunctor([](double x, const QVector& 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 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(plotFunction) && static_cast(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 ¶ms, const QString &title_, JKQTBasePlotter *parent):
+ JKQTPFunctorLineGraphBase(type, params, title_, parent)
+{
+}
+
+JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector ¶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& 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 JKQTPXFunctionLineGraph::buildErrorFunctorSpec()
+{
+ std::function 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& 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 ¶ms, const QString &title_, JKQTBasePlotter *parent):
+ JKQTPFunctorLineGraphBase(type, params, title_, parent)
+{
+}
+
+JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector ¶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& 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 JKQTPYFunctionLineGraph::buildErrorFunctorSpec()
+{
+ std::function 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& 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;
+}
+
+
+
+
+
+
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.h b/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.h
index 246227409c..970a04f544 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.h
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedfunction.h
@@ -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&)> jkqtpPlotFunctionT
typedef std::function 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 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 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 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 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& params, const QString& title, JKQTBasePlotter* parent);
+ JKQTPFunctorLineGraphBase(SpecialFunction type, const QVector& params, const QString& title, JKQTBasePlotter* parent);
/** \brief class constructor */
- JKQTPXFunctionLineGraph(SpecialFunction type, const QVector& params, const QString& title, JKQTPlotter* parent);
+ JKQTPFunctorLineGraphBase(SpecialFunction type, const QVector& 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 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& 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 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& params, const QString& title, JKQTBasePlotter* parent);
+ /** \brief class constructor */
+ JKQTPXFunctionLineGraph(SpecialFunction type, const QVector& 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 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 buildErrorFunctorSpec() override;
};
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.cpp b/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.cpp
index 103362b109..d46a06a1fb 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.cpp
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.cpp
@@ -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 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 ¶ms)
+void JKQTPEvaluatedFunctionGraphBase::setParams(const QVector ¶ms)
{
iparams=params;
}
-void JKQTPEvaluatedFunctionWithParamsGraphBase::setCopiedParams(const double *params, int N)
+void JKQTPEvaluatedFunctionGraphBase::setCopiedParams(const double *params, int N)
{
QVector v;
for (int i=0; i p;
p< p;
p< p;
p< p;
p< p;
p<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(__value);
}
-QVector JKQTPEvaluatedFunctionWithParamsGraphBase::getInternalParams() const {
+const QVector& JKQTPEvaluatedFunctionGraphBase::getInternalParams() const {
return iparams;
}
-bool JKQTPEvaluatedFunctionWithParamsGraphBase::usesColumn(int c) const
+QVector &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(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& JKQTPEvaluatedFunctionWithErrorsGraphBase::getInternalErrorParams() const {
+ return ierrorparams;
+}
+
+QVector& JKQTPEvaluatedFunctionWithErrorsGraphBase::getInternalErrorParams() {
+ return ierrorparams;
+}
+
+bool JKQTPEvaluatedFunctionWithErrorsGraphBase::usesColumn(int c) const
+{
+ return JKQTPEvaluatedFunctionGraphBase::usesColumn(c)||(c==errorParameterColumn);
+}
+
+void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParams(const QVector &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(__value);
+}
+
+void JKQTPEvaluatedFunctionWithErrorsGraphBase::setErrorParamsV(double p1)
+{
+ QVector p;
+ p< p;
+ p< p;
+ p< p;
+ p< p;
+ p<=0) {
+ ierrorparams.clear();
+ JKQTPDatastore* datastore=parent->getDatastore();
+ int imin=0;
+ int imax= static_cast(datastore->getRows(errorParameterColumn));
+
+ for (int i=imin; iget(errorParameterColumn,i);
+ ierrorparams<=0 && !JKQTPIsOKFloat(ierrorparams[i])) {
+ ierrorparams.remove(i,1);
+ i--;
+ }
+ }
+}
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.h b/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.h
index 728220b28f..4399cb215c 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.h
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedfunctionbase.h
@@ -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& 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& getInternalParams() const;
+ /** \brief returns the currently set internal parameter vector */
+ QVector& 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 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 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 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 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& 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 getInternalParams() const;
- /** \copydoc parameterColumn */
- int getParameterColumn() const;
+ const QVector& getInternalErrorParams() const;
+ /** \brief returns the currently set internal parameter vector */
+ QVector& 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& 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 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 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 ierrorparams;
};
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp
index df0d57f314..536902eb0b 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp
@@ -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 JKQTPXYFunctionLineGraphBase::getTRange() const
+{
+ return QPair(tmin,tmax);
+}
+
+void JKQTPXYFunctionLineGraphBase::setTRange(double tmin_, double tmax_)
+{
+ tmin=tmin_;
+ tmax=tmax_;
+}
+
+void JKQTPXYFunctionLineGraphBase::setTRange(const QPair &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(plotFunction) && static_cast(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 JKQTPXYFunctionLineGraph::getTRange() const
-{
- return QPair(tmin,tmax);
-}
-
-void JKQTPXYFunctionLineGraph::setTRange(double tmin_, double tmax_)
-{
- tmin=tmin_;
- tmax=tmax_;
-}
-
-void JKQTPXYFunctionLineGraph::setTRange(const QPair &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;
}
diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h
index 6835ead8de..3d25926907 100644
--- a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h
+++ b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h
@@ -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 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& 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)> 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 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& 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 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& 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 */
diff --git a/lib/jkqtplotter/graphs/jkqtpparsedfunction.cpp b/lib/jkqtplotter/graphs/jkqtpparsedfunction.cpp
index 86dd7e8870..df12d830b5 100644
--- a/lib/jkqtplotter/graphs/jkqtpparsedfunction.cpp
+++ b/lib/jkqtplotter/graphs/jkqtpparsedfunction.cpp
@@ -27,131 +27,73 @@
#include
#include
-
-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();
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();
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; ideleteVariable(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: "<parse(function.toStdString());
- //qDebug()<<"createPlotData(): parsing: "<deleteVariable(std::string("p")+jkqtp_inttostr(i+1));
- }
- efdata.varcount=0;
- try {
- QVector* errorParameters=static_cast*>(errorParams);
- if (errorParameters) {
- for (int i=0; isize(); 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: "<parse(errorFunction.toStdString());
- //qDebug()<<"createPlotData(): parsing: "<next;
- }
- qDebug()<<"refined to "<& /*data*/, JKQTPXParsedFunctionLineGraphFunctionData *fdata) {
- JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunctionData* d=fdata;//static_cast(data);
+double JKQTPParsedFunctionLineGraphBase::evaluateParsedFunction(double t, ParsedFunctionLineGraphFunctionData *fdata) {
+ JKQTPParsedFunctionLineGraphBase::ParsedFunctionLineGraphFunctionData* d=fdata;//static_cast(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()<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; ideleteVariable(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(fdata.parser->parse(function.toStdString()));
+ } catch(std::exception& E) {
+ qDebug()< QPointF { return QPointF(0, plotFunction(x)); }, std::placeholders::_1);
+
+ return spec;
+}
+
+std::function JKQTPXParsedFunctionLineGraph::buildErrorFunctorSpec()
+{
+ std::function spec;
+
+ for (int i=0; ideleteVariable(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(efdata.parser->parse(errorFunction.toStdString()));
+ } catch(std::exception& /*E*/) {
+ //qDebug()< 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; ideleteVariable(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: "<parse(function.toStdString());
- //qDebug()<<"createPlotData(): parsing: "<addVariableDouble(getDependentVariableName().toStdString(), 0.0);
+ fdata.node=std::shared_ptr(fdata.parser->parse(function.toStdString()));
} catch(std::exception& E) {
qDebug()< 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 JKQTPYParsedFunctionLineGraph::buildErrorFunctorSpec()
+{
+ std::function spec;
+
for (int i=0; ideleteVariable(std::string("p")+jkqtp_inttostr(i+1));
}
efdata.varcount=0;
try {
- QVector* errorParameters=static_cast*>(errorParams);
- if (errorParameters) {
- for (int i=0; isize(); 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: "<parse(errorFunction.toStdString());
- //qDebug()<<"createPlotData(): parsing: "<addVariableDouble(getDependentVariableName().toStdString(), 0.0);
+ efdata.node=std::shared_ptr(efdata.parser->parse(errorFunction.toStdString()));
+ } catch(std::exception& /*E*/) {
+ //qDebug()<next;
- }
- qDebug()<<"refined to "< & /*data*/, JKQTPYParsedFunctionLineGraphFunctionData *fdata) {
- JKQTPYParsedFunctionLineGraph::JKQTPYParsedFunctionLineGraphFunctionData* d=fdata;//static_cast(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()<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;
}
diff --git a/lib/jkqtplotter/graphs/jkqtpparsedfunction.h b/lib/jkqtplotter/graphs/jkqtpparsedfunction.h
index 9f0b6608a2..86b5a93ec0 100644
--- a/lib/jkqtplotter/graphs/jkqtpparsedfunction.h
+++ b/lib/jkqtplotter/graphs/jkqtpparsedfunction.h
@@ -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 parser;
+ std::shared_ptr 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 &data, JKQTPXParsedFunctionLineGraphFunctionData* fdata) ;
+ /** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
+ virtual std::function 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& data, JKQTPYParsedFunctionLineGraphFunctionData* fdata);
+ /** \copydoc JKQTPEvaluatedFunctionWithErrorsGraphBase::buildPlotFunctorSpec() */
+ virtual std::function buildErrorFunctorSpec() override;
};
#endif // jkqtpgraphsparsedfunction_H
diff --git a/screenshots/evalcurve.png b/screenshots/evalcurve.png
index f44cd00696..08ceef17a0 100644
Binary files a/screenshots/evalcurve.png and b/screenshots/evalcurve.png differ
diff --git a/screenshots/evalcurve_small.png b/screenshots/evalcurve_small.png
index 3638362acf..d78fcfb01e 100644
Binary files a/screenshots/evalcurve_small.png and b/screenshots/evalcurve_small.png differ