2018-12-24 03:27:24 +08:00
|
|
|
/*
|
2020-08-26 18:58:23 +08:00
|
|
|
Copyright (c) 2008-2020 Jan W. Krieger (<jan@jkrieger.de>)
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This software is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
2019-02-08 00:24:46 +08:00
|
|
|
the Free Software Foundation, either version 2.1 of the License, or
|
2018-12-24 03:27:24 +08:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License (LGPL) for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-06-20 22:06:31 +08:00
|
|
|
#include "jkqtplotter/graphs/jkqtpevaluatedfunction.h"
|
2018-12-24 03:27:24 +08:00
|
|
|
#include "jkqtplotter/jkqtpbaseplotter.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <iostream>
|
2019-05-30 04:40:02 +08:00
|
|
|
#include "jkqtplotter/jkqtptools.h"
|
2019-06-20 22:06:31 +08:00
|
|
|
#include "jkqtplotter/graphs/jkqtpimage.h"
|
2018-12-24 03:27:24 +08:00
|
|
|
#include "jkqtplotter/jkqtpbaseelements.h"
|
|
|
|
#include "jkqtplotter/jkqtplotter.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTBasePlotter* parent):
|
|
|
|
JKQTPGraph(parent)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
functionType=SpecialFunction::UserFunction;
|
2018-12-24 03:27:24 +08:00
|
|
|
drawLine=true;
|
|
|
|
fillCurve=false;
|
|
|
|
params=nullptr;
|
2020-09-05 18:44:02 +08:00
|
|
|
minSamples=50;
|
|
|
|
maxRefinementDegree=5;
|
2018-12-24 03:27:24 +08:00
|
|
|
slopeTolerance=0.005;
|
|
|
|
minPixelPerSample=32;
|
|
|
|
plotRefinement=true;
|
|
|
|
displaySamplePoints=false;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
initLineStyle(parent, parentPlotStyle);
|
|
|
|
initFillStyle(parent, parentPlotStyle);
|
|
|
|
|
2018-12-24 03:27:24 +08:00
|
|
|
drawErrorPolygons=false;
|
|
|
|
drawErrorLines=false;
|
|
|
|
errorParams=nullptr;
|
2019-04-22 19:27:50 +08:00
|
|
|
errorColor=getLineColor().lighter();
|
|
|
|
errorFillColor=getLineColor().lighter();
|
2018-12-24 03:27:24 +08:00
|
|
|
errorStyle=Qt::SolidLine;
|
|
|
|
errorLineWidth=1;
|
|
|
|
errorFillStyle=Qt::SolidPattern;
|
|
|
|
|
|
|
|
parameterColumn=-1;
|
|
|
|
errorParameterColumn=-1;
|
|
|
|
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
if (parent && parentPlotStyle>=0) { // get style settings from parent object
|
2018-12-24 03:27:24 +08:00
|
|
|
//std::cout<<"got style settings from parent: "<<parentPlotStyle<<std::endl;
|
2019-02-08 00:24:46 +08:00
|
|
|
errorColor=parent->getPlotStyle(parentPlotStyle).errorColor();
|
|
|
|
errorStyle=parent->getPlotStyle(parentPlotStyle).errorStyle();
|
|
|
|
errorLineWidth=parent->getPlotStyle(parentPlotStyle).errorWidthF();
|
|
|
|
errorFillStyle=parent->getPlotStyle(parentPlotStyle).errorFillStyle();
|
|
|
|
errorFillColor=parent->getPlotStyle(parentPlotStyle).errorFillColor();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
errorFillColor.setAlphaF(0.5);
|
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPlotter* parent):
|
2019-04-22 19:27:50 +08:00
|
|
|
JKQTPXFunctionLineGraph(parent->getPlotter())
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-30 04:40:02 +08:00
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTBasePlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(parent)
|
|
|
|
{
|
|
|
|
title=title_;
|
|
|
|
plotFunction=jkqtpPlotFunctionType();
|
|
|
|
simplePlotFunction=f;
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2019-05-30 04:40:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
2020-09-05 05:41:23 +08:00
|
|
|
JKQTPXFunctionLineGraph(f, title_, parent->getPlotter())
|
2019-05-30 04:40:02 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(parent)
|
|
|
|
{
|
|
|
|
title=title_;
|
|
|
|
plotFunction=jkqtpPlotFunctionType();
|
|
|
|
simplePlotFunction=std::move(f);
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2019-05-30 04:40:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
2020-09-05 05:41:23 +08:00
|
|
|
JKQTPXFunctionLineGraph(std::move(f), title_, parent->getPlotter())
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
2019-05-30 04:40:02 +08:00
|
|
|
JKQTPXFunctionLineGraph(parent)
|
|
|
|
{
|
|
|
|
title=title_;
|
2020-09-05 05:41:23 +08:00
|
|
|
functionType=type;
|
|
|
|
setParams(params);
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2019-05-30 04:40:02 +08:00
|
|
|
}
|
|
|
|
|
2020-09-05 05:41:23 +08:00
|
|
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(type, params, title, parent->getPlotter())
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setDrawLine(bool __value)
|
|
|
|
{
|
|
|
|
this->drawLine = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JKQTPXFunctionLineGraph::getDrawLine() const
|
|
|
|
{
|
|
|
|
return this->drawLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpPlotFunctionType &__value)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
|
|
|
plotFunction = __value;
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimplePlotFunctionType &__value)
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
plotFunction=jkqtpPlotFunctionType();
|
|
|
|
simplePlotFunction=__value;
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpPlotFunctionType &&__value)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
simplePlotFunction=jkqtpSimplePlotFunctionType();
|
|
|
|
plotFunction = std::move(__value);
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimplePlotFunctionType &&__value)
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
plotFunction=jkqtpPlotFunctionType();
|
|
|
|
simplePlotFunction=std::move(__value);
|
|
|
|
functionType=SpecialFunction::UserFunction;
|
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getPlotFunctionFunctor() const
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
return plotFunction;
|
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getSimplePlotFunction() const
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
return simplePlotFunction;
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParams(void *__value)
|
|
|
|
{
|
|
|
|
if (this->params != __value) {
|
|
|
|
this->params = __value;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2019-04-22 19:27:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *JKQTPXFunctionLineGraph::getParams() const
|
|
|
|
{
|
|
|
|
return this->params;
|
|
|
|
}
|
|
|
|
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPXFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePen(painter, parent);
|
2018-12-24 03:27:24 +08:00
|
|
|
p.setJoinStyle(Qt::RoundJoin);
|
|
|
|
p.setCapStyle(Qt::RoundCap);
|
|
|
|
QPen np(Qt::NoPen);
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2018-12-24 19:29:33 +08:00
|
|
|
const double y=rect.top()+rect.height()/2.0;
|
2018-12-24 03:27:24 +08:00
|
|
|
painter.setPen(np);
|
|
|
|
if (drawLine) painter.setPen(p);
|
|
|
|
painter.setBrush(b);
|
|
|
|
if (fillCurve) painter.drawRect(rect);
|
|
|
|
if (!fillCurve & drawLine) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
|
2019-02-08 00:24:46 +08:00
|
|
|
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QColor JKQTPXFunctionLineGraph::getKeyLabelColor() const {
|
|
|
|
return getLineColor();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPXFunctionLineGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
smallestGreaterZero=minx=maxx=0; return false;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPXFunctionLineGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
smallestGreaterZero=miny=maxy=0; return false;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPXFunctionLineGraph::createPlotData(bool collectParams) {
|
2018-12-24 03:27:24 +08:00
|
|
|
#ifdef JKQTBP_AUTOTIMER
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPAutoOutputTimer jkaat(QString("JKQTPXFunctionLineGraph[%1]::createPlotData()").arg(title));
|
2018-12-24 03:27:24 +08:00
|
|
|
#endif
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
if (collectParams) collectParameters();
|
|
|
|
|
|
|
|
if (parent==nullptr) return;
|
2018-12-24 19:29:33 +08:00
|
|
|
if (!plotFunction && !simplePlotFunction) return;
|
|
|
|
|
|
|
|
jkqtpSimplePlotFunctionType func;
|
|
|
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
|
|
|
else if (simplePlotFunction) func=simplePlotFunction;
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
const double xmin=parent->getXMin();
|
|
|
|
const double xmax=parent->getXMax();
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double x) -> QPointF { return plot->transform(x, func(x)); }, this, std::placeholders::_1);
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
|
|
|
data=evaluator.evaluate(xmin, xmax);
|
|
|
|
data=JKQTPSimplyfyLineSegemnts(data);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPXFunctionLineGraph::collectParameters()
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
if (parent && parameterColumn>=0) {
|
|
|
|
iparams.clear();
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-12-24 03:27:24 +08:00
|
|
|
int imin=0;
|
2019-06-22 20:21:32 +08:00
|
|
|
int imax=static_cast<int>(datastore->getRows(parameterColumn));
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double xv=datastore->get(parameterColumn,i);
|
|
|
|
iparams<<xv;
|
|
|
|
}
|
|
|
|
//qDebug()<<"iparams_beforeclean:";
|
|
|
|
//for (int i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
|
|
|
|
int i=iparams.size()-1;
|
|
|
|
while (i>=0 && !JKQTPIsOKFloat(iparams[i])) {
|
|
|
|
iparams.remove(i,1);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
//qDebug()<<"iparams:";
|
|
|
|
//for (i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
|
|
|
|
|
|
|
|
params=&iparams;
|
|
|
|
}
|
|
|
|
if (parent && errorParameterColumn>=0) {
|
|
|
|
ierrorparams.clear();
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-12-24 03:27:24 +08:00
|
|
|
int imin=0;
|
2019-06-22 20:21:32 +08:00
|
|
|
int imax= static_cast<int>(datastore->getRows(errorParameterColumn));
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double xv=datastore->get(errorParameterColumn,i);
|
|
|
|
ierrorparams<<xv;
|
|
|
|
}
|
|
|
|
int i=ierrorparams.size()-1;
|
|
|
|
while (i>=0 && !JKQTPIsOKFloat(ierrorparams[i])) {
|
|
|
|
ierrorparams.remove(i,1);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
errorParams=&ierrorparams;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
void JKQTPXFunctionLineGraph::drawSamplePoints(JKQTPEnhancedPainter& painter) {
|
|
|
|
QColor c=getLineColor();
|
|
|
|
c.setHsv(fmod(c.hue()+90, 360), c.saturation(), c.value());
|
|
|
|
painter.save(); auto __finalpaintsamplepoints=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
for (const auto& d: data) {
|
|
|
|
if (JKQTPIsOKFloat(d.x()) && JKQTPIsOKFloat(d.y())) {
|
|
|
|
JKQTPPlotSymbol(painter, d.x(), d.y(), JKQTPCross, 6,1*parent->getLineWidthMultiplier(), c, QColor(Qt::transparent));
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
2018-12-24 03:27:24 +08:00
|
|
|
#ifdef JKQTBP_AUTOTIMER
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPAutoOutputTimer jkaaot("JKQTPXFunctionLineGraph::draw");
|
2018-12-24 03:27:24 +08:00
|
|
|
#endif
|
|
|
|
if (parent==nullptr) return;
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-12-24 03:27:24 +08:00
|
|
|
if (datastore==nullptr) return;
|
|
|
|
|
|
|
|
//qDebug()<<"start plot\n";
|
|
|
|
createPlotData();
|
|
|
|
//qDebug()<<"plot data created\n";
|
|
|
|
|
|
|
|
drawErrorsBefore(painter);
|
2019-02-08 00:24:46 +08:00
|
|
|
{
|
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePen(painter, parent);
|
2019-02-08 00:24:46 +08:00
|
|
|
QPen np(Qt::NoPen);
|
|
|
|
|
|
|
|
QPen ep=painter.pen();
|
|
|
|
ep.setColor(errorColor);
|
2019-05-13 04:22:48 +08:00
|
|
|
ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
|
2019-02-08 00:24:46 +08:00
|
|
|
ep.setStyle(errorStyle);
|
|
|
|
ep.setJoinStyle(Qt::RoundJoin);
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2019-02-08 00:24:46 +08:00
|
|
|
|
|
|
|
QBrush eb=painter.brush();
|
|
|
|
eb.setColor(errorFillColor);
|
|
|
|
eb.setStyle(errorFillStyle);
|
|
|
|
|
|
|
|
|
|
|
|
double y0=transformY(0);
|
|
|
|
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
|
|
|
bool first=false;
|
|
|
|
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
|
|
|
|
QList<QPointF> epTop, epBottom;
|
|
|
|
double yami=qMin(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
|
|
|
double yama=qMax(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
|
|
|
|
double dypix=fabs(yama-yami);
|
2020-09-05 18:44:02 +08:00
|
|
|
yami=yami-2.0*dypix;
|
|
|
|
yama=yama+2.0*dypix;
|
|
|
|
for (auto it=data.begin(); it!=data.end(); ++it) {
|
|
|
|
const QPointF& d=*it;
|
|
|
|
double x=d.x();
|
|
|
|
double y=d.y();
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
2020-09-05 18:44:02 +08:00
|
|
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
|
|
|
double xv=backtransformX(x);
|
|
|
|
double yv=backtransformY(y);
|
2019-02-08 00:24:46 +08:00
|
|
|
double ype=0, yme=0;
|
|
|
|
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
double e=errorPlotFunction(xv, errorParams);
|
|
|
|
ype=transformY(yv+e);
|
|
|
|
yme=transformY(yv-e);
|
|
|
|
ype=qBound(yami, ype, yama);
|
|
|
|
yme=qBound(yami, yme, yama);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
y=qBound(yami, y, yama);
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
if (fillCurve) {
|
|
|
|
if (!first) filledPolygon<<QPointF(x, y0);
|
|
|
|
filledPolygon<<QPointF(x, y);
|
2020-09-05 18:44:02 +08:00
|
|
|
if (it+1==data.end()) filledPolygon<<QPointF(x, y0);
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
epTop<<QPointF(x, ype);
|
|
|
|
epBottom<<QPointF(x, yme);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
if (drawLine) {
|
|
|
|
linePolygon<<QPointF(x, y);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
errorLineTop<<QPointF(x, ype);
|
|
|
|
errorLineBottom<<QPointF(x, yme);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
first=true;
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
|
|
|
if (drawErrorPolygons) {
|
2020-08-26 17:43:44 +08:00
|
|
|
painter.save(); auto __finalpainterrpoly=JKQTPFinally([&painter]() {painter.restore();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setBrush(eb);
|
|
|
|
painter.setPen(np);
|
|
|
|
QPolygonF poly;
|
|
|
|
for (int i=0; i<epTop.size(); i++) {
|
|
|
|
poly<<epTop[i];
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2019-02-08 00:24:46 +08:00
|
|
|
for (int i=epBottom.size()-1; i>=0; i--) {
|
|
|
|
poly<<epBottom[i];
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.drawPolygon(poly, Qt::OddEvenFill);
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
}
|
2019-02-08 00:24:46 +08:00
|
|
|
if (fillCurve) {
|
2020-08-26 17:43:44 +08:00
|
|
|
painter.save(); auto __finalpaintfillc=JKQTPFinally([&painter]() {painter.restore();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setBrush(b);
|
|
|
|
painter.setPen(np);
|
|
|
|
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2019-02-08 00:24:46 +08:00
|
|
|
if (drawLine) {
|
2020-08-26 17:43:44 +08:00
|
|
|
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setPen(p);
|
|
|
|
painter.drawPolyline(linePolygon);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
2020-08-26 17:43:44 +08:00
|
|
|
painter.save(); auto __finalpainterrline=JKQTPFinally([&painter]() {painter.restore();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setPen(ep);
|
|
|
|
painter.drawPolyline(errorLineTop);
|
|
|
|
painter.drawPolyline(errorLineBottom);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
if (displaySamplePoints) drawSamplePoints(painter);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
drawErrorsAfter(painter);
|
|
|
|
//std::cout<<"plot done\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTBasePlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(parent)
|
|
|
|
{
|
2018-12-28 05:52:00 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPlotter *parent):
|
|
|
|
JKQTPYFunctionLineGraph(parent->getPlotter())
|
|
|
|
{
|
2018-12-28 05:52:00 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
}
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTBasePlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(f, title, parent)
|
|
|
|
{
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
}
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTPlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(f, title, parent)
|
|
|
|
{
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
}
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-08-26 17:43:44 +08:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2019-05-30 04:40:02 +08:00
|
|
|
|
2020-09-05 05:41:23 +08:00
|
|
|
|
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(type, params, title_, parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTPlotter *parent):
|
|
|
|
JKQTPXFunctionLineGraph(type, params, title_, parent->getPlotter())
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
2018-12-24 03:27:24 +08:00
|
|
|
#ifdef JKQTBP_AUTOTIMER
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::draw");
|
2018-12-24 03:27:24 +08:00
|
|
|
#endif
|
|
|
|
if (parent==nullptr) return;
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-12-24 03:27:24 +08:00
|
|
|
if (datastore==nullptr) return;
|
|
|
|
|
|
|
|
//std::cout<<"start plot\n";
|
|
|
|
createPlotData();
|
|
|
|
//std::cout<<"plot data created\n";
|
|
|
|
|
|
|
|
drawErrorsBefore(painter);
|
2019-02-08 00:24:46 +08:00
|
|
|
{
|
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePen(painter, parent);
|
2019-02-08 00:24:46 +08:00
|
|
|
QPen np(Qt::NoPen);
|
|
|
|
|
|
|
|
QPen ep=painter.pen();
|
|
|
|
ep.setColor(errorColor);
|
2019-05-13 04:22:48 +08:00
|
|
|
ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
|
2019-02-08 00:24:46 +08:00
|
|
|
ep.setStyle(errorStyle);
|
|
|
|
ep.setJoinStyle(Qt::RoundJoin);
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2019-02-08 00:24:46 +08:00
|
|
|
|
|
|
|
QBrush eb=painter.brush();
|
|
|
|
eb.setColor(errorFillColor);
|
|
|
|
eb.setStyle(errorFillStyle);
|
|
|
|
|
|
|
|
|
|
|
|
double x0=transformX(0);
|
|
|
|
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
|
|
|
bool first=false;
|
2020-09-05 18:44:02 +08:00
|
|
|
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();
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
|
2020-09-05 18:44:02 +08:00
|
|
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
|
|
|
|
double xv=backtransformX(x);
|
|
|
|
double yv=backtransformY(y);
|
2019-02-08 00:24:46 +08:00
|
|
|
double xpe=0, xme=0;
|
|
|
|
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
2020-09-05 18:44:02 +08:00
|
|
|
double e=errorPlotFunction(yv, errorParams);
|
2019-02-08 00:24:46 +08:00
|
|
|
xpe=transformX(xv+e);
|
|
|
|
xme=transformX(xv-e);
|
2020-09-05 18:44:02 +08:00
|
|
|
xpe=qBound(xami, xpe, xama);
|
|
|
|
xme=qBound(xami, xme, xama);
|
|
|
|
}
|
|
|
|
|
|
|
|
x=qBound(xami, x, xama);
|
|
|
|
|
|
|
|
if (fillCurve) {
|
|
|
|
if (!first) filledPolygon<<QPointF(x0, y);
|
|
|
|
filledPolygon<<QPointF(x, y);
|
|
|
|
if (it+1==data.end()) filledPolygon<<QPointF(x0, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
epTop<<QPointF(xpe, y);
|
|
|
|
epBottom<<QPointF(xme, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawLine) {
|
|
|
|
linePolygon<<QPointF(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
errorLineTop<<QPointF(xpe, y);
|
|
|
|
errorLineBottom<<QPointF(xme, y);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
first=true;
|
|
|
|
}
|
|
|
|
}
|
2020-09-05 18:44:02 +08:00
|
|
|
if (drawErrorPolygons) {
|
|
|
|
painter.save(); auto __finalpainterrpoly=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();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setBrush(b);
|
|
|
|
painter.setPen(np);
|
2020-09-05 18:44:02 +08:00
|
|
|
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
|
|
|
if (drawLine) {
|
2020-09-05 18:44:02 +08:00
|
|
|
painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();});
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.setPen(p);
|
2020-09-05 18:44:02 +08:00
|
|
|
painter.drawPolyline(linePolygon);
|
|
|
|
}
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
|
|
|
painter.save(); auto __finalpainterrline=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
painter.setPen(ep);
|
|
|
|
painter.drawPolyline(errorLineTop);
|
|
|
|
painter.drawPolyline(errorLineBottom);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2020-09-05 18:44:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
if (displaySamplePoints) drawSamplePoints(painter);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
drawErrorsAfter(painter);
|
|
|
|
//std::cout<<"plot done\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPYFunctionLineGraph::createPlotData(bool collectParams) {
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 22:07:14 +08:00
|
|
|
if (collectParams) collectParameters();
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
if (parent==nullptr) return;
|
2018-12-24 19:29:33 +08:00
|
|
|
if (!plotFunction && !simplePlotFunction) return;
|
|
|
|
|
|
|
|
jkqtpSimplePlotFunctionType func;
|
|
|
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
|
|
|
else if (simplePlotFunction) func=simplePlotFunction;
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2020-09-05 18:44:02 +08:00
|
|
|
const double ymin=parent->getYMin();
|
|
|
|
const double ymax=parent->getYMax();
|
|
|
|
|
|
|
|
std::function<QPointF(double)> fTransformedFunc= std::bind([&](const JKQTPPlotElement* plot, double y) -> QPointF { return plot->transform(func(y), y); }, this, std::placeholders::_1);
|
|
|
|
|
|
|
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
|
|
|
data=evaluator.evaluate(ymin, ymax);
|
|
|
|
data=JKQTPSimplyfyLineSegemnts(data);
|
2018-12-24 03:27:24 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
QBrush JKQTPXFunctionLineGraph::getErrorBrush(JKQTPEnhancedPainter& /*painter*/) const {
|
2018-12-24 03:27:24 +08:00
|
|
|
QBrush b;
|
|
|
|
b.setColor(errorFillColor);
|
|
|
|
b.setStyle(errorFillStyle);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
QPen JKQTPXFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
|
2018-12-24 03:27:24 +08:00
|
|
|
QPen p;
|
|
|
|
p.setColor(errorColor);
|
2019-05-13 04:22:48 +08:00
|
|
|
p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
|
2018-12-24 03:27:24 +08:00
|
|
|
p.setStyle(errorStyle);
|
|
|
|
p.setJoinStyle(Qt::RoundJoin);
|
|
|
|
p.setCapStyle(Qt::RoundCap);
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParams(const QVector<double> ¶ms)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
iparams=params;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(&iparams);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setCopiedParams(const double *params, int N)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
QVector<double> v;
|
|
|
|
for (int i=0; i<N; i++) { v<<params[i]; }
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(v);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParamsV(double p1) {
|
2018-12-24 19:29:33 +08:00
|
|
|
QVector<double> p;
|
|
|
|
p<<p1;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(p);
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParamsV(double p1, double p2) {
|
2018-12-24 19:29:33 +08:00
|
|
|
QVector<double> p;
|
|
|
|
p<<p1<<p2;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(p);
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParamsV(double p1, double p2, double p3) {
|
2018-12-24 19:29:33 +08:00
|
|
|
QVector<double> p;
|
|
|
|
p<<p1<<p2<<p3;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(p);
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParamsV(double p1, double p2, double p3, double p4) {
|
2018-12-24 19:29:33 +08:00
|
|
|
QVector<double> p;
|
|
|
|
p<<p1<<p2<<p3<<p4;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(p);
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParamsV(double p1, double p2, double p3, double p4, double p5) {
|
2018-12-24 19:29:33 +08:00
|
|
|
QVector<double> p;
|
|
|
|
p<<p1<<p2<<p3<<p4<<p5;
|
2019-01-26 20:00:40 +08:00
|
|
|
setParams(p);
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorParams(const QVector<double> &errorParams)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
ierrorparams=errorParams;
|
2019-01-26 20:00:40 +08:00
|
|
|
setErrorParams(&ierrorparams);
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParameterColumn(int __value)
|
|
|
|
{
|
|
|
|
this->parameterColumn = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
int JKQTPXFunctionLineGraph::getParameterColumn() const
|
|
|
|
{
|
|
|
|
return this->parameterColumn;
|
|
|
|
}
|
|
|
|
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setParameterColumn(size_t __value) {
|
|
|
|
this->parameterColumn = static_cast<int>(__value);
|
|
|
|
}
|
2019-04-22 19:27:50 +08:00
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setErrorParameterColumn(int __value)
|
|
|
|
{
|
|
|
|
this->errorParameterColumn = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
int JKQTPXFunctionLineGraph::getErrorParameterColumn() const
|
|
|
|
{
|
|
|
|
return this->errorParameterColumn;
|
|
|
|
}
|
|
|
|
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorParameterColumn(size_t __value) {
|
|
|
|
this->errorParameterColumn = static_cast<int>(__value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setErrorLineColor(const QColor &__value)
|
|
|
|
{
|
|
|
|
this->errorColor = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor JKQTPXFunctionLineGraph::getErrorLineColor() const
|
|
|
|
{
|
|
|
|
return this->errorColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setErrorFillColor(const QColor &__value)
|
|
|
|
{
|
|
|
|
this->errorFillColor = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
QColor JKQTPXFunctionLineGraph::getErrorFillColor() const
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2019-04-22 19:27:50 +08:00
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setSpecialFunction(JKQTPXFunctionLineGraph::SpecialFunction function)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2019-01-20 17:49:29 +08:00
|
|
|
if (function==JKQTPXFunctionLineGraph::Polynomial) {
|
2019-04-22 19:27:50 +08:00
|
|
|
setPlotFunctionFunctor([](double x, void* param) {
|
2018-12-24 19:29:33 +08:00
|
|
|
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;
|
|
|
|
});
|
|
|
|
}
|
2019-04-22 19:27:50 +08:00
|
|
|
else if (function==JKQTPXFunctionLineGraph::Exponential) setPlotFunctionFunctor([](double x, void* param) {
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
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));
|
|
|
|
}
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
return res;
|
|
|
|
});
|
2019-04-22 19:27:50 +08:00
|
|
|
else if (function==JKQTPXFunctionLineGraph::PowerLaw) setPlotFunctionFunctor([](double x, void* param) {
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
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));
|
|
|
|
}
|
2018-12-24 19:29:33 +08:00
|
|
|
|
- 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, ...)
- 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
2020-09-04 05:08:52 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
});
|
2018-12-24 19:29:33 +08:00
|
|
|
else throw std::runtime_error("unknown special function type");
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPXFunctionLineGraph::SpecialFunction JKQTPXFunctionLineGraph::getFunctionType() const
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
return functionType;
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
QVector<double> JKQTPXFunctionLineGraph::getInternalParams() const {
|
2018-12-24 03:27:24 +08:00
|
|
|
return iparams;
|
|
|
|
}
|
2019-01-26 20:00:40 +08:00
|
|
|
QVector<double> JKQTPXFunctionLineGraph::getInternalErrorParams() const {
|
2018-12-24 03:27:24 +08:00
|
|
|
return ierrorparams;
|
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setMinSamples(const unsigned int &__value)
|
|
|
|
{
|
|
|
|
this->minSamples = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int JKQTPXFunctionLineGraph::getMinSamples() const
|
|
|
|
{
|
|
|
|
return this->minSamples;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setMaxRefinementDegree(const unsigned int &__value)
|
|
|
|
{
|
|
|
|
this->maxRefinementDegree = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int JKQTPXFunctionLineGraph::getMaxRefinementDegree() const
|
|
|
|
{
|
|
|
|
return this->maxRefinementDegree;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setSlopeTolerance(double __value)
|
|
|
|
{
|
|
|
|
this->slopeTolerance = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
double JKQTPXFunctionLineGraph::getSlopeTolerance() const
|
|
|
|
{
|
|
|
|
return this->slopeTolerance;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setMinPixelPerSample(double __value)
|
|
|
|
{
|
|
|
|
this->minPixelPerSample = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
double JKQTPXFunctionLineGraph::getMinPixelPerSample() const
|
|
|
|
{
|
|
|
|
return this->minPixelPerSample;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setPlotRefinement(bool __value)
|
|
|
|
{
|
|
|
|
this->plotRefinement = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JKQTPXFunctionLineGraph::getPlotRefinement() const
|
|
|
|
{
|
|
|
|
return this->plotRefinement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPXFunctionLineGraph::setDisplaySamplePoints(bool __value)
|
|
|
|
{
|
|
|
|
this->displaySamplePoints = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JKQTPXFunctionLineGraph::getDisplaySamplePoints() const
|
|
|
|
{
|
|
|
|
return this->displaySamplePoints;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpPlotFunctionType &__value)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
2018-12-24 03:27:24 +08:00
|
|
|
errorPlotFunction=__value;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpPlotFunctionType &&__value)
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
2018-12-24 19:29:33 +08:00
|
|
|
errorSimplePlotFunction=jkqtpSimplePlotFunctionType();
|
|
|
|
errorPlotFunction = std::move(__value);
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 03:27:24 +08:00
|
|
|
}
|
2019-01-26 20:00:40 +08:00
|
|
|
jkqtpPlotFunctionType JKQTPXFunctionLineGraph::getErrorPlotFunction() const
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
return errorPlotFunction;
|
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(const jkqtpSimplePlotFunctionType &__value)
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
errorPlotFunction=jkqtpPlotFunctionType();
|
|
|
|
errorSimplePlotFunction=__value;
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorPlotFunction(jkqtpSimplePlotFunctionType &&__value)
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
errorPlotFunction=jkqtpPlotFunctionType();
|
|
|
|
errorSimplePlotFunction = std::move(__value);
|
2020-09-05 18:44:02 +08:00
|
|
|
data.clear();
|
2018-12-24 19:29:33 +08:00
|
|
|
}
|
2019-01-26 20:00:40 +08:00
|
|
|
jkqtpSimplePlotFunctionType JKQTPXFunctionLineGraph::getErrorSimplePlotFunction() const
|
2018-12-24 19:29:33 +08:00
|
|
|
{
|
|
|
|
return errorSimplePlotFunction;
|
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPXFunctionLineGraph::setErrorParams(void *__value)
|
|
|
|
{
|
|
|
|
this->errorParams = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *JKQTPXFunctionLineGraph::getErrorParams() const
|
|
|
|
{
|
|
|
|
return this->errorParams;
|
|
|
|
}
|
|
|
|
|
2018-12-24 03:27:24 +08:00
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPXFunctionLineGraph::usesColumn(int c) const
|
2018-12-24 03:27:24 +08:00
|
|
|
{
|
|
|
|
return (c==parameterColumn)||(c==errorParameterColumn);
|
|
|
|
}
|
|
|
|
|