mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2025-01-26 15:39:09 +08:00
simplification/unification: JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph now use JKQTPAdaptiveFunctionGraphEvaluator to generate sample points
This commit is contained in:
parent
c57c672f78
commit
8c0c8bf62e
@ -24,21 +24,20 @@ private:
|
|||||||
double a;
|
double a;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
template <class TFUNCGRAPH>
|
||||||
{
|
void drawExample(QApplication& app, const QString& name) {
|
||||||
QApplication app(argc, argv);
|
|
||||||
|
|
||||||
// 1. create a window that contains a line-edit to edit a function
|
// 1. create a window that contains a line-edit to edit a function
|
||||||
// and a JKQTPlotter to display the function, combine everything in a layout
|
// and a JKQTPlotter to display the function, combine everything in a layout
|
||||||
QWidget mainWin;
|
QWidget* mainWin=new QWidget();
|
||||||
JKQTPlotter* plot=new JKQTPlotter(&mainWin);
|
mainWin->setWindowTitle(name);
|
||||||
|
JKQTPlotter* plot=new JKQTPlotter(mainWin);
|
||||||
QVBoxLayout* layout=new QVBoxLayout;
|
QVBoxLayout* layout=new QVBoxLayout;
|
||||||
mainWin.setLayout(layout);
|
mainWin->setLayout(layout);
|
||||||
layout->addWidget(plot);
|
layout->addWidget(plot);
|
||||||
|
|
||||||
// 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);
|
TFUNCGRAPH* func1=new TFUNCGRAPH(plot);
|
||||||
func1->setPlotFunctionFunctor([](double x) { return 0.2*x*x-0.015*x*x*x; });
|
func1->setPlotFunctionFunctor([](double x) { return 0.2*x*x-0.015*x*x*x; });
|
||||||
func1->setTitle("C++-inline function $0.2x^2-0.015x^3$");
|
func1->setTitle("C++-inline function $0.2x^2-0.015x^3$");
|
||||||
plot->addGraph(func1);
|
plot->addGraph(func1);
|
||||||
@ -46,7 +45,7 @@ int main(int argc, char* argv[])
|
|||||||
// 3. now we add a JKQTPXFunctionLineGraph object, which will draw a simple function
|
// 3. now we add a JKQTPXFunctionLineGraph object, which will draw a simple function
|
||||||
// the function is again defined as C++ inline function, but now uses internal
|
// the function is again defined as C++ inline function, but now uses internal
|
||||||
// parameters (handed over to the function as a pointer to QVector<double>
|
// parameters (handed over to the function as a pointer to QVector<double>
|
||||||
JKQTPXFunctionLineGraph* func2=new JKQTPXFunctionLineGraph(plot);
|
TFUNCGRAPH* func2=new TFUNCGRAPH(plot);
|
||||||
func2->setPlotFunctionFunctor([](double x, void* params) {
|
func2->setPlotFunctionFunctor([](double x, void* params) {
|
||||||
QVector<double>* p=static_cast<QVector<double>*>(params);
|
QVector<double>* p=static_cast<QVector<double>*>(params);
|
||||||
return p->at(0)*sin(2.0*JKQTPSTATISTICS_PI*x*p->at(1));
|
return p->at(0)*sin(2.0*JKQTPSTATISTICS_PI*x*p->at(1));
|
||||||
@ -59,7 +58,7 @@ int main(int argc, char* argv[])
|
|||||||
// 4. now we add a JKQTPXFunctionLineGraph object, which will draw a simple function
|
// 4. now we add a JKQTPXFunctionLineGraph object, which will draw a simple function
|
||||||
// the function is again defined as C++ inline function, but now uses external
|
// the function is again defined as C++ inline function, but now uses external
|
||||||
// parameters, which may have any type (here QMap<QString,double)
|
// parameters, which may have any type (here QMap<QString,double)
|
||||||
JKQTPXFunctionLineGraph* func3=new JKQTPXFunctionLineGraph(plot);
|
/*TFUNCGRAPH* func3=new TFUNCGRAPH(plot);
|
||||||
func3->setPlotFunctionFunctor([](double x, void* params) {
|
func3->setPlotFunctionFunctor([](double x, void* params) {
|
||||||
QMap<QString,double>* p=static_cast<QMap<QString,double>*>(params);
|
QMap<QString,double>* p=static_cast<QMap<QString,double>*>(params);
|
||||||
return p->value("amplitude")*sin(2.0*JKQTPSTATISTICS_PI*x*p->value("frequency"));
|
return p->value("amplitude")*sin(2.0*JKQTPSTATISTICS_PI*x*p->value("frequency"));
|
||||||
@ -70,32 +69,32 @@ int main(int argc, char* argv[])
|
|||||||
params3["frequency"]=0.3;
|
params3["frequency"]=0.3;
|
||||||
func3->setParams(¶ms3);
|
func3->setParams(¶ms3);
|
||||||
func3->setTitle("C++-inline function with ext. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
func3->setTitle("C++-inline function with ext. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
||||||
plot->addGraph(func3);
|
plot->addGraph(func3);*/
|
||||||
|
|
||||||
// 5. of course the function may also be any C+ funtor object:
|
// 5. of course the function may also be any C+ funtor object:
|
||||||
JKQTPXFunctionLineGraph* func4=new JKQTPXFunctionLineGraph(plot);
|
TFUNCGRAPH* func4=new TFUNCGRAPH(plot);
|
||||||
func4->setPlotFunctionFunctor(SincSqr(-8));
|
func4->setPlotFunctionFunctor(SincSqr(-8));
|
||||||
func4->setTitle("C++ functor $-8*\\sin^2(x)/x^2$");
|
func4->setTitle("C++ functor $-8*\\sin^2(x)/x^2$");
|
||||||
plot->addGraph(func4);
|
plot->addGraph(func4);
|
||||||
|
|
||||||
|
|
||||||
// 6. now we use a JKQTPXFunctionLineGraph to draw a static C function
|
// 6. now we use a JKQTPXFunctionLineGraph to draw a static C function
|
||||||
JKQTPXFunctionLineGraph* func5=new JKQTPXFunctionLineGraph(plot);
|
TFUNCGRAPH* func5=new TFUNCGRAPH(plot);
|
||||||
func5->setPlotFunctionFunctor(&sinc);
|
func5->setPlotFunctionFunctor(&sinc);
|
||||||
func5->setTitle("static C function $10*\\sin(x)/x$");
|
func5->setTitle("static C function $10*\\sin(x)/x$");
|
||||||
plot->addGraph(func5);
|
plot->addGraph(func5);
|
||||||
|
|
||||||
// 7. finally JKQTPXFunctionLineGraph defines a small set of common functions
|
// 7. finally JKQTPXFunctionLineGraph defines a small set of common functions
|
||||||
JKQTPXFunctionLineGraph* func6=new JKQTPXFunctionLineGraph(plot);
|
TFUNCGRAPH* func6=new TFUNCGRAPH(plot);
|
||||||
func6->setSpecialFunction(JKQTPXFunctionLineGraph::Line);
|
func6->setSpecialFunction(TFUNCGRAPH::Line);
|
||||||
// here we set offset p0=-1 and slope p1=1.5 of the line p0+p1*x
|
// here we set offset p0=-1 and slope p1=1.5 of the line p0+p1*x
|
||||||
func6->setParamsV(-1,1.5);
|
func6->setParamsV(-1,1.5);
|
||||||
func6->setTitle("special function: linear p_0=-1, p_1=1.5");
|
func6->setTitle("special function: linear p_0=-1, p_1=1.5");
|
||||||
plot->addGraph(func6);
|
plot->addGraph(func6);
|
||||||
|
|
||||||
// 7. finally JKQTPXFunctionLineGraph defines a small set of common functions
|
// 7. finally JKQTPXFunctionLineGraph defines a small set of common functions
|
||||||
JKQTPXFunctionLineGraph* func7=new JKQTPXFunctionLineGraph(plot);
|
TFUNCGRAPH* func7=new TFUNCGRAPH(plot);
|
||||||
func7->setSpecialFunction(JKQTPXFunctionLineGraph::Line);
|
func7->setSpecialFunction(TFUNCGRAPH::Line);
|
||||||
// here we set offset p0=1 and slope p1=-1.5 of the line p0+p1*x by adding these into a column
|
// here we set offset p0=1 and slope p1=-1.5 of the line p0+p1*x by adding these into a column
|
||||||
// in the internal datastore and then set that column as parameterColumn for the function graph
|
// in the internal datastore and then set that column as parameterColumn for the function graph
|
||||||
QVector<double> params;
|
QVector<double> params;
|
||||||
@ -114,10 +113,20 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// 4. scale the plot so the graph is contained
|
// 4. scale the plot so the graph is contained
|
||||||
plot->setXY(-10,10,-10,10);
|
plot->setXY(-10,10,-10,10);
|
||||||
|
plot->redrawPlot();
|
||||||
|
|
||||||
// show window and make it a decent size
|
// show window and make it a decent size
|
||||||
mainWin.show();
|
mainWin->show();
|
||||||
mainWin.resize(800,800);
|
mainWin->resize(800,800);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
drawExample<JKQTPXFunctionLineGraph>(app, "functionplot: JKQTPXFunctionLineGraph");
|
||||||
|
drawExample<JKQTPYFunctionLineGraph>(app, "functionplot: JKQTPYFunctionLineGraph");
|
||||||
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ void JKQTPAdaptiveFunctionGraphEvaluator::refine(JKQTPAdaptiveFunctionGraphEvalu
|
|||||||
if (degree>=maxRefinementDegree) return;
|
if (degree>=maxRefinementDegree) return;
|
||||||
const double ta=a->first;
|
const double ta=a->first;
|
||||||
const double tb=b->first;
|
const double tb=b->first;
|
||||||
const double tmid=ta+(tb-ta)/2.0;
|
const double tmid=ta+(tb-ta)*(0.5 +(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)/5.0);
|
||||||
const QPointF pa=a->second;
|
const QPointF pa=a->second;
|
||||||
const QPointF pb=b->second;
|
const QPointF pb=b->second;
|
||||||
const QPointF pmid(fxy(tmid));
|
const QPointF pmid(fxy(tmid));
|
||||||
|
@ -193,7 +193,7 @@ JKQTCOMMON_LIB_EXPORT QVector<QPointF> JKQTPSplitPolylineIntoPoints(const QVecto
|
|||||||
\note this implements an incomplete algorithm
|
\note this implements an incomplete algorithm
|
||||||
|
|
||||||
*/
|
*/
|
||||||
JKQTCOMMON_LIB_EXPORT QVector<QPointF> JKQTPSimplyfyLineSegemnts(const QVector<QPointF>& points, double maxConsecutiveAngleDegree=1.0);
|
JKQTCOMMON_LIB_EXPORT QVector<QPointF> JKQTPSimplyfyLineSegemnts(const QVector<QPointF>& points, double maxConsecutiveAngleDegree=0.2);
|
||||||
|
|
||||||
|
|
||||||
/** \brief cleans a polygon by uniting all consecutive points that were closer than distanceThreshold are united
|
/** \brief cleans a polygon by uniting all consecutive points that were closer than distanceThreshold are united
|
||||||
|
@ -40,13 +40,13 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTBasePlotter* parent):
|
|||||||
drawLine=true;
|
drawLine=true;
|
||||||
fillCurve=false;
|
fillCurve=false;
|
||||||
params=nullptr;
|
params=nullptr;
|
||||||
minSamples=10;
|
minSamples=50;
|
||||||
maxRefinementDegree=7;
|
maxRefinementDegree=5;
|
||||||
slopeTolerance=0.005;
|
slopeTolerance=0.005;
|
||||||
minPixelPerSample=32;
|
minPixelPerSample=32;
|
||||||
plotRefinement=true;
|
plotRefinement=true;
|
||||||
displaySamplePoints=false;
|
displaySamplePoints=false;
|
||||||
data=nullptr;
|
data.clear();
|
||||||
|
|
||||||
initLineStyle(parent, parentPlotStyle);
|
initLineStyle(parent, parentPlotStyle);
|
||||||
initFillStyle(parent, parentPlotStyle);
|
initFillStyle(parent, parentPlotStyle);
|
||||||
@ -88,7 +88,7 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionTy
|
|||||||
plotFunction=jkqtpPlotFunctionType();
|
plotFunction=jkqtpPlotFunctionType();
|
||||||
simplePlotFunction=f;
|
simplePlotFunction=f;
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
||||||
@ -103,7 +103,7 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f
|
|||||||
plotFunction=jkqtpPlotFunctionType();
|
plotFunction=jkqtpPlotFunctionType();
|
||||||
simplePlotFunction=std::move(f);
|
simplePlotFunction=std::move(f);
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
||||||
@ -118,7 +118,7 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::Specia
|
|||||||
title=title_;
|
title=title_;
|
||||||
functionType=type;
|
functionType=type;
|
||||||
setParams(params);
|
setParams(params);
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
||||||
@ -129,17 +129,9 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::Specia
|
|||||||
|
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::clearData() {
|
|
||||||
while (data!=nullptr) {
|
|
||||||
doublePair* d=data;
|
|
||||||
data=data->next;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
data=nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setDrawLine(bool __value)
|
void JKQTPXFunctionLineGraph::setDrawLine(bool __value)
|
||||||
{
|
{
|
||||||
@ -157,7 +149,7 @@ void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpPlotFunctionType
|
|||||||
plotFunction = __value;
|
plotFunction = __value;
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
|
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimplePlotFunctionType &__value)
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimplePlotFunctionType &__value)
|
||||||
@ -166,7 +158,7 @@ void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimplePlotFuncti
|
|||||||
simplePlotFunction=__value;
|
simplePlotFunction=__value;
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
|
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__value)
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__value)
|
||||||
@ -174,7 +166,7 @@ void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__v
|
|||||||
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||||
plotFunction = std::move(__value);
|
plotFunction = std::move(__value);
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType &&__value)
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType &&__value)
|
||||||
@ -183,7 +175,7 @@ void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType
|
|||||||
simplePlotFunction=std::move(__value);
|
simplePlotFunction=std::move(__value);
|
||||||
functionType=SpecialFunction::UserFunction;
|
functionType=SpecialFunction::UserFunction;
|
||||||
|
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getPlotFunctionFunctor() const
|
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getPlotFunctionFunctor() const
|
||||||
@ -200,7 +192,7 @@ void JKQTPXFunctionLineGraph::setParams(void *__value)
|
|||||||
{
|
{
|
||||||
if (this->params != __value) {
|
if (this->params != __value) {
|
||||||
this->params = __value;
|
this->params = __value;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +236,7 @@ void JKQTPXFunctionLineGraph::createPlotData(bool collectParams) {
|
|||||||
#ifdef JKQTBP_AUTOTIMER
|
#ifdef JKQTBP_AUTOTIMER
|
||||||
JKQTPAutoOutputTimer jkaat(QString("JKQTPXFunctionLineGraph[%1]::createPlotData()").arg(title));
|
JKQTPAutoOutputTimer jkaat(QString("JKQTPXFunctionLineGraph[%1]::createPlotData()").arg(title));
|
||||||
#endif
|
#endif
|
||||||
clearData();
|
data.clear();
|
||||||
if (collectParams) collectParameters();
|
if (collectParams) collectParameters();
|
||||||
|
|
||||||
if (parent==nullptr) return;
|
if (parent==nullptr) return;
|
||||||
@ -254,52 +246,14 @@ void JKQTPXFunctionLineGraph::createPlotData(bool collectParams) {
|
|||||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
||||||
else if (simplePlotFunction) func=simplePlotFunction;
|
else if (simplePlotFunction) func=simplePlotFunction;
|
||||||
|
|
||||||
double xmin=parent->getXMin();
|
const double xmin=parent->getXMin();
|
||||||
double xmax=parent->getXMax();
|
const double xmax=parent->getXMax();
|
||||||
double pxmin=transformX(xmin);
|
|
||||||
double pxmax=transformX(xmax);
|
|
||||||
double delta0=(pxmax-pxmin)/static_cast<double>(minSamples);
|
|
||||||
//double logdelta0=(log(xmax)-log(xmin))/static_cast<double>(minSamples);
|
|
||||||
|
|
||||||
// initially sample function
|
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double x) -> QPointF { return plot->transform(x, func(x)); }, this, std::placeholders::_1);
|
||||||
doublePair* d=new doublePair;
|
|
||||||
d->x=xmin;
|
|
||||||
d->f=func(xmin);
|
|
||||||
d->next=nullptr;
|
|
||||||
data=d;
|
|
||||||
/*if (parent && parent->getXAxis()->isLogAxis()) {
|
|
||||||
for (double x=log(xmin)+logdelta0; x<log(xmax); x=x+logdelta0) {
|
|
||||||
d->next = new doublePair;
|
|
||||||
d->next->x=exp(x+(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)*delta0/2.0);
|
|
||||||
d->next->f=func(d->next->x,);
|
|
||||||
d->next->next=nullptr;
|
|
||||||
doublePair* dd=d;
|
|
||||||
d=d->next;
|
|
||||||
refine(dd, d);
|
|
||||||
}
|
|
||||||
} else {*/
|
|
||||||
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) {
|
|
||||||
d->next = new doublePair;
|
|
||||||
d->next->x=parent->p2x(x+(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)*delta0/2.0);
|
|
||||||
d->next->f=func(d->next->x);
|
|
||||||
d->next->next=nullptr;
|
|
||||||
doublePair* dd=d;
|
|
||||||
d=d->next;
|
|
||||||
refine(dd, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//}
|
|
||||||
d->next = new doublePair;
|
|
||||||
d->next->x=xmax;
|
|
||||||
d->next->f=func(xmax);
|
|
||||||
d->next->next=nullptr;
|
|
||||||
refine(d, d->next);
|
|
||||||
|
|
||||||
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||||
|
data=evaluator.evaluate(xmin, xmax);
|
||||||
|
data=JKQTPSimplyfyLineSegemnts(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::collectParameters()
|
void JKQTPXFunctionLineGraph::collectParameters()
|
||||||
@ -347,40 +301,14 @@ void JKQTPXFunctionLineGraph::collectParameters()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::refine(doublePair* a, doublePair* b, unsigned int degree) {
|
void JKQTPXFunctionLineGraph::drawSamplePoints(JKQTPEnhancedPainter& painter) {
|
||||||
if (degree>=maxRefinementDegree) return;
|
QColor c=getLineColor();
|
||||||
double ax=transformX(a->x);
|
c.setHsv(fmod(c.hue()+90, 360), c.saturation(), c.value());
|
||||||
double af=transformX(a->f);
|
painter.save(); auto __finalpaintsamplepoints=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
double bx=transformX(b->x);
|
for (const auto& d: data) {
|
||||||
double bf=transformX(b->f);
|
if (JKQTPIsOKFloat(d.x()) && JKQTPIsOKFloat(d.y())) {
|
||||||
|
JKQTPPlotSymbol(painter, d.x(), d.y(), JKQTPCross, 6,1*parent->getLineWidthMultiplier(), c, QColor(Qt::transparent));
|
||||||
double delta=bx - ax;
|
}
|
||||||
//double logdelta=log(bx) - log(ax);
|
|
||||||
double xmid=ax+(delta)/2.0;
|
|
||||||
/*if (parent && parent->getXAxis()->isLogAxis()) {
|
|
||||||
xmid=log(a->x)+(logdelta)/2.0;
|
|
||||||
xmid=xmid+(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)*delta/5.0;
|
|
||||||
xmid=exp(xmid);
|
|
||||||
} else {*/
|
|
||||||
xmid=xmid+(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)*delta/5.0; // shake by 10%
|
|
||||||
//}
|
|
||||||
const double realxmid=parent->p2x(xmid);
|
|
||||||
double realfmid = 0.0;
|
|
||||||
if (plotFunction) realfmid=plotFunction(realxmid, params);
|
|
||||||
else if (simplePlotFunction) realfmid=simplePlotFunction(realxmid);
|
|
||||||
const double fmid=transformY(realfmid);
|
|
||||||
const double a1=(fmid - af)/(xmid - ax);
|
|
||||||
const double a2=(bf - fmid)/(bx - xmid);
|
|
||||||
//std::cout<<std::string(degree*2, ' ')<<"refine( ["<<a->x<<", "<<a->f<<"], ["<<xmid<<", "<<fmid<<"], ["<<b->x<<", "<<b->f<<"] ): a1="<<a1<<", a2="<<a2<<" acrit="<<abs(a2/a1)-1.0<<"\n";
|
|
||||||
//std::cout<<std::string(degree*2, ' ')<<"refine(): a1="<<a1<<", a2="<<a2<<" acrit="<<fabs(a2-a1)<<"\n";
|
|
||||||
if (fabs(a2-a1)>slopeTolerance || delta>minPixelPerSample) {
|
|
||||||
doublePair* dmid = new doublePair;
|
|
||||||
dmid->x=realxmid;
|
|
||||||
dmid->f=realfmid;
|
|
||||||
a->next=dmid;
|
|
||||||
dmid->next=b;
|
|
||||||
refine(a, dmid, degree+1);
|
|
||||||
refine(dmid, b, degree+1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,34 +345,25 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
eb.setStyle(errorFillStyle);
|
eb.setStyle(errorFillStyle);
|
||||||
|
|
||||||
|
|
||||||
// double xold=-1;
|
|
||||||
// double yold=-1;
|
|
||||||
// double ypeold=-1;
|
|
||||||
// double ymeold=-1;
|
|
||||||
|
|
||||||
// double x0=transformX(0);
|
|
||||||
// if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
|
||||||
double y0=transformY(0);
|
double y0=transformY(0);
|
||||||
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
||||||
bool first=false;
|
bool first=false;
|
||||||
doublePair* d=data;
|
|
||||||
//QPainterPath pa, pfill;
|
|
||||||
//QPainterPath pel, pef;
|
|
||||||
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
|
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
|
||||||
QList<QPointF> epTop, epBottom;
|
QList<QPointF> epTop, epBottom;
|
||||||
double yami=qMin(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
double yami=qMin(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
||||||
double yama=qMax(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
double yama=qMax(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
||||||
double dypix=fabs(yama-yami);
|
double dypix=fabs(yama-yami);
|
||||||
yami=yami-2*dypix;
|
yami=yami-2.0*dypix;
|
||||||
yama=yama+2*dypix;
|
yama=yama+2.0*dypix;
|
||||||
while (d!=nullptr) {
|
for (auto it=data.begin(); it!=data.end(); ++it) {
|
||||||
|
const QPointF& d=*it;
|
||||||
|
double x=d.x();
|
||||||
|
double y=d.y();
|
||||||
|
|
||||||
double xv=d->x;
|
|
||||||
double yv=d->f;
|
|
||||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
||||||
double x=transformX(xv);
|
double xv=backtransformX(x);
|
||||||
double y=transformY(yv);
|
double yv=backtransformY(y);
|
||||||
double ype=0, yme=0;
|
double ype=0, yme=0;
|
||||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||||
double e=errorPlotFunction(xv, errorParams);
|
double e=errorPlotFunction(xv, errorParams);
|
||||||
@ -459,7 +378,7 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
if (fillCurve) {
|
if (fillCurve) {
|
||||||
if (!first) filledPolygon<<QPointF(x, y0);
|
if (!first) filledPolygon<<QPointF(x, y0);
|
||||||
filledPolygon<<QPointF(x, y);
|
filledPolygon<<QPointF(x, y);
|
||||||
if (!d->next) filledPolygon<<QPointF(x, y0);
|
if (it+1==data.end()) filledPolygon<<QPointF(x, y0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
||||||
@ -476,20 +395,14 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
errorLineBottom<<QPointF(x, yme);
|
errorLineBottom<<QPointF(x, yme);
|
||||||
}
|
}
|
||||||
|
|
||||||
// xold=x;
|
|
||||||
// yold=y;
|
|
||||||
// ypeold=ype;
|
|
||||||
// ymeold=yme;
|
|
||||||
first=true;
|
first=true;
|
||||||
}
|
}
|
||||||
d=d->next;
|
|
||||||
}
|
}
|
||||||
if (drawErrorPolygons) {
|
if (drawErrorPolygons) {
|
||||||
painter.save(); auto __finalpainterrpoly=JKQTPFinally([&painter]() {painter.restore();});
|
painter.save(); auto __finalpainterrpoly=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
painter.setBrush(eb);
|
painter.setBrush(eb);
|
||||||
painter.setPen(np);
|
painter.setPen(np);
|
||||||
QPolygonF poly;
|
QPolygonF poly;
|
||||||
//poly << QPointF(xold, ypeold) << QPointF(x, ype)<< QPointF(x, yme) << QPointF(xold, ymeold) ;
|
|
||||||
for (int i=0; i<epTop.size(); i++) {
|
for (int i=0; i<epTop.size(); i++) {
|
||||||
poly<<epTop[i];
|
poly<<epTop[i];
|
||||||
}
|
}
|
||||||
@ -504,13 +417,11 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
painter.setBrush(b);
|
painter.setBrush(b);
|
||||||
painter.setPen(np);
|
painter.setPen(np);
|
||||||
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
|
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (drawLine) {
|
if (drawLine) {
|
||||||
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
painter.setPen(p);
|
painter.setPen(p);
|
||||||
painter.drawPolyline(linePolygon);
|
painter.drawPolyline(linePolygon);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||||
@ -518,29 +429,10 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
painter.setPen(ep);
|
painter.setPen(ep);
|
||||||
painter.drawPolyline(errorLineTop);
|
painter.drawPolyline(errorLineTop);
|
||||||
painter.drawPolyline(errorLineBottom);
|
painter.drawPolyline(errorLineBottom);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QColor c=getLineColor();
|
if (displaySamplePoints) drawSamplePoints(painter);
|
||||||
c.setHsv(fmod(c.hue()+90, 360), c.saturation(), c.value());
|
|
||||||
d=data;
|
|
||||||
if (displaySamplePoints) {
|
|
||||||
painter.save(); auto __finalpaintsamplepoints=JKQTPFinally([&painter]() {painter.restore();});
|
|
||||||
while (d!=nullptr) {
|
|
||||||
double xv=d->x;
|
|
||||||
double yv=d->f;
|
|
||||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
|
||||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
|
|
||||||
double x=transformX(xv);
|
|
||||||
double y=transformY(yv);
|
|
||||||
JKQTPPlotSymbol(painter, x, y, JKQTPCross, 6,1*parent->getLineWidthMultiplier(), c, QColor(Qt::transparent));
|
|
||||||
}
|
|
||||||
d=d->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
drawErrorsAfter(painter);
|
drawErrorsAfter(painter);
|
||||||
//std::cout<<"plot done\n";
|
//std::cout<<"plot done\n";
|
||||||
@ -642,121 +534,93 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
eb.setStyle(errorFillStyle);
|
eb.setStyle(errorFillStyle);
|
||||||
|
|
||||||
|
|
||||||
double xold=-1;
|
|
||||||
double yold=-1;
|
|
||||||
double xpeold=-1;
|
|
||||||
double xmeold=-1;
|
|
||||||
|
|
||||||
double x0=transformX(0);
|
double x0=transformX(0);
|
||||||
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
||||||
// double y0=transformY(0);
|
|
||||||
// if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
|
||||||
bool first=false;
|
bool first=false;
|
||||||
doublePair* d=data;
|
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
|
||||||
|
QList<QPointF> epTop, epBottom;
|
||||||
|
double xami=qMin(transformY(parent->getXAxis()->getMin()),transformY(parent->getXAxis()->getMax()));
|
||||||
|
double xama=qMax(transformY(parent->getXAxis()->getMin()),transformY(parent->getXAxis()->getMax()));
|
||||||
|
double dxpix=fabs(xama-xami);
|
||||||
|
xami=xami-2.0*dxpix;
|
||||||
|
xama=xama+2.0*dxpix;
|
||||||
|
for (auto it=data.begin(); it!=data.end(); ++it) {
|
||||||
|
const QPointF& d=*it;
|
||||||
|
double x=d.x();
|
||||||
|
double y=d.y();
|
||||||
|
|
||||||
while (d!=nullptr) {
|
|
||||||
double yv=d->x;
|
|
||||||
double xv=d->f;
|
|
||||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
||||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
||||||
double x=transformX(xv);
|
double xv=backtransformX(x);
|
||||||
double y=transformY(yv);
|
double yv=backtransformY(y);
|
||||||
double xpe=0, xme=0;
|
double xpe=0, xme=0;
|
||||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||||
double e=errorPlotFunction(xv, errorParams);
|
double e=errorPlotFunction(yv, errorParams);
|
||||||
xpe=transformX(xv+e);
|
xpe=transformX(xv+e);
|
||||||
xme=transformX(xv-e);
|
xme=transformX(xv-e);
|
||||||
|
xpe=qBound(xami, xpe, xama);
|
||||||
|
xme=qBound(xami, xme, xama);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first) {
|
x=qBound(xami, x, xama);
|
||||||
double xl1=xold;
|
|
||||||
double yl1=yold;
|
|
||||||
double xl2=x;
|
|
||||||
double yl2=y;
|
|
||||||
|
|
||||||
if (fillCurve) {
|
if (fillCurve) {
|
||||||
painter.save(); auto __finalpaintfillcurve=JKQTPFinally([&painter]() {painter.restore();});
|
if (!first) filledPolygon<<QPointF(x0, y);
|
||||||
painter.setBrush(b);
|
filledPolygon<<QPointF(x, y);
|
||||||
painter.setPen(np);
|
if (it+1==data.end()) filledPolygon<<QPointF(x0, y);
|
||||||
QPolygonF poly;
|
|
||||||
poly << QPointF(xl1, yl1) << QPointF(xl2, yl2) << QPointF(x0, yl2) << QPointF(x0, yl1);
|
|
||||||
painter.drawConvexPolygon(poly);
|
|
||||||
|
|
||||||
/*pfill.lineTo(x, y);
|
|
||||||
if (d->next==nullptr) { // last datapoint
|
|
||||||
pfill.lineTo(x, y0);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
||||||
painter.save(); auto __finalpainterrorpoly=JKQTPFinally([&painter]() {painter.restore();});
|
epTop<<QPointF(xpe, y);
|
||||||
painter.setBrush(eb);
|
epBottom<<QPointF(xme, y);
|
||||||
painter.setPen(np);
|
|
||||||
QPolygonF poly;
|
|
||||||
poly << QPointF(xpeold, yold) << QPointF(xpe, y)<< QPointF(xme, y) << QPointF(xmeold, yold) ;
|
|
||||||
painter.drawConvexPolygon(poly);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawLine) {
|
if (drawLine) {
|
||||||
painter.setPen(p);
|
linePolygon<<QPointF(x, y);
|
||||||
//pa.lineTo(x, y);
|
|
||||||
painter.drawLine(QLineF(xl1, yl1, xl2, yl2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||||
painter.setPen(ep);
|
errorLineTop<<QPointF(xpe, y);
|
||||||
painter.drawLine(QLineF(xpeold, yold, xpe, y));
|
errorLineBottom<<QPointF(xme, y);
|
||||||
painter.drawLine(QLineF(xmeold, yold, xme, y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout<<"line ("<<xl1<<", "<<yl1<<") -- ("<<xl2<<", "<<yl2<<")"<<std::endl;
|
|
||||||
} /*else {
|
|
||||||
if (drawLine) {
|
|
||||||
pa.moveTo(x, y);
|
|
||||||
}
|
|
||||||
if (fillCurve) {
|
|
||||||
pfill.moveTo(x, y0);
|
|
||||||
pfill.lineTo(x, y);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
xold=x;
|
|
||||||
yold=y;
|
|
||||||
xpeold=xpe;
|
|
||||||
xmeold=xme;
|
|
||||||
first=true;
|
first=true;
|
||||||
}
|
}
|
||||||
d=d->next;
|
|
||||||
}
|
}
|
||||||
/*if (fillCurve) {
|
if (drawErrorPolygons) {
|
||||||
pfill.closeSubpath();
|
painter.save(); auto __finalpainterrpoly=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
painter.setBrush(eb);
|
||||||
|
painter.setPen(np);
|
||||||
|
QPolygonF poly;
|
||||||
|
for (int i=0; i<epTop.size(); i++) {
|
||||||
|
poly<<epTop[i];
|
||||||
|
}
|
||||||
|
for (int i=epBottom.size()-1; i>=0; i--) {
|
||||||
|
poly<<epBottom[i];
|
||||||
|
}
|
||||||
|
painter.drawPolygon(poly, Qt::OddEvenFill);
|
||||||
|
}
|
||||||
|
if (fillCurve) {
|
||||||
|
painter.save(); auto __finalpaintfillc=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
painter.setBrush(b);
|
painter.setBrush(b);
|
||||||
painter.setPen(np);
|
painter.setPen(np);
|
||||||
painter.drawPath(pfill);
|
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawLine) {
|
if (drawLine) {
|
||||||
|
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
painter.setPen(p);
|
painter.setPen(p);
|
||||||
painter.drawPath(pa);
|
painter.drawPolyline(linePolygon);
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QColor c=getLineColor();
|
|
||||||
c.setHsv(fmod(c.hue()+90, 360), c.saturation(), c.value());
|
|
||||||
d=data;
|
|
||||||
if (displaySamplePoints) while (d!=nullptr) {
|
|
||||||
double yv=d->x;
|
|
||||||
double xv=d->f;
|
|
||||||
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
|
||||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
|
|
||||||
double x=transformX(xv);
|
|
||||||
double y=transformY(yv);
|
|
||||||
JKQTPPlotSymbol(painter, x, y, JKQTPCross, 6, 1*parent->getLineWidthMultiplier(), c, QColor(Qt::transparent));
|
|
||||||
}
|
}
|
||||||
d=d->next;
|
|
||||||
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||||
|
painter.save(); auto __finalpainterrline=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
|
painter.setPen(ep);
|
||||||
|
painter.drawPolyline(errorLineTop);
|
||||||
|
painter.drawPolyline(errorLineBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (displaySamplePoints) drawSamplePoints(painter);
|
||||||
}
|
}
|
||||||
drawErrorsAfter(painter);
|
drawErrorsAfter(painter);
|
||||||
//std::cout<<"plot done\n";
|
//std::cout<<"plot done\n";
|
||||||
@ -764,7 +628,7 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
|||||||
|
|
||||||
|
|
||||||
void JKQTPYFunctionLineGraph::createPlotData(bool collectParams) {
|
void JKQTPYFunctionLineGraph::createPlotData(bool collectParams) {
|
||||||
clearData();
|
data.clear();
|
||||||
if (collectParams) collectParameters();
|
if (collectParams) collectParameters();
|
||||||
|
|
||||||
if (parent==nullptr) return;
|
if (parent==nullptr) return;
|
||||||
@ -774,30 +638,14 @@ void JKQTPYFunctionLineGraph::createPlotData(bool collectParams) {
|
|||||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
||||||
else if (simplePlotFunction) func=simplePlotFunction;
|
else if (simplePlotFunction) func=simplePlotFunction;
|
||||||
|
|
||||||
double ymin=parent->getYMin();
|
const double ymin=parent->getYMin();
|
||||||
double ymax=parent->getYMax();
|
const double ymax=parent->getYMax();
|
||||||
double delta0=(ymax-ymin)/static_cast<double>(minSamples);
|
|
||||||
|
|
||||||
// initially sample function
|
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double y) -> QPointF { return plot->transform(func(y), y); }, this, std::placeholders::_1);
|
||||||
doublePair* d=new doublePair;
|
|
||||||
d->x=ymin;
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||||
d->f=func(ymin);
|
data=evaluator.evaluate(ymin, ymax);
|
||||||
d->next=nullptr;
|
data=JKQTPSimplyfyLineSegemnts(data);
|
||||||
data=d;
|
|
||||||
for (double y=ymin+delta0; y<ymax; y=y+delta0) {
|
|
||||||
d->next = new doublePair;
|
|
||||||
d->next->x=y+(static_cast<double>(rand())/static_cast<double>(RAND_MAX)-0.5)*delta0/2.0;
|
|
||||||
d->next->f=func(d->next->x);
|
|
||||||
d->next->next=nullptr;
|
|
||||||
doublePair* dd=d;
|
|
||||||
d=d->next;
|
|
||||||
refine(dd, d);
|
|
||||||
}
|
|
||||||
d->next = new doublePair;
|
|
||||||
d->next->x=ymax;
|
|
||||||
d->next->f=func(ymax);
|
|
||||||
d->next->next=nullptr;
|
|
||||||
refine(d, d->next);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,14 +942,14 @@ void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpPlotFunctionType &
|
|||||||
{
|
{
|
||||||
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||||
errorPlotFunction=__value;
|
errorPlotFunction=__value;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpPlotFunctionType &&__value)
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpPlotFunctionType &&__value)
|
||||||
{
|
{
|
||||||
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
||||||
errorPlotFunction = std::move(__value);
|
errorPlotFunction = std::move(__value);
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getErrorPlotFunction() const
|
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getErrorPlotFunction() const
|
||||||
{
|
{
|
||||||
@ -1112,14 +960,14 @@ void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpSimplePlotFunction
|
|||||||
{
|
{
|
||||||
errorPlotFunction=jkqtpPlotFunctionType();
|
errorPlotFunction=jkqtpPlotFunctionType();
|
||||||
errorSimplePlotFunction=__value;
|
errorSimplePlotFunction=__value;
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
|
||||||
{
|
{
|
||||||
errorPlotFunction=jkqtpPlotFunctionType();
|
errorPlotFunction=jkqtpPlotFunctionType();
|
||||||
errorSimplePlotFunction = std::move(__value);
|
errorSimplePlotFunction = std::move(__value);
|
||||||
clearData();
|
data.clear();
|
||||||
}
|
}
|
||||||
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getErrorSimplePlotFunction() const
|
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getErrorSimplePlotFunction() const
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
||||||
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||||
#include "jkqtplotter/jkqtplotter_imexport.h"
|
#include "jkqtplotter/jkqtplotter_imexport.h"
|
||||||
|
#include "jkqtcommon/jkqtpgeometrytools.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#ifndef jkqtpgraphsevaluatedfunction_H
|
#ifndef jkqtpgraphsevaluatedfunction_H
|
||||||
@ -67,7 +68,7 @@ typedef std::function<double(double)> jkqtpSimplePlotFunctionType;
|
|||||||
|
|
||||||
\image html plot_functionplots.png
|
\image html plot_functionplots.png
|
||||||
|
|
||||||
\see \ref JKQTPlotterFunctionPlots, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression()
|
\see \ref JKQTPlotterFunctionPlots, JKQTPAdaptiveFunctionGraphEvaluator, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression()
|
||||||
*/
|
*/
|
||||||
class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -120,9 +121,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public
|
|||||||
*/
|
*/
|
||||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||||
|
|
||||||
/** \brief clear the data sampled from the function. */
|
|
||||||
void clearData();
|
|
||||||
|
|
||||||
/*! \brief set color, fill color and error color at the same time */
|
/*! \brief set color, fill color and error color at the same time */
|
||||||
void setColor(QColor c);
|
void setColor(QColor c);
|
||||||
|
|
||||||
@ -287,20 +285,14 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
struct doublePair {
|
/** \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 */
|
||||||
double x;
|
QVector<QPointF> data;
|
||||||
double f;
|
|
||||||
doublePair* next;
|
|
||||||
};
|
|
||||||
/** \brief a linked list holding the datapoints \f$ \left(x, y=f(x, \vec{p})\right) \f$ to be plotted */
|
|
||||||
doublePair* data;
|
|
||||||
|
|
||||||
/** \brief fill the data array with data from the function plotFunction */
|
/** \brief fill the data array with data from the function plotFunction */
|
||||||
virtual void createPlotData( bool collectParams=true);
|
virtual void createPlotData( bool collectParams=true);
|
||||||
/** \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 */
|
/** \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();
|
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);
|
|
||||||
|
|
||||||
/** \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 */
|
||||||
int parameterColumn;
|
int parameterColumn;
|
||||||
@ -366,6 +358,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public
|
|||||||
QVector<double> iparams;
|
QVector<double> iparams;
|
||||||
/** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
/** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||||
QVector<double> ierrorparams;
|
QVector<double> ierrorparams;
|
||||||
|
/** \brief draw all the sample points in data as small symbols */
|
||||||
|
void drawSamplePoints(JKQTPEnhancedPainter &painter);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
|
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
|
||||||
|
@ -264,7 +264,7 @@ void JKQTPXYFunctionLineGraph::createPlotData(bool collectParams) {
|
|||||||
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
||||||
else if (simplePlotFunction) func=simplePlotFunction;
|
else if (simplePlotFunction) func=simplePlotFunction;
|
||||||
|
|
||||||
jkqtpSimpleParametricCurveFunctionType fTransformedFunc= std::bind([&](const JKQTPXYFunctionLineGraph* plot, double t) -> QPointF { return plot->transform(func(t)); }, this, std::placeholders::_1);
|
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);
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||||
data=evaluator.evaluate(tmin, tmax);
|
data=evaluator.evaluate(tmin, tmax);
|
||||||
|
Loading…
Reference in New Issue
Block a user