improved parsed/evaluated function classes (made C++11-ready) and added examples for them

This commit is contained in:
Jan W. Krieger 2018-12-23 20:27:24 +01:00
parent 4e64a493ef
commit 4ac14ed871
22 changed files with 1568 additions and 1126 deletions

View File

@ -52,6 +52,8 @@ addSimpleTest(rgbimageplot_qt)
addSimpleTest(impulsesplot) addSimpleTest(impulsesplot)
addSimpleTest(paramscatterplot) addSimpleTest(paramscatterplot)
addSimpleTest(parametriccurve) addSimpleTest(parametriccurve)
addSimpleTest(parsedfunctionplot)
addSimpleTest(functionplot)
#addSimpleTest(imageplot_nodatastore) #addSimpleTest(imageplot_nodatastore)
#addSimpleTest(rgbimageplot_opencv) #addSimpleTest(rgbimageplot_opencv)
#addSimpleTest(imageplot_opencv) #addSimpleTest(imageplot_opencv)

View File

@ -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_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_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_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, ... ### Styling the Plot, Keys, Axes, ...

View File

@ -22,7 +22,7 @@ HEADERS += $$PWD/jkqtplotter/jkqtpbaseplotter.h \
$$PWD/jkqtplottertools/jkqtpimagetools.h \ $$PWD/jkqtplottertools/jkqtpimagetools.h \
$$PWD/jkqtplotter/jkqtpgraphsbarchart.h \ $$PWD/jkqtplotter/jkqtpgraphsbarchart.h \
$$PWD/jkqtplotter/jkqtpgraphsboxplot.h \ $$PWD/jkqtplotter/jkqtpgraphsboxplot.h \
$$PWD/jkqtplotter/jkqtpgraphsvaluatedfunction.h \ $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.h \
$$PWD/jkqtplotter/jkqtpgraphsfilledcurve.h \ $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.h \
$$PWD/jkqtplotter/jkqtpgraphsimpulses.h \ $$PWD/jkqtplotter/jkqtpgraphsimpulses.h \
$$PWD/jkqtplotter/jkqtpgraphsparsedfunction.h \ $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.h \
@ -54,7 +54,7 @@ SOURCES += $$PWD/jkqtplotter/jkqtpbaseplotter.cpp \
$$PWD/jkqtplottertools/jkqtpimagetools.cpp \ $$PWD/jkqtplottertools/jkqtpimagetools.cpp \
$$PWD/jkqtplotter/jkqtpgraphsbarchart.cpp \ $$PWD/jkqtplotter/jkqtpgraphsbarchart.cpp \
$$PWD/jkqtplotter/jkqtpgraphsboxplot.cpp \ $$PWD/jkqtplotter/jkqtpgraphsboxplot.cpp \
$$PWD/jkqtplotter/jkqtpgraphsvaluatedfunction.cpp \ $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp \
$$PWD/jkqtplotter/jkqtpgraphsfilledcurve.cpp \ $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.cpp \
$$PWD/jkqtplotter/jkqtpgraphsimpulses.cpp \ $$PWD/jkqtplotter/jkqtpgraphsimpulses.cpp \
$$PWD/jkqtplotter/jkqtpgraphsparsedfunction.cpp \ $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.cpp \

View File

@ -1,290 +1,317 @@
/* /*
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>) Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details. GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL) 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* \defgroup jkqtplotter_elements Plot Elements * \defgroup jkqtplotter_elements Plot Elements
* \ingroup jkqtplotter * \ingroup jkqtplotter
* \defgroup jkqtplotter_plots Graphs * \defgroup jkqtplotter_plots Graphs
* \ingroup jkqtplotter_elements * \ingroup jkqtplotter_elements
*/ */
/** \file jkqtpgraphs.h /** \file jkqtpgraphs.h
* \ingroup jkqtplotter * \ingroup jkqtplotter
*/ */
#include <QString> #include <QString>
#include <QPainter> #include <QPainter>
#include <QPair> #include <QPair>
#include "jkqtplotter/jkqtpgraphs.h" #include "jkqtplotter/jkqtpgraphs.h"
#include "jkqtplottertools/jkqtp_imexport.h" #include "jkqtplottertools/jkqtp_imexport.h"
#include <functional>
#ifndef jkqtpgraphsvaluatedfunction_H
#define jkqtpgraphsvaluatedfunction_H #ifndef jkqtpgraphsevaluatedfunction_H
#define jkqtpgraphsevaluatedfunction_H
/*! \brief type of functions that may be plottet
\ingroup jkqtplotter_plots /*! \brief type of functions that may be plottet
\ingroup jkqtplotter_plots
This is the type of functions \f$ y=f(x, \vec{p}) \f$ that may be plottet by JKQTPxFunctionLineGraph
and JKQTPyFunctionLineGraph. It is possible to supply parameters \f$ \vec{p} \f$ to the function that This is the type of functions \f$ y=f(x, \vec{p}) \f$ that may be plottet by JKQTPxFunctionLineGraph
influence its result. Parameters are given as a pointer to some memory location. The function has to and JKQTPyFunctionLineGraph. It is possible to supply parameters \f$ \vec{p} \f$ to the function that
know on its own how to interpret these. 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$
\ingroup jkqtplotter_plots /*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
\ingroup jkqtplotter_plots
This class implements an intelligent plotting algorithm for functions. It starts by sampling
the function at minSamples positions. Then each function interval is bisected recursively if This class implements an intelligent plotting algorithm for functions. It starts by sampling
necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$ the function at minSamples positions. Then each function interval is bisected recursively if
and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f] and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added
In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f]
distance to the other points. This helps to prevent beats when sampling periodic functions. In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
distance to the other points. This helps to prevent beats when sampling periodic functions.
the following image
\image html plot_functionplots.png the following image
*/ \image html plot_functionplots.png
class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph { */
Q_OBJECT class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
public: Q_OBJECT
public:
enum SpecialFunction {
Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ enum SpecialFunction {
Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
PowerLaw /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */ Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
}; PowerLaw /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
};
/** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtBasePlotter* parent=nullptr); /** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtPlotter* parent); /** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtPlotter* parent);
/** \brief class destructor */
virtual ~JKQTPxFunctionLineGraph(); /** \brief class destructor */
virtual ~JKQTPxFunctionLineGraph();
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter); /** \brief plots the graph to the plotter object specified as parent */
/** \brief plots a key marker inside the specified rectangle \a rect */ virtual void draw(JKQTPEnhancedPainter& painter);
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect); /** \brief plots a key marker inside the specified rectangle \a rect */
/** \brief returns the color to be used for the key label */ virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
virtual QColor getKeyLabelColor(); /** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
/** \brief get the maximum and minimum x-value of the graph
* /** \brief get the maximum and minimum x-value of the graph
* This functions returns 0 for both parameters, so that the plotter uses the predefined *
* min and max values. * This functions returns 0 for both parameters, so that the plotter uses the predefined
*/ * min and max values.
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero); */
/** \brief get the maximum and minimum y-value of the graph virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
*/ /** \brief get the maximum and minimum y-value of the graph
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero); */
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
/** \brief clear the data sampled from the function. */
void clearData(); /** \brief clear the data sampled from the function. */
void clearData();
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(QColor, fillColor) JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(Qt::BrushStyle, fillStyle) JKQTPGET_SET_MACRO(QColor, fillColor)
JKQTPGET_SET_MACRO(Qt::PenStyle, style) JKQTPGET_SET_MACRO(Qt::BrushStyle, fillStyle)
JKQTPGET_SET_MACRO(double, lineWidth) JKQTPGET_SET_MACRO(Qt::PenStyle, style)
JKQTPGET_SET_MACRO(bool, drawLine) JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO_I(jkqtpPlotFunctionType, plotFunction, clearData()) JKQTPGET_SET_MACRO(bool, drawLine)
JKQTPGET_SET_MACRO_I(void*, params, clearData())
/** \brief sets the params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */ /** \brief sets the property plotFunction to the specified \a __value.
void set_params(const QVector<double>& params); *
/** \brief sets the params from a copy of the given array of length \a N */ * \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER>
void set_copiedParams(const double* params, int N); * \see plotFunction for more information */
inline void set_paramsV(double p1) { virtual void set_plotFunction (jkqtpPlotFunctionType && __value);
QVector<double> p; /** \brief sets the property plotFunction to the specified \a __value.
p<<p1; *
set_params(p); * \details Description of the parameter varname is: <CENTER>\copybrief plotFunction.</CENTER>
} * \see plotFunction for more information */
inline void set_paramsV(double p1, double p2) { virtual void set_plotFunction (const jkqtpPlotFunctionType & __value);
QVector<double> p; /** \brief returns the property varname. \see varname for more information */ \
p<<p1<<p2; virtual jkqtpPlotFunctionType get_plotFunction () const;
set_params(p);
} JKQTPGET_SET_MACRO_I(void*, params, clearData())
inline void set_paramsV(double p1, double p2, double p3) { /** \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!!!) */
QVector<double> p; void set_params(const QVector<double>& params);
p<<p1<<p2<<p3; /** \brief sets the params from a copy of the given array of length \a N */
set_params(p); void set_copiedParams(const double* params, int N);
} inline void set_paramsV(double p1) {
inline void set_paramsV(double p1, double p2, double p3, double p4) { QVector<double> p;
QVector<double> p; p<<p1;
p<<p1<<p2<<p3<<p4; set_params(p);
set_params(p); }
} inline void set_paramsV(double p1, double p2) {
inline void set_paramsV(double p1, double p2, double p3, double p4, double p5) { QVector<double> p;
QVector<double> p; p<<p1<<p2;
p<<p1<<p2<<p3<<p4<<p5; set_params(p);
set_params(p); }
} inline void set_paramsV(double p1, double p2, double p3) {
QVector<double> p;
QVector<double> get_internalParams() const; p<<p1<<p2<<p3;
QVector<double> get_internalErrorParams() const; set_params(p);
JKQTPGET_SET_MACRO(unsigned int, minSamples) }
JKQTPGET_SET_MACRO(unsigned int, maxRefinementDegree) inline void set_paramsV(double p1, double p2, double p3, double p4) {
JKQTPGET_SET_MACRO(double, slopeTolerance) QVector<double> p;
JKQTPGET_SET_MACRO(double, minPixelPerSample) p<<p1<<p2<<p3<<p4;
JKQTPGET_SET_MACRO(bool, plotRefinement) set_params(p);
JKQTPGET_SET_MACRO(bool, displaySamplePoints) }
JKQTPGET_SET_MACRO(bool, drawErrorPolygons) inline void set_paramsV(double p1, double p2, double p3, double p4, double p5) {
JKQTPGET_SET_MACRO(bool, drawErrorLines) QVector<double> p;
JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction) p<<p1<<p2<<p3<<p4<<p5;
JKQTPGET_SET_MACRO(void*, errorParams) set_params(p);
/** \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);
QVector<double> get_internalParams() const;
JKQTPGET_SET_MACRO(int, parameterColumn) QVector<double> get_internalErrorParams() const;
JKQTPSET_CAST_MACRO(size_t, int, parameterColumn) JKQTPGET_SET_MACRO(unsigned int, minSamples)
JKQTPGET_SET_MACRO(int, errorParameterColumn) JKQTPGET_SET_MACRO(unsigned int, maxRefinementDegree)
JKQTPSET_CAST_MACRO(size_t, int, errorParameterColumn) JKQTPGET_SET_MACRO(double, slopeTolerance)
JKQTPGET_SET_MACRO(double, minPixelPerSample)
JKQTPGET_SET_MACRO(QColor, errorColor) JKQTPGET_SET_MACRO(bool, plotRefinement)
JKQTPGET_SET_MACRO(QColor, errorFillColor) JKQTPGET_SET_MACRO(bool, displaySamplePoints)
JKQTPGET_SET_MACRO(Qt::BrushStyle, errorFillStyle) JKQTPGET_SET_MACRO(bool, drawErrorPolygons)
JKQTPGET_SET_MACRO(Qt::PenStyle, errorStyle) JKQTPGET_SET_MACRO(bool, drawErrorLines)
JKQTPGET_SET_MACRO(double, errorLineWidth) /** \brief sets the property errorPlotFunction to the specified \a __value.
*
/** \copydoc JKQTPgraph::usesColumn() */ * \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
virtual bool usesColumn(int c); * \see errorPlotFunction for more information */
virtual void set_errorPlotFunction (jkqtpPlotFunctionType && __value);
/** \brief sets the property errorPlotFunction to the specified \a __value.
/** \brief sets function to the given special function */ *
void setSpecialFunction(SpecialFunction function); * \details Description of the parameter varname is: <CENTER>\copybrief errorPlotFunction.</CENTER>
protected: * \see errorPlotFunction for more information */
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */ virtual void set_errorPlotFunction (const jkqtpPlotFunctionType & __value);
int parentPlotStyle; /** \brief returns the property varname. \see varname for more information */ \
virtual jkqtpPlotFunctionType get_errorPlotFunction () const;
struct doublePair { JKQTPGET_SET_MACRO(void*, errorParams)
double x; /** \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!!!) */
double f; void set_errorParams(const QVector<double>& errorParams);
doublePair* next;
}; JKQTPGET_SET_MACRO(int, parameterColumn)
/** \brief a linked list holding the datapoints \f$ \left(x, y=f(x, \vec{p})\right) \f$ to be plotted */ JKQTPSET_CAST_MACRO(size_t, int, parameterColumn)
doublePair* data; JKQTPGET_SET_MACRO(int, errorParameterColumn)
JKQTPSET_CAST_MACRO(size_t, int, errorParameterColumn)
/** \brief fill the data array with data from the function plotFunction */
virtual void createPlotData( bool collectParams=true); JKQTPGET_SET_MACRO(QColor, errorColor)
JKQTPGET_SET_MACRO(QColor, errorFillColor)
virtual void collectParameters(); JKQTPGET_SET_MACRO(Qt::BrushStyle, errorFillStyle)
JKQTPGET_SET_MACRO(Qt::PenStyle, errorStyle)
void refine(doublePair* a, doublePair* b, unsigned int degree=0); JKQTPGET_SET_MACRO(double, errorLineWidth)
int parameterColumn; /** \copydoc JKQTPgraph::usesColumn() */
int errorParameterColumn; virtual bool usesColumn(int c);
/** \brief color of the graph */
QColor color; /** \brief sets function to the given special function */
/** \brief color of the graph fill */ void setSpecialFunction(SpecialFunction function);
QColor fillColor; protected:
/** \brief linestyle of the graph lines */ /** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
Qt::PenStyle style; int parentPlotStyle;
/** \brief width (pixels) of the graph */
double lineWidth; struct doublePair {
/** \brief fill style, if the curve should be filled */ double x;
Qt::BrushStyle fillStyle; double f;
/** \brief indicates whether to draw a line or not */ doublePair* next;
bool drawLine; };
/** \brief indicates whether to fill the space between the curve and the x-axis */ /** \brief a linked list holding the datapoints \f$ \left(x, y=f(x, \vec{p})\right) \f$ to be plotted */
bool fillCurve; doublePair* data;
/** \brief the function to be plotted */
jkqtpPlotFunctionType plotFunction; /** \brief fill the data array with data from the function plotFunction */
/** \brief pointer to the parameters supplied to the plotting funtion */ virtual void createPlotData( bool collectParams=true);
void* params;
/** \brief the minimum number of points to evaluate the function at */ virtual void collectParameters();
unsigned int minSamples;
/** \brief the maximum number of recursive refinement steps void refine(doublePair* a, doublePair* b, unsigned int degree=0);
*
* each step bisects the interval \f$ [a, b] \f$ into two halfes. So the maximum number /** \brief if set, the values from this datatsore column are used for the parameters \c p1 , \c p2 , \c p3 , ... of the plot function */
* of points plotted at all are thus: int parameterColumn;
* \f[ \mbox{minSamples} \cdot 2^{\mbox{maxRefinementDegree}} \f] /** \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;
unsigned int maxRefinementDegree;
/** \brief the tolerance for the difference of two subsequent slopes */ /** \brief color of the graph */
double slopeTolerance; QColor color;
/** \brief create one sample at least every \a minPixelPerSample pixels */ /** \brief color of the graph fill */
double minPixelPerSample; QColor fillColor;
/** \brief switch on or off [default: on] the plot refinement algorithm */ /** \brief linestyle of the graph lines */
bool plotRefinement; Qt::PenStyle style;
/** \brief if true [default: off] display the points where the function has been sampled */ /** \brief width (pixels) of the graph */
bool displaySamplePoints; double lineWidth;
/** \brief indicates whether an error polygon should be drawn */ /** \brief fill style, if the curve should be filled */
bool drawErrorPolygons; Qt::BrushStyle fillStyle;
/** \brief indicates whether error lines should be drawn */ /** \brief indicates whether to draw a line or not */
bool drawErrorLines; bool drawLine;
/** \brief this function calculates the error at a given position */ /** \brief indicates whether to fill the space between the curve and the x-axis */
jkqtpPlotFunctionType errorPlotFunction; bool fillCurve;
/** \brief parameters for errorFunction */ /** \brief the function to be plotted */
void* errorParams; jkqtpPlotFunctionType plotFunction;
/** \brief color of the error graph */ /** \brief pointer to the parameters supplied to the plotting funtion */
QColor errorColor; void* params;
/** \brief color of the error graph fill */ /** \brief the minimum number of points to evaluate the function at */
QColor errorFillColor; unsigned int minSamples;
/** \brief linestyle of the error graph lines */ /** \brief the maximum number of recursive refinement steps
Qt::PenStyle errorStyle; *
/** \brief width (pixels) of the error graph */ * each step bisects the interval \f$ [a, b] \f$ into two halfes. So the maximum number
double errorLineWidth; * of points plotted at all are thus:
/** \brief fill style, if the error curve should be filled */ * \f[ \mbox{minSamples} \cdot 2^{\mbox{maxRefinementDegree}} \f]
Qt::BrushStyle errorFillStyle; */
unsigned int maxRefinementDegree;
/** \brief the tolerance for the difference of two subsequent slopes */
QBrush getBrush(JKQTPEnhancedPainter& painter) const; double slopeTolerance;
QPen getLinePen(JKQTPEnhancedPainter& painter) const; /** \brief create one sample at least every \a minPixelPerSample pixels */
double minPixelPerSample;
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const; /** \brief switch on or off [default: on] the plot refinement algorithm */
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const; bool plotRefinement;
/** \brief if true [default: off] display the points where the function has been sampled */
QVector<double> iparams, ierrorparams; bool displaySamplePoints;
}; /** \brief indicates whether an error polygon should be drawn */
bool drawErrorPolygons;
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$ /** \brief indicates whether error lines should be drawn */
\ingroup jkqtplotter_plots bool drawErrorLines;
/** \brief this function calculates the error at a given position */
*/ jkqtpPlotFunctionType errorPlotFunction;
class LIB_EXPORT JKQTPyFunctionLineGraph: public JKQTPxFunctionLineGraph { /** \brief parameters for errorFunction */
Q_OBJECT void* errorParams;
public: /** \brief color of the error graph */
/** \brief class constructor */ QColor errorColor;
inline JKQTPyFunctionLineGraph(JKQtBasePlotter* parent=nullptr):JKQTPxFunctionLineGraph(parent) {} /** \brief color of the error graph fill */
/** \brief class constructor */ QColor errorFillColor;
inline JKQTPyFunctionLineGraph(JKQtPlotter* parent):JKQTPxFunctionLineGraph(parent) {} /** \brief linestyle of the error graph lines */
Qt::PenStyle errorStyle;
/** \brief plots the graph to the plotter object specified as parent */ /** \brief width (pixels) of the error graph */
virtual void draw(JKQTPEnhancedPainter& painter); double errorLineWidth;
protected: /** \brief fill style, if the error curve should be filled */
Qt::BrushStyle errorFillStyle;
/** \brief fill the data array with data from the function plotFunction */
virtual void createPlotData( bool collectParams=true);
QBrush getBrush(JKQTPEnhancedPainter& painter) const;
}; QPen getLinePen(JKQTPEnhancedPainter& painter) const;
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const;
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
#endif // jkqtpgraphsvaluatedfunction_H QVector<double> iparams, ierrorparams;
};
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
\ingroup jkqtplotter_plots
*/
class LIB_EXPORT JKQTPyFunctionLineGraph: public JKQTPxFunctionLineGraph {
Q_OBJECT
public:
/** \brief class constructor */
inline JKQTPyFunctionLineGraph(JKQtBasePlotter* parent=nullptr):JKQTPxFunctionLineGraph(parent) {}
/** \brief class constructor */
inline JKQTPyFunctionLineGraph(JKQtPlotter* parent):JKQTPxFunctionLineGraph(parent) {}
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
protected:
/** \brief fill the data array with data from the function plotFunction */
virtual void createPlotData( bool collectParams=true);
};
#endif // jkqtpgraphsevaluatedfunction_H

View File

@ -26,11 +26,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <QDebug> #include <QDebug>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <utility>
double JKQTPxParsedFunctionLineGraphFunction(double x, void* data) { double JKQTPxParsedFunctionLineGraphFunction(double x, void* data) {
JKQTPxParsedFunctionLineGraphFunctionData* d=(JKQTPxParsedFunctionLineGraphFunctionData*)data; JKQTPxParsedFunctionLineGraph::JKQTPxParsedFunctionLineGraphFunctionData* d=(JKQTPxParsedFunctionLineGraph::JKQTPxParsedFunctionLineGraphFunctionData*)data;
if (d && d->parser && d->node) { if (d && d->parser && d->node) {
try { try {
d->parser->addVariableDouble("x", x); d->parser->addVariableDouble("x", x);
@ -102,6 +102,14 @@ JKQTPxParsedFunctionLineGraph::~JKQTPxParsedFunctionLineGraph()
delete efdata.parser; 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*/) void JKQTPxParsedFunctionLineGraph::createPlotData(bool /*collectParams*/)
{ {
collectParameters(); collectParameters();

View File

@ -27,19 +27,13 @@
#include "jkqtplottertools/jkqtptools.h" #include "jkqtplottertools/jkqtptools.h"
#include "jkqtplottertools/jkqtpmathparser.h" #include "jkqtplottertools/jkqtpmathparser.h"
#include "jkqtplottertools/jkqtp_imexport.h" #include "jkqtplottertools/jkqtp_imexport.h"
#include "jkqtplotter/jkqtpgraphsvaluatedfunction.h" #include "jkqtplotter/jkqtpgraphsevaluatedfunction.h"
// forward declarations // forward declarations
class JKQtBasePlotter; class JKQtBasePlotter;
class JKQtPlotter; 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 /*! \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 \ingroup jkqtplotter_plots
@ -63,26 +57,34 @@ class LIB_EXPORT JKQTPxParsedFunctionLineGraph: public JKQTPxFunctionLineGraph {
JKQTPGET_SET_MACRO(QList<double>, parameters) JKQTPGET_SET_MACRO(QList<double>, parameters)
JKQTPGET_SET_MACRO(QString, function) JKQTPGET_SET_MACRO(QString, function)
JKQTPGET_SET_MACRO(int, parameterColumn)
JKQTPGET_SET_MACRO(QList<double>, errorParameters) JKQTPGET_SET_MACRO(QList<double>, errorParameters)
JKQTPGET_SET_MACRO(QString, errorFunction) 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: protected:
/** \brief the function to be evaluated for the plot. Use \c x as the free variable, e.g. \c "x^2+2" */
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
QString function; QString function;
/** \brief values of the parameters \c p1 , \c p2 , \c p3 , ... */
QList<double> parameters; QList<double> parameters;
JKQTPxParsedFunctionLineGraphFunctionData fdata; 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; QString errorFunction;
/** \brief values of the parameters \c p1 , \c p2 , \c p3 , ... for the error function*/
QList<double> errorParameters; QList<double> errorParameters;
JKQTPxParsedFunctionLineGraphFunctionData efdata; 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_I(void*, params, clearData())
JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction) JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction)
JKQTPGET_SET_MACRO(void*, errorParams) JKQTPGET_SET_MACRO(void*, errorParams)

View File

@ -1079,6 +1079,7 @@ JKQTPMathParser::jkmpTokenType JKQTPMathParser::getToken(){
// else // else
program->putback(ch1); program->putback(ch1);
jkmpError("undefined operator '&'; Did you mean LOGICAL_AND ('&&' / 'and')?"); jkmpError("undefined operator '&'; Did you mean LOGICAL_AND ('&&' / 'and')?");
break;
} }
case '|':{ case '|':{
char ch1=0; char ch1=0;
@ -1087,6 +1088,7 @@ JKQTPMathParser::jkmpTokenType JKQTPMathParser::getToken(){
// else // else
program->putback(ch1); program->putback(ch1);
jkmpError("undefined operator '|'; Did you mean LOGICAL_OR ('||' / 'or')?"); jkmpError("undefined operator '|'; Did you mean LOGICAL_OR ('||' / 'or')?");
break;
} }
case '=':{ case '=':{
char ch1=0; char ch1=0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View 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(&params3);
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/)

View File

@ -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(&params3);
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();
}

View File

@ -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

View File

@ -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

View 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/)

View File

@ -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();
}

View File

@ -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

View File

@ -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