JKQTPxFunctionLineGraph and JKQTPyFunctionLineGraph now allow for simplified functions without parameters + improved handling of special functions, improved example for parsed functions (with possibility to display sample points

This commit is contained in:
Jan W. Krieger 2018-12-24 12:29:33 +01:00
parent 936ae5b410
commit 94acc1b7d5
7 changed files with 240 additions and 108 deletions

View File

@ -28,57 +28,16 @@
#include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpgraphsimage.h"
#include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpbaseelements.h"
#include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtplotter.h"
#include "jkqtpgraphsevaluatedfunction.h"
double JKQTPxFunctionLineGraphPolynomial(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d && d->size()>0) {
res=d->value(0,0);
double xx=x;
for (int i=1; i<d->size(); i++) {
res=res+d->value(i,0)*xx;
xx=xx*x;
}
}
return res;
}
double JKQTPxFunctionLineGraphExponential(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*exp(x/d->value(2,0));
} else if (d->size()>=2) {
res=d->value(0,0)*exp(x/d->value(1,0));
}
}
return res;
}
double JKQTPxFunctionLineGraphPowerLaw(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*pow(x, d->value(2,1));
} else if (d->size()>=2) {
res=d->value(0,0)*pow(x, d->value(1,1));
} else if (d->size()>=1) {
res=pow(x, d->value(0,1));
}
}
return res;
}
JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent): JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent):
JKQTPgraph(parent) JKQTPgraph(parent)
{ {
functionType=SpecialFunction::UserFunction;
color=QColor("red"); color=QColor("red");
fillColor=color.lighter(); fillColor=color.lighter();
style=Qt::SolidLine; style=Qt::SolidLine;
@ -86,7 +45,6 @@ JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent):
fillStyle=Qt::SolidPattern; fillStyle=Qt::SolidPattern;
drawLine=true; drawLine=true;
fillCurve=false; fillCurve=false;
plotFunction=nullptr;
params=nullptr; params=nullptr;
minSamples=10; minSamples=10;
maxRefinementDegree=7; maxRefinementDegree=7;
@ -98,7 +56,6 @@ JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent):
drawErrorPolygons=false; drawErrorPolygons=false;
drawErrorLines=false; drawErrorLines=false;
errorPlotFunction=nullptr;
errorParams=nullptr; errorParams=nullptr;
errorColor=color.lighter(); errorColor=color.lighter();
errorFillColor=color.lighter(); errorFillColor=color.lighter();
@ -127,6 +84,7 @@ JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent):
JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtPlotter* parent): JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtPlotter* parent):
JKQTPgraph(parent) JKQTPgraph(parent)
{ {
functionType=SpecialFunction::UserFunction;
color=QColor("red"); color=QColor("red");
fillColor=color.lighter(); fillColor=color.lighter();
style=Qt::SolidLine; style=Qt::SolidLine;
@ -134,7 +92,6 @@ JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtPlotter* parent):
fillStyle=Qt::SolidPattern; fillStyle=Qt::SolidPattern;
drawLine=true; drawLine=true;
fillCurve=false; fillCurve=false;
plotFunction=nullptr;
params=nullptr; params=nullptr;
minSamples=10; minSamples=10;
maxRefinementDegree=7; maxRefinementDegree=7;
@ -146,7 +103,6 @@ JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtPlotter* parent):
drawErrorPolygons=false; drawErrorPolygons=false;
drawErrorLines=false; drawErrorLines=false;
errorPlotFunction=nullptr;
errorParams=nullptr; errorParams=nullptr;
errorColor=color.lighter(); errorColor=color.lighter();
errorFillColor=color.lighter(); errorFillColor=color.lighter();
@ -188,19 +144,47 @@ void JKQTPxFunctionLineGraph::clearData() {
void JKQTPxFunctionLineGraph::set_plotFunction(const jkqtpPlotFunctionType &__value) void JKQTPxFunctionLineGraph::set_plotFunction(const jkqtpPlotFunctionType &__value)
{ {
this->plotFunction = __value; simplePlotFunction=jkqtpSimplePlotFunctionType();
plotFunction = __value;
functionType=SpecialFunction::UserFunction;
clearData();
}
void JKQTPxFunctionLineGraph::set_plotFunction(const jkqtpSimplePlotFunctionType &__value)
{
plotFunction=jkqtpPlotFunctionType();
simplePlotFunction=__value;
functionType=SpecialFunction::UserFunction;
clearData(); clearData();
} }
void JKQTPxFunctionLineGraph::set_plotFunction(jkqtpPlotFunctionType &&__value) void JKQTPxFunctionLineGraph::set_plotFunction(jkqtpPlotFunctionType &&__value)
{ {
this->plotFunction = std::move(__value); simplePlotFunction=jkqtpSimplePlotFunctionType();
plotFunction = std::move(__value);
functionType=SpecialFunction::UserFunction;
clearData();
}
void JKQTPxFunctionLineGraph::set_plotFunction(jkqtpSimplePlotFunctionType &&__value)
{
plotFunction=jkqtpPlotFunctionType();
simplePlotFunction=std::move(__value);
functionType=SpecialFunction::UserFunction;
clearData(); clearData();
} }
jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_plotFunction() const jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_plotFunction() const
{ {
return this->plotFunction; return plotFunction;
}
jkqtpSimplePlotFunctionType JKQTPxFunctionLineGraph::get_simplePlotFunction() const
{
return simplePlotFunction;
} }
@ -215,7 +199,7 @@ void JKQTPxFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRect
QBrush b=painter.brush(); QBrush b=painter.brush();
b.setColor(fillColor); b.setColor(fillColor);
b.setStyle(fillStyle); b.setStyle(fillStyle);
int y=rect.top()+rect.height()/2.0; const double y=rect.top()+rect.height()/2.0;
painter.setPen(np); painter.setPen(np);
if (drawLine) painter.setPen(p); if (drawLine) painter.setPen(p);
painter.setBrush(b); painter.setBrush(b);
@ -246,7 +230,11 @@ void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
if (collectParams) collectParameters(); if (collectParams) collectParameters();
if (parent==nullptr) return; if (parent==nullptr) return;
if (plotFunction==nullptr) return; if (!plotFunction && !simplePlotFunction) return;
jkqtpSimplePlotFunctionType func;
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
else if (simplePlotFunction) func=simplePlotFunction;
double xmin=parent->getXMin(); double xmin=parent->getXMin();
double xmax=parent->getXMax(); double xmax=parent->getXMax();
@ -258,14 +246,14 @@ void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
// initially sample function // initially sample function
doublePair* d=new doublePair; doublePair* d=new doublePair;
d->x=xmin; d->x=xmin;
d->f=plotFunction(xmin, params); d->f=func(xmin);
d->next=nullptr; d->next=nullptr;
data=d; data=d;
/*if (parent && parent->getXAxis()->isLogAxis()) { /*if (parent && parent->getXAxis()->isLogAxis()) {
for (double x=log(xmin)+logdelta0; x<log(xmax); x=x+logdelta0) { for (double x=log(xmin)+logdelta0; x<log(xmax); x=x+logdelta0) {
d->next = new doublePair; d->next = new doublePair;
d->next->x=exp(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0); d->next->x=exp(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0);
d->next->f=plotFunction(d->next->x, params); d->next->f=func(d->next->x,);
d->next->next=nullptr; d->next->next=nullptr;
doublePair* dd=d; doublePair* dd=d;
d=d->next; d=d->next;
@ -273,20 +261,24 @@ void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
} }
} else {*/ } else {*/
QVector<double>* dv=static_cast<QVector<double>*>(params); QVector<double>* dv=static_cast<QVector<double>*>(params);
if (functionType==Polynomial && dv && dv->size()<=2) {
// we only need the first and last datapoint
} else {
for (double x=pxmin+delta0; x<pxmax; x=x+delta0) { for (double x=pxmin+delta0; x<pxmax; x=x+delta0) {
d->next = new doublePair; d->next = new doublePair;
d->next->x=parent->p2x(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0); d->next->x=parent->p2x(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0);
d->next->f=plotFunction(d->next->x, params); d->next->f=func(d->next->x);
d->next->next=nullptr; d->next->next=nullptr;
doublePair* dd=d; doublePair* dd=d;
d=d->next; d=d->next;
refine(dd, d); refine(dd, d);
} }
}
//} //}
d->next = new doublePair; d->next = new doublePair;
d->next->x=xmax; d->next->x=xmax;
d->next->f=plotFunction(xmax, params); d->next->f=func(xmax);
d->next->next=nullptr; d->next->next=nullptr;
refine(d, d->next); refine(d, d->next);
@ -355,7 +347,9 @@ void JKQTPxFunctionLineGraph::refine(doublePair* a, doublePair* b, unsigned int
xmid=xmid+((double)rand()/(double)RAND_MAX-0.5)*delta/5.0; // shake by 10% xmid=xmid+((double)rand()/(double)RAND_MAX-0.5)*delta/5.0; // shake by 10%
//} //}
double realxmid=parent->p2x(xmid); double realxmid=parent->p2x(xmid);
double realfmid=plotFunction(realxmid, params); double realfmid;
if (plotFunction) realfmid=plotFunction(realxmid, params);
else if (simplePlotFunction) realfmid=simplePlotFunction(realxmid);
double fmid=yAxis->x2p(realfmid); double fmid=yAxis->x2p(realfmid);
double a1=(fmid - af)/(xmid - ax); double a1=(fmid - af)/(xmid - ax);
double a2=(bf - fmid)/(bx - xmid); double a2=(bf - fmid)/(bx - xmid);
@ -721,7 +715,11 @@ void JKQTPyFunctionLineGraph::createPlotData(bool /*collectParams*/) {
clearData(); clearData();
if (parent==nullptr) return; if (parent==nullptr) return;
if (plotFunction==nullptr) return; if (!plotFunction && !simplePlotFunction) return;
jkqtpSimplePlotFunctionType func;
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
else if (simplePlotFunction) func=simplePlotFunction;
double ymin=parent->getYMin(); double ymin=parent->getYMin();
double ymax=parent->getYMax(); double ymax=parent->getYMax();
@ -730,13 +728,13 @@ void JKQTPyFunctionLineGraph::createPlotData(bool /*collectParams*/) {
// initially sample function // initially sample function
doublePair* d=new doublePair; doublePair* d=new doublePair;
d->x=ymin; d->x=ymin;
d->f=plotFunction(ymin, params); d->f=func(ymin);
d->next=nullptr; d->next=nullptr;
data=d; data=d;
for (double y=ymin+delta0; y<ymax; y=y+delta0) { for (double y=ymin+delta0; y<ymax; y=y+delta0) {
d->next = new doublePair; d->next = new doublePair;
d->next->x=y+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0; d->next->x=y+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0;
d->next->f=plotFunction(d->next->x, params); d->next->f=func(d->next->x);
d->next->next=nullptr; d->next->next=nullptr;
doublePair* dd=d; doublePair* dd=d;
d=d->next; d=d->next;
@ -744,7 +742,7 @@ void JKQTPyFunctionLineGraph::createPlotData(bool /*collectParams*/) {
} }
d->next = new doublePair; d->next = new doublePair;
d->next->x=ymax; d->next->x=ymax;
d->next->f=plotFunction(ymax, params); d->next->f=func(ymax);
d->next->next=nullptr; d->next->next=nullptr;
refine(d, d->next); refine(d, d->next);
@ -802,18 +800,93 @@ void JKQTPxFunctionLineGraph::set_copiedParams(const double *params, int N)
set_params(v); set_params(v);
} }
void JKQTPxFunctionLineGraph::set_paramsV(double p1) {
QVector<double> p;
p<<p1;
set_params(p);
}
void JKQTPxFunctionLineGraph::set_paramsV(double p1, double p2) {
QVector<double> p;
p<<p1<<p2;
set_params(p);
}
void JKQTPxFunctionLineGraph::set_paramsV(double p1, double p2, double p3) {
QVector<double> p;
p<<p1<<p2<<p3;
set_params(p);
}
void JKQTPxFunctionLineGraph::set_paramsV(double p1, double p2, double p3, double p4) {
QVector<double> p;
p<<p1<<p2<<p3<<p4;
set_params(p);
}
void JKQTPxFunctionLineGraph::set_paramsV(double p1, double p2, double p3, double p4, double p5) {
QVector<double> p;
p<<p1<<p2<<p3<<p4<<p5;
set_params(p);
}
void JKQTPxFunctionLineGraph::set_errorParams(const QVector<double> &errorParams) void JKQTPxFunctionLineGraph::set_errorParams(const QVector<double> &errorParams)
{ {
ierrorparams=errorParams; ierrorparams=errorParams;
set_errorParams(&ierrorparams); set_errorParams(&ierrorparams);
} }
void JKQTPxFunctionLineGraph::setSpecialFunction(JKQTPxFunctionLineGraph::SpecialFunction function) void JKQTPxFunctionLineGraph::setSpecialFunction(JKQTPxFunctionLineGraph::SpecialFunction function)
{ {
if (function==JKQTPxFunctionLineGraph::Polynomial) set_plotFunction(JKQTPxFunctionLineGraphPolynomial); if (function==JKQTPxFunctionLineGraph::Polynomial) {
else if (function==JKQTPxFunctionLineGraph::Exponential) set_plotFunction(JKQTPxFunctionLineGraphExponential); set_plotFunction([](double x, void* param) {
else if (function==JKQTPxFunctionLineGraph::PowerLaw) set_plotFunction(JKQTPxFunctionLineGraphPowerLaw); double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d && d->size()>0) {
res=d->value(0,0);
double xx=x;
for (int i=1; i<d->size(); i++) {
res=res+d->value(i,0)*xx;
xx=xx*x;
}
}
return res;
});
}
else if (function==JKQTPxFunctionLineGraph::Exponential) set_plotFunction([](double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*exp(x/d->value(2,0));
} else if (d->size()>=2) {
res=d->value(0,0)*exp(x/d->value(1,0));
}
}
return res;
});
else if (function==JKQTPxFunctionLineGraph::PowerLaw) set_plotFunction([](double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*pow(x, d->value(2,1));
} else if (d->size()>=2) {
res=d->value(0,0)*pow(x, d->value(1,1));
} else if (d->size()>=1) {
res=pow(x, d->value(0,1));
}
}
return res;
});
else throw std::runtime_error("unknown special function type");
}
JKQTPxFunctionLineGraph::SpecialFunction JKQTPxFunctionLineGraph::getFunctionType() const
{
return functionType;
} }
QVector<double> JKQTPxFunctionLineGraph::get_internalParams() const { QVector<double> JKQTPxFunctionLineGraph::get_internalParams() const {
@ -825,12 +898,15 @@ QVector<double> JKQTPxFunctionLineGraph::get_internalErrorParams() const {
void JKQTPxFunctionLineGraph::set_errorPlotFunction(const jkqtpPlotFunctionType &__value) void JKQTPxFunctionLineGraph::set_errorPlotFunction(const jkqtpPlotFunctionType &__value)
{ {
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
errorPlotFunction=__value; errorPlotFunction=__value;
clearData();
} }
void JKQTPxFunctionLineGraph::set_errorPlotFunction(jkqtpPlotFunctionType &&__value) void JKQTPxFunctionLineGraph::set_errorPlotFunction(jkqtpPlotFunctionType &&__value)
{ {
this->errorPlotFunction = std::move(__value); errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
errorPlotFunction = std::move(__value);
clearData(); clearData();
} }
jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_errorPlotFunction() const jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_errorPlotFunction() const
@ -838,6 +914,24 @@ jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_errorPlotFunction() const
return errorPlotFunction; return errorPlotFunction;
} }
void JKQTPxFunctionLineGraph::set_errorPlotFunction(const jkqtpSimplePlotFunctionType &__value)
{
errorPlotFunction=jkqtpPlotFunctionType();
errorSimplePlotFunction=__value;
clearData();
}
void JKQTPxFunctionLineGraph::set_errorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
{
errorPlotFunction=jkqtpPlotFunctionType();
errorSimplePlotFunction = std::move(__value);
clearData();
}
jkqtpSimplePlotFunctionType JKQTPxFunctionLineGraph::get_errorSimplePlotFunction() const
{
return errorSimplePlotFunction;
}
bool JKQTPxFunctionLineGraph::usesColumn(int c) bool JKQTPxFunctionLineGraph::usesColumn(int c)
{ {

View File

@ -53,6 +53,14 @@
*/ */
typedef std::function<double(double, void*)> jkqtpPlotFunctionType; typedef std::function<double(double, void*)> jkqtpPlotFunctionType;
/*! \brief simplified type of functions (without parameters) that may be plottet
\ingroup jkqtplotter_plots
This is the type of functions \f$ y=f(x) \f$ that may be plottet by JKQTPxFunctionLineGraph
and JKQTPyFunctionLineGraph.
*/
typedef std::function<double(double)> jkqtpSimplePlotFunctionType;
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$ /*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
\ingroup jkqtplotter_plots \ingroup jkqtplotter_plots
@ -76,7 +84,9 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
PowerLaw /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ PowerLaw, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
UserFunction, /*!< \brief no special function but the function is provided by the user */
}; };
/** \brief class constructor */ /** \brief class constructor */
@ -125,41 +135,40 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
* \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER> * \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER>
* \see plotFunction for more information */ * \see plotFunction for more information */
virtual void set_plotFunction (const jkqtpPlotFunctionType & __value); virtual void set_plotFunction (const jkqtpPlotFunctionType & __value);
/** \brief returns the property varname. \see varname for more information */ \ /** \brief sets the property plotFunction to the specified \a __value.
*
* \details Description of the parameter plotFunction is: <CENTER>\copybrief plotFunction.</CENTER>
* \see plotFunction for more information */
virtual void set_plotFunction (jkqtpSimplePlotFunctionType && __value);
/** \brief sets the property plotFunction to the specified \a __value.
*
* \details Description of the parameter plotFunction is: <CENTER>\copybrief plotFunction.</CENTER>
* \see plotFunction for more information */
virtual void set_plotFunction (const jkqtpSimplePlotFunctionType & __value);
/** \brief returns the property plotFunction. \see plotFunction for more information */ \
virtual jkqtpPlotFunctionType get_plotFunction () const; virtual jkqtpPlotFunctionType get_plotFunction () const;
/** \brief returns the property simplePlotFunction. \see simplePlotFunction for more information */ \
virtual jkqtpSimplePlotFunctionType get_simplePlotFunction () const;
JKQTPGET_SET_MACRO_I(void*, params, clearData()) JKQTPGET_SET_MACRO_I(void*, params, clearData())
/** \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!!!) */ /** \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!!!) */
void set_params(const QVector<double>& params); void set_params(const QVector<double>& params);
/** \brief sets the params from a copy of the given array of length \a N */ /** \brief sets the params from a copy of the given array of length \a N */
void set_copiedParams(const double* params, int N); void set_copiedParams(const double* params, int N);
inline void set_paramsV(double p1) { /** \brief set an internal parameter vector as function parameters, initialized with {p1} */
QVector<double> p; void set_paramsV(double p1);
p<<p1; /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2} */
set_params(p); void set_paramsV(double p1, double p2);
} /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3} */
inline void set_paramsV(double p1, double p2) { void set_paramsV(double p1, double p2, double p3);
QVector<double> p; /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4} */
p<<p1<<p2; void set_paramsV(double p1, double p2, double p3, double p4);
set_params(p); /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4,p5} */
} void set_paramsV(double p1, double p2, double p3, double p4, double p5);
inline void set_paramsV(double p1, double p2, double p3) {
QVector<double> p;
p<<p1<<p2<<p3;
set_params(p);
}
inline void set_paramsV(double p1, double p2, double p3, double p4) {
QVector<double> p;
p<<p1<<p2<<p3<<p4;
set_params(p);
}
inline void set_paramsV(double p1, double p2, double p3, double p4, double p5) {
QVector<double> p;
p<<p1<<p2<<p3<<p4<<p5;
set_params(p);
}
/** \brief returns the currently set internal parameter vector */
QVector<double> get_internalParams() const; QVector<double> get_internalParams() const;
/** \brief returns the currently set internal parameter vector */
QVector<double> get_internalErrorParams() const; QVector<double> get_internalErrorParams() const;
JKQTPGET_SET_MACRO(unsigned int, minSamples) JKQTPGET_SET_MACRO(unsigned int, minSamples)
JKQTPGET_SET_MACRO(unsigned int, maxRefinementDegree) JKQTPGET_SET_MACRO(unsigned int, maxRefinementDegree)
@ -181,6 +190,18 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
virtual void set_errorPlotFunction (const jkqtpPlotFunctionType & __value); virtual void set_errorPlotFunction (const jkqtpPlotFunctionType & __value);
/** \brief returns the property varname. \see varname for more information */ \ /** \brief returns the property varname. \see varname for more information */ \
virtual jkqtpPlotFunctionType get_errorPlotFunction () const; virtual jkqtpPlotFunctionType get_errorPlotFunction () const;
/** \brief sets the property errorPlotFunction to the specified \a __value.
*
* \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
* \see errorPlotFunction for more information */
virtual void set_errorPlotFunction (jkqtpSimplePlotFunctionType && __value);
/** \brief sets the property errorPlotFunction to the specified \a __value.
*
* \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
* \see errorPlotFunction for more information */
virtual void set_errorPlotFunction (const jkqtpSimplePlotFunctionType & __value);
/** \brief returns the property varname. \see varname for more information */ \
virtual jkqtpSimplePlotFunctionType get_errorSimplePlotFunction () const;
JKQTPGET_SET_MACRO(void*, errorParams) JKQTPGET_SET_MACRO(void*, errorParams)
/** \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!!!) */ /** \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 set_errorParams(const QVector<double>& errorParams); void set_errorParams(const QVector<double>& errorParams);
@ -202,6 +223,8 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
/** \brief sets function to the given special function */ /** \brief sets function to the given special function */
void setSpecialFunction(SpecialFunction function); void setSpecialFunction(SpecialFunction function);
/** \brief returns, which special function is set (or if any is set) */
SpecialFunction getFunctionType() const;
protected: protected:
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */ /** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle; int parentPlotStyle;
@ -218,7 +241,7 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
virtual void createPlotData( bool collectParams=true); virtual void createPlotData( bool collectParams=true);
virtual void collectParameters(); virtual void collectParameters();
/** \brief refine datapoints on the function graph between two evaluations \a a and \a b */
void refine(doublePair* a, doublePair* b, unsigned int degree=0); void refine(doublePair* a, doublePair* b, unsigned int degree=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 */ /** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the plot function */
@ -242,6 +265,10 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
bool fillCurve; bool fillCurve;
/** \brief the function to be plotted */ /** \brief the function to be plotted */
jkqtpPlotFunctionType plotFunction; 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 pointer to the parameters supplied to the plotting funtion */ /** \brief pointer to the parameters supplied to the plotting funtion */
void* params; void* params;
/** \brief the minimum number of points to evaluate the function at */ /** \brief the minimum number of points to evaluate the function at */
@ -267,6 +294,8 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
bool drawErrorLines; bool drawErrorLines;
/** \brief this function calculates the error at a given position */ /** \brief this function calculates the error at a given position */
jkqtpPlotFunctionType errorPlotFunction; jkqtpPlotFunctionType errorPlotFunction;
/** \brief this function calculates the error at a given position, simplified form without parameters */
jkqtpSimplePlotFunctionType errorSimplePlotFunction;
/** \brief parameters for errorFunction */ /** \brief parameters for errorFunction */
void* errorParams; void* errorParams;
/** \brief color of the error graph */ /** \brief color of the error graph */

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -8,7 +8,7 @@ This project (see `./test/simpletest_functionplot/`) demonstrates how to plot ma
The first example shows how to plot a C++ inline function: The first example shows how to plot a C++ inline function:
```c++ ```c++
JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot); JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot);
func1->set_plotFunction([](double x, void* /*params*/) { return 0.2*x*x-0.015*x*x*x; }); func1->set_plotFunction([](double x) { return 0.2*x*x-0.015*x*x*x; });
func1->set_title("C++-inline function $0.2x^2-0.015x^3$"); func1->set_title("C++-inline function $0.2x^2-0.015x^3$");
plot->addGraph(func1); plot->addGraph(func1);
``` ```
@ -47,7 +47,7 @@ You can also use C++ functors (or function objects):
struct SincSqr { struct SincSqr {
public: public:
inline SincSqr(double amplitude): a(amplitude) {} inline SincSqr(double amplitude): a(amplitude) {}
inline double operator()(double x, void* /*params*/) { inline double operator()(double x) {
return a*sin(x)*sin(x)/x/x; return a*sin(x)*sin(x)/x/x;
} }
private: private:
@ -64,7 +64,7 @@ You can also use C++ functors (or function objects):
... or simple static C functions: ... or simple static C functions:
```c++ ```c++
double sinc(double x, void* /*params*/) { double sinc(double x) {
return 10.0*sin(x)/x; return 10.0*sin(x)/x;
} }

View File

@ -4,14 +4,14 @@
#include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/jkqtpgraphsevaluatedfunction.h" #include "jkqtplotter/jkqtpgraphsevaluatedfunction.h"
double sinc(double x, void* /*params*/) { double sinc(double x) {
return 10.0*sin(x)/x; return 10.0*sin(x)/x;
} }
struct SincSqr { struct SincSqr {
public: public:
inline SincSqr(double amplitude): a(amplitude) {} inline SincSqr(double amplitude): a(amplitude) {}
inline double operator()(double x, void* /*params*/) { inline double operator()(double x) {
return a*sin(x)*sin(x)/x/x; return a*sin(x)*sin(x)/x/x;
} }
private: private:
@ -33,7 +33,7 @@ int main(int argc, char* argv[])
// 2. now we add a JKQTPxFunctionLineGraph object, which will draw a simple function // 2. now we add a JKQTPxFunctionLineGraph object, which will draw a simple function
// the function is defined as C++ inline function // the function is defined as C++ inline function
JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot); JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot);
func1->set_plotFunction([](double x, void* /*params*/) { return 0.2*x*x-0.015*x*x*x; }); func1->set_plotFunction([](double x) { return 0.2*x*x-0.015*x*x*x; });
func1->set_title("C++-inline function $0.2x^2-0.015x^3$"); func1->set_title("C++-inline function $0.2x^2-0.015x^3$");
plot->addGraph(func1); plot->addGraph(func1);

View File

@ -45,9 +45,13 @@ This code snippet results in a plot like this:
![jkqtplotter_simpletest_parsedfunctionplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot.png) ![jkqtplotter_simpletest_parsedfunctionplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot.png)
the adaptive capabilities of the rendering algorithm can be seen, when plotting e.g. `2/x`, which is drawn smoothely, even around the undefined value at `x=0`: The adaptive capabilities of the rendering algorithm can be seen, when plotting e.g. `2/x`, which is drawn smoothely, even around the undefined value at `x=0`:
![jkqtplotter_simpletest_parsedfunctionplot_2overx.png](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx.png) ![jkqtplotter_simpletest_parsedfunctionplot_2overx.png](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx.png)
With an additional checkbox in this example, you can switch drawing the actual sample points of the drawing algorithm on and off, by calling `parsedFunc->set_displaySamplePoints(...)`. This can be used to debug the drawing algorithm and explore its parameters (which you can set with `set_minSamples()`, `set_maxRefinementDegree()`, `set_slopeTolerance()`, `set_minPixelPerSample()`). Here is an example of a 2/x function with shown sample points:
![jkqtplotter_simpletest_parsedfunctionplot_2overx_samplepoints.png](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx_samplepoints.png)
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/) [Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)

View File

@ -1,5 +1,6 @@
#include <QApplication> #include <QApplication>
#include <QLineEdit> #include <QLineEdit>
#include <QCheckBox>
#include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpgraphsparsedfunction.h"
@ -14,10 +15,12 @@ int main(int argc, char* argv[])
QWidget mainWin; QWidget mainWin;
QLineEdit* edit=new QLineEdit(&mainWin); QLineEdit* edit=new QLineEdit(&mainWin);
edit->setToolTip("enter a function in dependence of the variable <tt>x</tt> and press ENTER to update the graph"); edit->setToolTip("enter a function in dependence of the variable <tt>x</tt> and press ENTER to update the graph");
QCheckBox* check=new QCheckBox("display sample points");
JKQtPlotter* plot=new JKQtPlotter(&mainWin); JKQtPlotter* plot=new JKQtPlotter(&mainWin);
QVBoxLayout* layout=new QVBoxLayout; QVBoxLayout* layout=new QVBoxLayout;
mainWin.setLayout(layout); mainWin.setLayout(layout);
layout->addWidget(edit); layout->addWidget(edit);
layout->addWidget(check);
layout->addWidget(plot); layout->addWidget(plot);
// 2. now we add a JKQTPxParsedFunctionLineGraph object, which will draw the function from // 2. now we add a JKQTPxParsedFunctionLineGraph object, which will draw the function from
@ -30,10 +33,12 @@ int main(int argc, char* argv[])
[=]() { [=]() {
parsedFunc->set_title("user function: \\verb{"+edit->text()+"}"); parsedFunc->set_title("user function: \\verb{"+edit->text()+"}");
parsedFunc->set_function(edit->text()); parsedFunc->set_function(edit->text());
parsedFunc->set_displaySamplePoints(check->isChecked());
plot->update_plot(); plot->update_plot();
}; };
QObject::connect(edit, &QLineEdit::returnPressed, updateGraphFunctor); QObject::connect(edit, &QLineEdit::returnPressed, updateGraphFunctor);
QObject::connect(edit, &QLineEdit::editingFinished, updateGraphFunctor); QObject::connect(edit, &QLineEdit::editingFinished, updateGraphFunctor);
QObject::connect(check, &QCheckBox::toggled, updateGraphFunctor);
edit->setText("sin(x*8)*exp(-x/4)"); edit->setText("sin(x*8)*exp(-x/4)");
updateGraphFunctor(); updateGraphFunctor();