mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-15 10:05:47 +08:00
improved parsed/evaluated function classes (made C++11-ready) and added examples for them
This commit is contained in:
parent
4e64a493ef
commit
4ac14ed871
@ -52,6 +52,8 @@ addSimpleTest(rgbimageplot_qt)
|
||||
addSimpleTest(impulsesplot)
|
||||
addSimpleTest(paramscatterplot)
|
||||
addSimpleTest(parametriccurve)
|
||||
addSimpleTest(parsedfunctionplot)
|
||||
addSimpleTest(functionplot)
|
||||
#addSimpleTest(imageplot_nodatastore)
|
||||
#addSimpleTest(rgbimageplot_opencv)
|
||||
#addSimpleTest(imageplot_opencv)
|
||||
|
@ -33,6 +33,8 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_impulsesplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_impulsesplot) | [Impulse Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_impulsesplot) | `JKQTPimpulsesVerticalGraph` and `JKQTPimpulsesHorizontalGraph`<br/>C++-style QVector as plot data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_paramscatterplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_paramscatterplot) | [Scatter Graph with Parametrized Symbols/Colors](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_paramscatterplot) | `JKQTPxyParametrizedScatterGraph`<br/>C++-style QVector as plot data<br/>modify scatter/points/line-graph properties by data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parametriccurve_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_parametriccurve) | [Plotting Parametric Curves](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_parametriccurve) | `JKQTPxyLineGraph` and `JKQTPxyParametrizedScatterGraph`<br/>C++-style QVector as plot data<br/>parametric curve plotting |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_functionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_functionplot) | [Plotting Mathematical Functions as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_functionplot) | `JKQTPxFunctionLineGraph` <br/>diretly plotting C/C++-functions |
|
||||
[![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_parsedfunctionplot) | [Plotting Parsed Mathematical Functions as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_parsedfunctionplot) | `JKQTPxParsedFunctionLineGraph` <br/>plotting functions with the internal math equation parser/evaluator |
|
||||
|
||||
### Styling the Plot, Keys, Axes, ...
|
||||
|
||||
|
@ -22,7 +22,7 @@ HEADERS += $$PWD/jkqtplotter/jkqtpbaseplotter.h \
|
||||
$$PWD/jkqtplottertools/jkqtpimagetools.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsbarchart.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsboxplot.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsvaluatedfunction.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsfilledcurve.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimpulses.h \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsparsedfunction.h \
|
||||
@ -54,7 +54,7 @@ SOURCES += $$PWD/jkqtplotter/jkqtpbaseplotter.cpp \
|
||||
$$PWD/jkqtplottertools/jkqtpimagetools.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsbarchart.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsboxplot.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsvaluatedfunction.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsfilledcurve.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsimpulses.cpp \
|
||||
$$PWD/jkqtplotter/jkqtpgraphsparsedfunction.cpp \
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
|
||||
#include "jkqtplotter/jkqtpgraphsvaluatedfunction.h"
|
||||
#include "jkqtplotter/jkqtpgraphsevaluatedfunction.h"
|
||||
#include "jkqtplotter/jkqtpbaseplotter.h"
|
||||
#include <stdlib.h>
|
||||
#include <QDebug>
|
||||
@ -186,6 +186,23 @@ void JKQTPxFunctionLineGraph::clearData() {
|
||||
data=nullptr;
|
||||
}
|
||||
|
||||
void JKQTPxFunctionLineGraph::set_plotFunction(const jkqtpPlotFunctionType &__value)
|
||||
{
|
||||
this->plotFunction = __value;
|
||||
clearData();
|
||||
}
|
||||
|
||||
void JKQTPxFunctionLineGraph::set_plotFunction(jkqtpPlotFunctionType &&__value)
|
||||
{
|
||||
this->plotFunction = std::move(__value);
|
||||
clearData();
|
||||
}
|
||||
|
||||
jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_plotFunction() const
|
||||
{
|
||||
return this->plotFunction;
|
||||
}
|
||||
|
||||
|
||||
void JKQTPxFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save();
|
||||
@ -256,9 +273,6 @@ void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
|
||||
}
|
||||
} else {*/
|
||||
QVector<double>* dv=static_cast<QVector<double>*>(params);
|
||||
if (plotFunction==JKQTPxFunctionLineGraphPolynomial && 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+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0);
|
||||
@ -268,7 +282,7 @@ void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
|
||||
d=d->next;
|
||||
refine(dd, d);
|
||||
}
|
||||
}
|
||||
|
||||
//}
|
||||
d->next = new doublePair;
|
||||
d->next->x=xmax;
|
||||
@ -428,7 +442,7 @@ void JKQTPxFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
double x=xAxis->x2p(xv);
|
||||
double y=yAxis->x2p(yv);
|
||||
double ype=0, yme=0;
|
||||
if ((drawErrorLines || drawErrorPolygons) && (errorPlotFunction!=nullptr)) {
|
||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||
double e=errorPlotFunction(xv, errorParams);
|
||||
ype=yAxis->x2p(yv+e);
|
||||
yme=yAxis->x2p(yv-e);
|
||||
@ -444,7 +458,7 @@ void JKQTPxFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
if (!d->next) filledPolygon<<QPointF(x, y0);
|
||||
}
|
||||
|
||||
if (drawErrorPolygons && (errorPlotFunction!=nullptr)) {
|
||||
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
||||
epTop<<QPointF(x, ype);
|
||||
epBottom<<QPointF(x, yme);
|
||||
}
|
||||
@ -453,7 +467,7 @@ void JKQTPxFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
linePolygon<<QPointF(x, y);
|
||||
}
|
||||
|
||||
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
|
||||
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||
errorLineTop<<QPointF(x, ype);
|
||||
errorLineBottom<<QPointF(x, yme);
|
||||
}
|
||||
@ -495,7 +509,7 @@ void JKQTPxFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
|
||||
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||
painter.save();
|
||||
painter.setPen(ep);
|
||||
painter.drawPolyline(errorLineTop);
|
||||
@ -602,7 +616,7 @@ void JKQTPyFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
double x=xAxis->x2p(xv);
|
||||
double y=yAxis->x2p(yv);
|
||||
double xpe=0, xme=0;
|
||||
if ((drawErrorLines || drawErrorPolygons) && (errorPlotFunction!=nullptr)) {
|
||||
if ((drawErrorLines || drawErrorPolygons) && (static_cast<bool>(errorPlotFunction))) {
|
||||
double e=errorPlotFunction(xv, errorParams);
|
||||
xpe=xAxis->x2p(xv+e);
|
||||
xme=xAxis->x2p(xv-e);
|
||||
@ -628,7 +642,7 @@ void JKQTPyFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
}*/
|
||||
}
|
||||
|
||||
if (drawErrorPolygons && (errorPlotFunction!=nullptr)) {
|
||||
if (drawErrorPolygons && (static_cast<bool>(errorPlotFunction))) {
|
||||
painter.save();
|
||||
painter.setBrush(eb);
|
||||
painter.setPen(np);
|
||||
@ -644,7 +658,7 @@ void JKQTPyFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
painter.drawLine(QLineF(xl1, yl1, xl2, yl2));
|
||||
}
|
||||
|
||||
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
|
||||
if (drawErrorLines && (static_cast<bool>(errorPlotFunction))) {
|
||||
painter.setPen(ep);
|
||||
painter.drawLine(QLineF(xpeold, yold, xpe, y));
|
||||
painter.drawLine(QLineF(xmeold, yold, xme, y));
|
||||
@ -809,6 +823,21 @@ QVector<double> JKQTPxFunctionLineGraph::get_internalErrorParams() const {
|
||||
return ierrorparams;
|
||||
}
|
||||
|
||||
void JKQTPxFunctionLineGraph::set_errorPlotFunction(const jkqtpPlotFunctionType &__value)
|
||||
{
|
||||
errorPlotFunction=__value;
|
||||
}
|
||||
|
||||
void JKQTPxFunctionLineGraph::set_errorPlotFunction(jkqtpPlotFunctionType &&__value)
|
||||
{
|
||||
this->errorPlotFunction = std::move(__value);
|
||||
clearData();
|
||||
}
|
||||
jkqtpPlotFunctionType JKQTPxFunctionLineGraph::get_errorPlotFunction() const
|
||||
{
|
||||
return errorPlotFunction;
|
||||
}
|
||||
|
||||
|
||||
bool JKQTPxFunctionLineGraph::usesColumn(int c)
|
||||
{
|
@ -35,9 +35,10 @@
|
||||
#include <QPair>
|
||||
#include "jkqtplotter/jkqtpgraphs.h"
|
||||
#include "jkqtplottertools/jkqtp_imexport.h"
|
||||
#include <functional>
|
||||
|
||||
#ifndef jkqtpgraphsvaluatedfunction_H
|
||||
#define jkqtpgraphsvaluatedfunction_H
|
||||
#ifndef jkqtpgraphsevaluatedfunction_H
|
||||
#define jkqtpgraphsevaluatedfunction_H
|
||||
|
||||
|
||||
|
||||
@ -50,7 +51,7 @@
|
||||
influence its result. Parameters are given as a pointer to some memory location. The function has to
|
||||
know on its own how to interpret these.
|
||||
*/
|
||||
typedef double(*jkqtpPlotFunctionType)(double, void*);
|
||||
typedef std::function<double(double, void*)> jkqtpPlotFunctionType;
|
||||
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
|
||||
@ -113,7 +114,20 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
|
||||
JKQTPGET_SET_MACRO(Qt::PenStyle, style)
|
||||
JKQTPGET_SET_MACRO(double, lineWidth)
|
||||
JKQTPGET_SET_MACRO(bool, drawLine)
|
||||
JKQTPGET_SET_MACRO_I(jkqtpPlotFunctionType, plotFunction, clearData())
|
||||
|
||||
/** \brief sets the property plotFunction to the specified \a __value.
|
||||
*
|
||||
* \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER>
|
||||
* \see plotFunction for more information */
|
||||
virtual void set_plotFunction (jkqtpPlotFunctionType && __value);
|
||||
/** \brief sets the property plotFunction to the specified \a __value.
|
||||
*
|
||||
* \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER>
|
||||
* \see plotFunction for more information */
|
||||
virtual void set_plotFunction (const jkqtpPlotFunctionType & __value);
|
||||
/** \brief returns the property varname. \see varname for more information */ \
|
||||
virtual jkqtpPlotFunctionType get_plotFunction () const;
|
||||
|
||||
JKQTPGET_SET_MACRO_I(void*, params, clearData())
|
||||
/** \brief sets the params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
void set_params(const QVector<double>& params);
|
||||
@ -155,7 +169,18 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
|
||||
JKQTPGET_SET_MACRO(bool, displaySamplePoints)
|
||||
JKQTPGET_SET_MACRO(bool, drawErrorPolygons)
|
||||
JKQTPGET_SET_MACRO(bool, drawErrorLines)
|
||||
JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction)
|
||||
/** \brief sets the property errorPlotFunction to the specified \a __value.
|
||||
*
|
||||
* \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
|
||||
* \see errorPlotFunction for more information */
|
||||
virtual void set_errorPlotFunction (jkqtpPlotFunctionType && __value);
|
||||
/** \brief sets the property errorPlotFunction to the specified \a __value.
|
||||
*
|
||||
* \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
|
||||
* \see errorPlotFunction for more information */
|
||||
virtual void set_errorPlotFunction (const jkqtpPlotFunctionType & __value);
|
||||
/** \brief returns the property varname. \see varname for more information */ \
|
||||
virtual jkqtpPlotFunctionType get_errorPlotFunction () const;
|
||||
JKQTPGET_SET_MACRO(void*, errorParams)
|
||||
/** \brief sets the error params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
|
||||
void set_errorParams(const QVector<double>& errorParams);
|
||||
@ -196,7 +221,9 @@ class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
|
||||
|
||||
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 */
|
||||
int parameterColumn;
|
||||
/** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the error plot function */
|
||||
int errorParameterColumn;
|
||||
|
||||
/** \brief color of the graph */
|
||||
@ -287,4 +314,4 @@ class LIB_EXPORT JKQTPyFunctionLineGraph: public JKQTPxFunctionLineGraph {
|
||||
|
||||
|
||||
|
||||
#endif // jkqtpgraphsvaluatedfunction_H
|
||||
#endif // jkqtpgraphsevaluatedfunction_H
|
@ -26,11 +26,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <QDebug>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
double JKQTPxParsedFunctionLineGraphFunction(double x, void* data) {
|
||||
JKQTPxParsedFunctionLineGraphFunctionData* d=(JKQTPxParsedFunctionLineGraphFunctionData*)data;
|
||||
JKQTPxParsedFunctionLineGraph::JKQTPxParsedFunctionLineGraphFunctionData* d=(JKQTPxParsedFunctionLineGraph::JKQTPxParsedFunctionLineGraphFunctionData*)data;
|
||||
if (d && d->parser && d->node) {
|
||||
try {
|
||||
d->parser->addVariableDouble("x", x);
|
||||
@ -102,6 +102,14 @@ JKQTPxParsedFunctionLineGraph::~JKQTPxParsedFunctionLineGraph()
|
||||
delete efdata.parser;
|
||||
}
|
||||
|
||||
void JKQTPxParsedFunctionLineGraph::set_plotFunction(jkqtpPlotFunctionType &&f){
|
||||
JKQTPxFunctionLineGraph::set_plotFunction(std::move(f));
|
||||
}
|
||||
|
||||
void JKQTPxParsedFunctionLineGraph::set_plotFunction(const jkqtpPlotFunctionType &f) {
|
||||
JKQTPxFunctionLineGraph::set_plotFunction(f);
|
||||
}
|
||||
|
||||
void JKQTPxParsedFunctionLineGraph::createPlotData(bool /*collectParams*/)
|
||||
{
|
||||
collectParameters();
|
||||
|
@ -27,19 +27,13 @@
|
||||
#include "jkqtplottertools/jkqtptools.h"
|
||||
#include "jkqtplottertools/jkqtpmathparser.h"
|
||||
#include "jkqtplottertools/jkqtp_imexport.h"
|
||||
#include "jkqtplotter/jkqtpgraphsvaluatedfunction.h"
|
||||
#include "jkqtplotter/jkqtpgraphsevaluatedfunction.h"
|
||||
|
||||
// forward declarations
|
||||
class JKQtBasePlotter;
|
||||
class JKQtPlotter;
|
||||
|
||||
|
||||
struct JKQTPxParsedFunctionLineGraphFunctionData {
|
||||
JKQTPMathParser* parser;
|
||||
JKQTPMathParser::jkmpNode* node;
|
||||
int varcount;
|
||||
};
|
||||
|
||||
|
||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$ The function is defined as a string and parsed by JKMathParser
|
||||
\ingroup jkqtplotter_plots
|
||||
@ -63,26 +57,34 @@ class LIB_EXPORT JKQTPxParsedFunctionLineGraph: public JKQTPxFunctionLineGraph {
|
||||
|
||||
JKQTPGET_SET_MACRO(QList<double>, parameters)
|
||||
JKQTPGET_SET_MACRO(QString, function)
|
||||
JKQTPGET_SET_MACRO(int, parameterColumn)
|
||||
|
||||
JKQTPGET_SET_MACRO(QList<double>, errorParameters)
|
||||
JKQTPGET_SET_MACRO(QString, errorFunction)
|
||||
JKQTPGET_SET_MACRO(int, errorParameterColumn)
|
||||
|
||||
/** \brief INTERNAL data structure
|
||||
* \internal
|
||||
*/
|
||||
struct JKQTPxParsedFunctionLineGraphFunctionData {
|
||||
JKQTPMathParser* parser;
|
||||
JKQTPMathParser::jkmpNode* node;
|
||||
int varcount;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
|
||||
/** \brief the function to be evaluated for the plot. Use \c x as the free variable, e.g. \c "x^2+2" */
|
||||
QString function;
|
||||
/** \brief values of the parameters \c p1 , \c p2 , \c p3 , ... */
|
||||
QList<double> parameters;
|
||||
JKQTPxParsedFunctionLineGraphFunctionData fdata;
|
||||
int parameterColumn;
|
||||
|
||||
/** \brief the function to be evaluated to add error indicators to the graph. This function is evaluated to an error for every x. Use \c x as the free variable, e.g. \c "x^2+2". */
|
||||
QString errorFunction;
|
||||
/** \brief values of the parameters \c p1 , \c p2 , \c p3 , ... for the error function*/
|
||||
QList<double> errorParameters;
|
||||
JKQTPxParsedFunctionLineGraphFunctionData efdata;
|
||||
int errorParameterColumn;
|
||||
|
||||
JKQTPGET_SET_MACRO_I(jkqtpPlotFunctionType, plotFunction, clearData())
|
||||
virtual void set_plotFunction(jkqtpPlotFunctionType&& f);
|
||||
virtual void set_plotFunction(const jkqtpPlotFunctionType& f);
|
||||
JKQTPGET_SET_MACRO_I(void*, params, clearData())
|
||||
JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction)
|
||||
JKQTPGET_SET_MACRO(void*, errorParams)
|
||||
|
@ -1079,6 +1079,7 @@ JKQTPMathParser::jkmpTokenType JKQTPMathParser::getToken(){
|
||||
// else
|
||||
program->putback(ch1);
|
||||
jkmpError("undefined operator '&'; Did you mean LOGICAL_AND ('&&' / 'and')?");
|
||||
break;
|
||||
}
|
||||
case '|':{
|
||||
char ch1=0;
|
||||
@ -1087,6 +1088,7 @@ JKQTPMathParser::jkmpTokenType JKQTPMathParser::getToken(){
|
||||
// else
|
||||
program->putback(ch1);
|
||||
jkmpError("undefined operator '|'; Did you mean LOGICAL_OR ('||' / 'or')?");
|
||||
break;
|
||||
}
|
||||
case '=':{
|
||||
char ch1=0;
|
||||
|
BIN
screenshots/jkqtplotter_simpletest_functionplot.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_functionplot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 89 KiB |
BIN
screenshots/jkqtplotter_simpletest_functionplot_small.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_functionplot_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.cpt
Normal file
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.cpt
Normal file
Binary file not shown.
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.png
Normal file
BIN
screenshots/jkqtplotter_simpletest_parsedfunctionplot_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
96
test/simpletest_functionplot/README.md
Normal file
96
test/simpletest_functionplot/README.md
Normal file
@ -0,0 +1,96 @@
|
||||
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
|
||||
|
||||
# JKQtPlotter
|
||||
|
||||
## Plotting Mathematical Functions as Line Graphs
|
||||
This project (see `./test/simpletest_functionplot/`) demonstrates how to plot mathematical functions as line graphs. The functions may be defined as static C functions, C++ functors or c++ inline functions. See [test/simpletest_parsedfunctionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/test/simpletest_parsedfunctionplot) for an example of how to use an internal equation parser provided with JKQtPlotter instead of directly defining functions.
|
||||
|
||||
The first example shows how to plot a C++ inline function:
|
||||
```c++
|
||||
JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot);
|
||||
func1->set_plotFunction([](double x, void* /*params*/) { return 0.2*x*x-0.015*x*x*x; });
|
||||
func1->set_title("C++-inline function $0.2x^2-0.015x^3$");
|
||||
plot->addGraph(func1);
|
||||
```
|
||||
|
||||
In any such plot function, you can also use parameters, provided via the second parameter. Usually these are "internal parameters", defined by `func2->set_paramsV(p0, p1, ...)`:
|
||||
```c++
|
||||
JKQTPxFunctionLineGraph* func2=new JKQTPxFunctionLineGraph(plot);
|
||||
func2->set_plotFunction([](double x, void* params) {
|
||||
QVector<double>* p=static_cast<QVector<double>*>(params);
|
||||
return p->at(0)*sin(2.0*M_PI*x*p->at(1));
|
||||
});
|
||||
// here we set the parameters p0, p1
|
||||
func2->set_paramsV(5, 0.2);
|
||||
func2->set_title("C++-inline function with int. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
||||
plot->addGraph(func2);
|
||||
```
|
||||
|
||||
... but generally any pointer can be used as parameter (the set by `set_parameter(static_cast<void*>(myDataObject))`):
|
||||
```c++
|
||||
JKQTPxFunctionLineGraph* func3=new JKQTPxFunctionLineGraph(plot);
|
||||
func3->set_plotFunction([](double x, void* params) {
|
||||
QMap<QString,double>* p=static_cast<QMap<QString,double>*>(params);
|
||||
return p->value("amplitude")*sin(2.0*M_PI*x*p->value("frequency"));
|
||||
});
|
||||
// here we set the parameters p0, p1
|
||||
QMap<QString,double> params3;
|
||||
params3["amplitude"]=-3;
|
||||
params3["frequency"]=0.3;
|
||||
func3->set_params(¶ms3);
|
||||
func3->set_title("C++-inline function with ext. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
||||
plot->addGraph(func3);
|
||||
```
|
||||
|
||||
You can also use C++ functors (or function objects):
|
||||
```c++
|
||||
struct SincSqr {
|
||||
public:
|
||||
inline SincSqr(double amplitude): a(amplitude) {}
|
||||
inline double operator()(double x, void* /*params*/) {
|
||||
return a*sin(x)*sin(x)/x/x;
|
||||
}
|
||||
private:
|
||||
double a;
|
||||
};
|
||||
|
||||
// ...
|
||||
|
||||
JKQTPxFunctionLineGraph* func4=new JKQTPxFunctionLineGraph(plot);
|
||||
func4->set_plotFunction(SincSqr(-8));
|
||||
func4->set_title("C++ functor $-8*\\sin^2(x)/x^2$");
|
||||
plot->addGraph(func4);
|
||||
```
|
||||
|
||||
... or simple static C functions:
|
||||
```c++
|
||||
double sinc(double x, void* /*params*/) {
|
||||
return 10.0*sin(x)/x;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
JKQTPxFunctionLineGraph* func5=new JKQTPxFunctionLineGraph(plot);
|
||||
func5->set_plotFunction(&sinc);
|
||||
func5->set_title("static C function $10*\\sin(x)/x$");
|
||||
plot->addGraph(func5);
|
||||
```
|
||||
|
||||
Finally `JKQTPxFunctionLineGraph` provides a small set of special functions (polynomial, exponential, ...), which draw their parameters from the internal or external parameters:
|
||||
```c++
|
||||
JKQTPxFunctionLineGraph* func6=new JKQTPxFunctionLineGraph(plot);
|
||||
func6->setSpecialFunction(JKQTPxFunctionLineGraph::Line);
|
||||
// here we set offset and slope of the line
|
||||
func6->set_paramsV(-1,1.5);
|
||||
func6->set_title("special function: linear");
|
||||
plot->addGraph(func6);
|
||||
```
|
||||
|
||||
|
||||
|
||||
This code snippets above result in a plot like this:
|
||||
|
||||
![jkqtplotter_simpletest_functionplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_functionplot.png)
|
||||
|
||||
|
||||
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
|
@ -0,0 +1,105 @@
|
||||
#include <QApplication>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/jkqtpgraphsevaluatedfunction.h"
|
||||
|
||||
double sinc(double x, void* params) {
|
||||
return 10.0*sin(x)/x;
|
||||
}
|
||||
|
||||
struct SincSqr {
|
||||
public:
|
||||
inline SincSqr(double amplitude): a(amplitude) {}
|
||||
inline double operator()(double x, void* params) {
|
||||
return a*sin(x)*sin(x)/x/x;
|
||||
}
|
||||
private:
|
||||
double a;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// 1. create a window that conatins a line-edit to edit a function
|
||||
// and a JKQtPlotter to display the function, combine everything in a layout
|
||||
QWidget mainWin;
|
||||
JKQtPlotter* plot=new JKQtPlotter(&mainWin);
|
||||
QVBoxLayout* layout=new QVBoxLayout;
|
||||
mainWin.setLayout(layout);
|
||||
layout->addWidget(plot);
|
||||
|
||||
// 2. now we add a JKQTPxFunctionLineGraph object, which will draw a simple function
|
||||
// the function is defined as C++ inline function
|
||||
JKQTPxFunctionLineGraph* func1=new JKQTPxFunctionLineGraph(plot);
|
||||
func1->set_plotFunction([](double x, void* /*params*/) { return 0.2*x*x-0.015*x*x*x; });
|
||||
func1->set_title("C++-inline function $0.2x^2-0.015x^3$");
|
||||
plot->addGraph(func1);
|
||||
|
||||
// 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
|
||||
// parameters (handed over to the function as a pointer to QVector<double>
|
||||
JKQTPxFunctionLineGraph* func2=new JKQTPxFunctionLineGraph(plot);
|
||||
func2->set_plotFunction([](double x, void* params) {
|
||||
QVector<double>* p=static_cast<QVector<double>*>(params);
|
||||
return p->at(0)*sin(2.0*M_PI*x*p->at(1));
|
||||
});
|
||||
// here we set the parameters p0, p1
|
||||
func2->set_paramsV(5, 0.2);
|
||||
func2->set_title("C++-inline function with int. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
||||
plot->addGraph(func2);
|
||||
|
||||
// 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
|
||||
// parameters, which may have any type (here QMap<QString,double)
|
||||
JKQTPxFunctionLineGraph* func3=new JKQTPxFunctionLineGraph(plot);
|
||||
func3->set_plotFunction([](double x, void* params) {
|
||||
QMap<QString,double>* p=static_cast<QMap<QString,double>*>(params);
|
||||
return p->value("amplitude")*sin(2.0*M_PI*x*p->value("frequency"));
|
||||
});
|
||||
// here we set the parameters p0, p1
|
||||
QMap<QString,double> params3;
|
||||
params3["amplitude"]=-3;
|
||||
params3["frequency"]=0.3;
|
||||
func3->set_params(¶ms3);
|
||||
func3->set_title("C++-inline function with ext. params $p_0\\cdot\\sin(x*2.0*\\pi\\cdot p_1)$");
|
||||
plot->addGraph(func3);
|
||||
|
||||
// 5. of course the function may also be any C+ funtor object:
|
||||
JKQTPxFunctionLineGraph* func4=new JKQTPxFunctionLineGraph(plot);
|
||||
func4->set_plotFunction(SincSqr(-8));
|
||||
func4->set_title("C++ functor $-8*\\sin^2(x)/x^2$");
|
||||
plot->addGraph(func4);
|
||||
|
||||
|
||||
// 6. now we use a JKQTPxFunctionLineGraph to draw a static C function
|
||||
JKQTPxFunctionLineGraph* func5=new JKQTPxFunctionLineGraph(plot);
|
||||
func5->set_plotFunction(&sinc);
|
||||
func5->set_title("static C function $10*\\sin(x)/x$");
|
||||
plot->addGraph(func5);
|
||||
|
||||
// 6. finally JKQTPxFunctionLineGraph defines a small set of common functions
|
||||
JKQTPxFunctionLineGraph* func6=new JKQTPxFunctionLineGraph(plot);
|
||||
func6->setSpecialFunction(JKQTPxFunctionLineGraph::Line);
|
||||
// here we set offset and slope of the line
|
||||
func6->set_paramsV(-1,1.5);
|
||||
func6->set_title("special function: linear");
|
||||
plot->addGraph(func6);
|
||||
|
||||
|
||||
// 8. set some axis properties (we use LaTeX for nice equation rendering)
|
||||
plot->getXAxis()->set_axisLabel(QObject::tr("x-axis"));
|
||||
plot->getYAxis()->set_axisLabel(QObject::tr("y-axis"));
|
||||
plot->get_plotter()->set_keyPosition(JKQTPkeyOutsideBottomLeft);
|
||||
|
||||
|
||||
// 4. scale the plot so the graph is contained
|
||||
plot->setXY(-10,10,-10,10);
|
||||
|
||||
// show window and make it a decent size
|
||||
mainWin.show();
|
||||
mainWin.resize(800,800);
|
||||
|
||||
return app.exec();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
# source code for this simple demo
|
||||
SOURCES = jkqtplotter_simpletest_functionplot.cpp
|
||||
|
||||
# configure Qt
|
||||
CONFIG += qt
|
||||
QT += core gui xml svg
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
|
||||
|
||||
# output executable name
|
||||
TARGET = jkqtplotter_simpletest_functionplot
|
||||
|
||||
|
||||
# include JKQtPlotter source code
|
||||
DEPENDPATH += . ../../lib
|
||||
INCLUDEPATH += ../../lib
|
||||
CONFIG (debug, debug|release):LIBS += -L../../lib/debug -ljkqtplotterlib
|
||||
CONFIG (release):LIBS += -L../../lib/release -ljkqtplotterlib
|
||||
|
||||
win32-msvc*: DEFINES += _USE_MATH_DEFINES
|
||||
|
||||
# here you can activate some debug options
|
||||
#DEFINES += SHOW_JKQTPLOTTER_DEBUG
|
||||
#DEFINES += JKQTBP_AUTOTIMER
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_functionplot
|
||||
|
||||
jkqtplotterlib.file = ../../lib/jkqtplotterlib.pro
|
||||
|
||||
jkqtplotter_simpletest_functionplot.file=$$PWD/jkqtplotter_simpletest_functionplot.pro
|
||||
jkqtplotter_simpletest_functionplot.depends = jkqtplotterlib
|
53
test/simpletest_parsedfunctionplot/README.md
Normal file
53
test/simpletest_parsedfunctionplot/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
|
||||
|
||||
# JKQtPlotter
|
||||
|
||||
## Plotting Parsed Mathematical Functions as Line Graphs
|
||||
This project (see `./test/simpletest_parsedfunctionplot/`) demonstrates how to plot mathematical functions as line graphs. The functions are defined as strings that will be evaluated with the equation parser, integrated into JKQtPlotter.
|
||||
|
||||
Adding an evaluated funtion to a graph is very simple:
|
||||
```c++
|
||||
JKQTPxParsedFunctionLineGraph* parsedFunc=new JKQTPxParsedFunctionLineGraph(plot);
|
||||
parsedFunc->set_function("sin(x*8)*exp(-x/4)");
|
||||
parsedFunc->set_title("user function");
|
||||
```
|
||||
As you can see a graph of the type `JKQTPxParsedFunctionLineGraph` is used, which plots a function that depends on the variable `x`. The given function is parsed and evaluated (see [`lib/jkqtplottertools/jkqtpmathparser.h`](https://github.com/jkriege2/JKQtPlotter/blob/master/lib/jkqtplottertools/jkqtpmathparser.h) for details on the features of the math parser). An intelligent drawing algorithm chooses the number of control points for drawing a smooth graph, with sufficient amount of details, by evaluating locally the slope of the function.
|
||||
|
||||
In the example in [`test/simpletest_parsedfunctionplot/simpletest_parsedfunctionplot.cpp`](https://github.com/jkriege2/JKQtPlotter/blob/master/test/simpletest_parsedfunctionplot/simpletest_parsedfunctionplot.cpp) we do not simply set a fixed function, but add a `QLineEdit` which allows to edit the function and redraws it, once ENTER is pressed:
|
||||
```c++
|
||||
JKQtPlotter* plot=new JKQtPlotter(&mainWin);
|
||||
QLineEdit* edit=new QLineEdit(&mainWin);
|
||||
edit->setToolTip("enter a function in dependence of the variable <tt>x</tt> and press ENTER to update the graph");
|
||||
|
||||
// ...
|
||||
|
||||
|
||||
// 2. now we add a JKQTPxParsedFunctionLineGraph object, which will draw the function from
|
||||
// the line edit
|
||||
JKQTPxParsedFunctionLineGraph* parsedFunc=new JKQTPxParsedFunctionLineGraph(plot);
|
||||
plot->addGraph(parsedFunc);
|
||||
// finally we connect the line edit with the graph, whenever RETURN is pressed,
|
||||
// the graph is updated:
|
||||
auto updateGraphFunctor=
|
||||
[=]() {
|
||||
parsedFunc->set_title("user function: \\verb{"+edit->text()+"}");
|
||||
parsedFunc->set_function(edit->text());
|
||||
plot->update_plot();
|
||||
};
|
||||
QObject::connect(edit, &QLineEdit::returnPressed, updateGraphFunctor);
|
||||
QObject::connect(edit, &QLineEdit::editingFinished, updateGraphFunctor);
|
||||
edit->setText("sin(x*8)*exp(-x/4)");
|
||||
updateGraphFunctor();
|
||||
```
|
||||
|
||||
|
||||
This code snippet results in a plot like this:
|
||||
|
||||
![jkqtplotter_simpletest_parsedfunctionplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot.png)
|
||||
|
||||
the adaptive capabilities of the rendering algorithm can be seen, when plotting e.g. `2/x`, which is drawn smoothely, even around the undefined value at `x=0`:
|
||||
|
||||
![jkqtplotter_simpletest_parsedfunctionplot_2overx.png](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_parsedfunctionplot_2overx.png.png)
|
||||
|
||||
|
||||
[Back to JKQTPlotter main page](https://github.com/jkriege2/JKQtPlotter/)
|
@ -0,0 +1,54 @@
|
||||
#include <QApplication>
|
||||
#include <QLineEdit>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/jkqtpgraphsparsedfunction.h"
|
||||
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// 1. create a window that conatins a line-edit to edit a function
|
||||
// and a JKQtPlotter to display the function, combine everything in a layout
|
||||
QWidget mainWin;
|
||||
QLineEdit* edit=new QLineEdit(&mainWin);
|
||||
edit->setToolTip("enter a function in dependence of the variable <tt>x</tt> and press ENTER to update the graph");
|
||||
JKQtPlotter* plot=new JKQtPlotter(&mainWin);
|
||||
QVBoxLayout* layout=new QVBoxLayout;
|
||||
mainWin.setLayout(layout);
|
||||
layout->addWidget(edit);
|
||||
layout->addWidget(plot);
|
||||
|
||||
// 2. now we add a JKQTPxParsedFunctionLineGraph object, which will draw the function from
|
||||
// the line edit
|
||||
JKQTPxParsedFunctionLineGraph* parsedFunc=new JKQTPxParsedFunctionLineGraph(plot);
|
||||
plot->addGraph(parsedFunc);
|
||||
// finally we connect the line edit with the graph, whenever RETURN is pressed,
|
||||
// the graph is updated:
|
||||
auto updateGraphFunctor=
|
||||
[=]() {
|
||||
parsedFunc->set_title("user function: \\verb{"+edit->text()+"}");
|
||||
parsedFunc->set_function(edit->text());
|
||||
plot->update_plot();
|
||||
};
|
||||
QObject::connect(edit, &QLineEdit::returnPressed, updateGraphFunctor);
|
||||
QObject::connect(edit, &QLineEdit::editingFinished, updateGraphFunctor);
|
||||
edit->setText("sin(x*8)*exp(-x/4)");
|
||||
updateGraphFunctor();
|
||||
|
||||
|
||||
// 3. set some axis properties (we use LaTeX for nice equation rendering)
|
||||
plot->getXAxis()->set_axisLabel(QObject::tr("x-axis"));
|
||||
plot->getYAxis()->set_axisLabel(QObject::tr("y-axis"));
|
||||
|
||||
|
||||
// 4. scale the plot so the graph is contained
|
||||
plot->setXY(-10,10,-10,10);
|
||||
|
||||
// show window and make it a decent size
|
||||
mainWin.show();
|
||||
mainWin.resize(600,400);
|
||||
|
||||
return app.exec();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
# source code for this simple demo
|
||||
SOURCES = jkqtplotter_simpletest_parsedfunctionplot.cpp
|
||||
|
||||
# configure Qt
|
||||
CONFIG += qt
|
||||
QT += core gui xml svg
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
|
||||
|
||||
# output executable name
|
||||
TARGET = jkqtplotter_simpletest_parsedfunctionplot
|
||||
|
||||
|
||||
# include JKQtPlotter source code
|
||||
DEPENDPATH += . ../../lib
|
||||
INCLUDEPATH += ../../lib
|
||||
CONFIG (debug, debug|release):LIBS += -L../../lib/debug -ljkqtplotterlib
|
||||
CONFIG (release):LIBS += -L../../lib/release -ljkqtplotterlib
|
||||
|
||||
win32-msvc*: DEFINES += _USE_MATH_DEFINES
|
||||
|
||||
# here you can activate some debug options
|
||||
#DEFINES += SHOW_JKQTPLOTTER_DEBUG
|
||||
#DEFINES += JKQTBP_AUTOTIMER
|
@ -0,0 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_parsedfunctionplot
|
||||
|
||||
jkqtplotterlib.file = ../../lib/jkqtplotterlib.pro
|
||||
|
||||
jkqtplotter_simpletest_parsedfunctionplot.file=$$PWD/jkqtplotter_simpletest_parsedfunctionplot.pro
|
||||
jkqtplotter_simpletest_parsedfunctionplot.depends = jkqtplotterlib
|
Loading…
Reference in New Issue
Block a user