diff --git a/JKQtPlotterBuildAllExamples.pro b/JKQtPlotterBuildAllExamples.pro index 0c0ed5e3c5..deaa934880 100644 --- a/JKQtPlotterBuildAllExamples.pro +++ b/JKQtPlotterBuildAllExamples.pro @@ -86,6 +86,7 @@ addSimpleTest(datastore_regression) addSimpleTest(datastore_groupedstat) addSimpleTest(contourplot) addSimpleTest(violinplot) +addSimpleTest(evalcurve) #addSimpleTest(rgbimageplot_opencv) #addSimpleTest(imageplot_opencv) diff --git a/doc/dox/examples_and_tutorials.dox b/doc/dox/examples_and_tutorials.dox index eb9705e9d3..27693b23ea 100644 --- a/doc/dox/examples_and_tutorials.dox +++ b/doc/dox/examples_and_tutorials.dox @@ -56,6 +56,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int \image html parsedfunctionplot_small.png \subpage JKQTPlotterParsedFunctionPlot `JKQTPXParsedFunctionLineGraph`
plotting functions with the internal math equation parser/evaluator + \image html evalcurve_small.png + \subpage JKQTPlotterEvalCurves + `JKQTPXYFunctionLineGraph` \image html boxplot_small.png \subpage JKQTPlotterBoxplotsGraphs `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph`, ... diff --git a/doc/dox/jkqtplotter.dox b/doc/dox/jkqtplotter.dox index af030660d0..2bf565d748 100644 --- a/doc/dox/jkqtplotter.dox +++ b/doc/dox/jkqtplotter.dox @@ -356,7 +356,10 @@ This group assembles graphs that show their data with symbols and optionally wit Classes \image html functionplot_small.png - JKQTPXParsedFunctionLineGraph, JKQTPYParsedFunctionLineGraph + JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph + + \image html evalcurve_small.png + JKQTPXYFunctionLineGraph \defgroup jkqtplotter_parsedFgraphs Parsed Function Graphs @@ -368,7 +371,7 @@ This group assembles graphs that show their data with symbols and optionally wit Classes \image html functionplot_small.png - JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph + JKQTPXParsedFunctionLineGraph, JKQTPYParsedFunctionLineGraph \defgroup jkqtplotter_barssticks Barcharts, Impulse-Charts, ... diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index ab85bc34a2..5b55d92c04 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -25,6 +25,7 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
  • 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: added geometric plot objects JKQTPGeoArrow to draw arrows (aka lines with added line-end decorators, also extended JKQTPGeoLine, JKQTPGeoInfiniteLine, JKQTPGeoPolyLines to draw line-end decorator (aka arrows)
  • 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
  • +
  • new: a new graph class JKQTPXYFunctionLineGraph draws parametric 2D curves ( \f$ [x,y] = f(t) \f$ ), see \ref JKQTPlotterEvalCurves for an example
  • \subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download diff --git a/doc/images/plot_evalcurve.png b/doc/images/plot_evalcurve.png new file mode 100644 index 0000000000..38643cd913 Binary files /dev/null and b/doc/images/plot_evalcurve.png differ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 36d6c4fbc6..e2e4670dbb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -58,5 +58,6 @@ add_subdirectory(symbols_and_styles) add_subdirectory(ui) add_subdirectory(user_interaction) add_subdirectory(violinplot) +add_subdirectory(evalcurve) diff --git a/examples/README.md b/examples/README.md index 4473084bf8..94a38933a3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -22,6 +22,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/parametriccurve_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/parametriccurve) | [Plotting Parametric Curves](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/parametriccurve) | `JKQTPXYLineGraph` and `JKQTPXYParametrizedScatterGraph`
    C++-style QVector as plot data
    parametric curve plotting | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/functionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) | [Plotting Mathematical Functions as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) | `JKQTPXFunctionLineGraph`
    diretly plotting C/C++-functions | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/parsedfunctionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/parsedfunctionplot) | [Plotting Parsed Mathematical Functions as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/parsedfunctionplot) | `JKQTPXParsedFunctionLineGraph`
    plotting functions with the internal math equation parser/evaluator | +| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/evalcurve_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/evalcurve) | [Plotting Parametric Mathematical Curves as Line Graphs](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/evalcurve) | `JKQTPXYFunctionLineGraph` | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/boxplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/boxplot) | [Plotting Box Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/boxplot) | `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph` | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/violinplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/violinplot) | [Plotting Violin Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/violinplot) | `JKQTPViolinplotVerticalElement`, `JKQTPViolinplotHorizontalElement` | diff --git a/examples/evalcurve/CMakeLists.txt b/examples/evalcurve/CMakeLists.txt new file mode 100644 index 0000000000..19dada8fe3 --- /dev/null +++ b/examples/evalcurve/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.0) + +set(EXAMPLE_NAME evalcurve) +set(EXENAME jkqtptest_${EXAMPLE_NAME}) + +message( STATUS ".. Building Example ${EXAMPLE_NAME}" ) + + +# Set up source files +set(SOURCES ${EXAMPLE_NAME}.cpp) +set(HEADERS ) +set(RESOURCES ) +set(UIS ) + +add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS}) +target_include_directories(${EXENAME} PRIVATE ../../lib) +if(JKQtPlotter_BUILD_STATIC_LIBS) + target_link_libraries(${EXENAME} JKQTPlotterLib) +elseif(JKQtPlotter_BUILD_SHARED_LIBS) + target_link_libraries(${EXENAME} JKQTPlotterSharedLib) +endif() + + + +# Installation +install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +#Installation of Qt DLLs on Windows +jkqtplotter_deployqt(${EXENAME}) diff --git a/examples/evalcurve/README.md b/examples/evalcurve/README.md new file mode 100644 index 0000000000..a0ac644885 --- /dev/null +++ b/examples/evalcurve/README.md @@ -0,0 +1,42 @@ +# Example (JKQTPlotter): Plotting Parametric Mathematical Curves as Line Graphs {#JKQTPlotterEvalCurves} +## Basics +This project (see `./examples/evalcurve/`) demonstrates how to plot mathematical functions as line graphs. The functions may be defined as static C functions, C++ functors or c++ inline functions. + +[TOC] + +# Simple C++ inline function +The example shows how to plot a simple C++ inline function: + +```.cpp + JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot); + func1->setPlotFunctionFunctor([](double t) -> QPointF { + const double a=5; + const double b=4; + const double delta=JKQTPSTATISTICS_PI/4.0; + return QPointF(sin(a*t+delta), sin(b*t)); + }); + func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI); + func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$"); + plot->addGraph(func1); +``` + +Note that here a functor is defined, which calculates the points on a [Lissajous Curve](https://en.wikipedia.org/wiki/Lissajous_curve), i.e. a function mapping a parameter `t` to a two-dimensional point `QPointF` with `x=sin(a*t+delta)`and `y=sin(b*t)`. This function is evaluated on a range of values for `t`, set by + +```.cpp + func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI); +``` + +The class uses an adaptive algorithm, which determines by the local slope, at how many points (or how close points) the functor has to be evaluated. + +# Screenshot + +This code snippets above result in a plot like this: + +![evalcurve](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/evalcurve.png) + +# Notes + +Just as shown in [examples/functionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) for JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph, different types of functions can be used to plot. Either simple C++ inline functions, that take a `double t` and return a `QPointF`, or functions that additionally take a parameter vector `void* params`. In that case, the parameters may be provided from different sources, as described in [examples/functionplot](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/functionplot) . + + + diff --git a/examples/evalcurve/evalcurve.cpp b/examples/evalcurve/evalcurve.cpp new file mode 100644 index 0000000000..11c82eed45 --- /dev/null +++ b/examples/evalcurve/evalcurve.cpp @@ -0,0 +1,52 @@ +/** \example evalcurve.cpp + * Shows how to plot Mathematical Functions as Line Graphs with JKQTPlotter (as evaluated C/C++ functions) + * + * \ref JKQTPlotterEvalCurves + */ + +#include +#include +#include +#include "jkqtplotter/jkqtplotter.h" +#include "jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h" + + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + + // 1. create a window that contains a line-edit to edit a function + // and a JKQTPlotter to display the function, combine everything in a layout + QWidget mainWin; + JKQTPlotter* plot=new JKQTPlotter(&mainWin); + QVBoxLayout* layout=new QVBoxLayout; + mainWin.setLayout(layout); + layout->addWidget(plot); + + // 2. now we add a JKQTPXYFunctionLineGraph object, which will draw a simple function + // the function is defined as C++ inline function + JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot); + func1->setPlotFunctionFunctor([](double t) ->QPointF { + const double a=5; + const double b=4; + const double delta=JKQTPSTATISTICS_PI/4.0; + return QPointF(sin(a*t+delta), sin(b*t)); + }); + func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI); + func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$"); + plot->addGraph(func1); + // 8. set some axis properties (we use LaTeX for nice equation rendering) + plot->getXAxis()->setAxisLabel(QObject::tr("x-axis")); + plot->getYAxis()->setAxisLabel(QObject::tr("y-axis")); + plot->getPlotter()->setKeyPosition(JKQTPKeyOutsideBottomLeft); + + + // 4. scale the plot so the graph is contained + plot->setXY(-1.1,1.1,-1.1,1.1); + + // show window and make it a decent size + mainWin.show(); + mainWin.resize(800,800); + + return app.exec(); +} diff --git a/examples/evalcurve/evalcurve.pro b/examples/evalcurve/evalcurve.pro new file mode 100644 index 0000000000..6aa71828aa --- /dev/null +++ b/examples/evalcurve/evalcurve.pro @@ -0,0 +1,28 @@ +# source code for this simple demo +SOURCES = evalcurve.cpp + +# configure Qt +CONFIG += link_prl qt +QT += core gui xml svg +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport + +# output executable name +TARGET = evalcurve + + +# include JKQTPlotter source code +DEPENDPATH += ../../lib ../../qmake/staticlib/jkqtplotterlib +INCLUDEPATH += ../../lib +CONFIG (debug, debug|release) { + LIBS += -L../../qmake/staticlib/jkqtplotterlib/debug -ljkqtplotterlib_debug +} else { + LIBS += -L../../qmake/staticlib/jkqtplotterlib/release -ljkqtplotterlib +} +message("LIBS = $$LIBS") + +win32-msvc*: DEFINES += _USE_MATH_DEFINES +win32-msvc*: DEFINES += NOMINMAX + + + + diff --git a/examples/evalcurve/evalcurve_and_lib.pro b/examples/evalcurve/evalcurve_and_lib.pro new file mode 100644 index 0000000000..87a4b001f1 --- /dev/null +++ b/examples/evalcurve/evalcurve_and_lib.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs + +SUBDIRS += jkqtplotterlib evalcurve + +jkqtplotterlib.file = ../../qmake/staticlib/jkqtplotterlib/jkqtplotterlib.pro + +evalcurve.file=$$PWD/evalcurve.pro +evalcurve.depends = jkqtplotterlib diff --git a/lib/jkqtcommon/jkqtpgeometrytools.cpp b/lib/jkqtcommon/jkqtpgeometrytools.cpp index c1fd561681..4afd2f1332 100644 --- a/lib/jkqtcommon/jkqtpgeometrytools.cpp +++ b/lib/jkqtcommon/jkqtpgeometrytools.cpp @@ -69,13 +69,10 @@ QVector JKQTPSplitEllipseIntoPoints(std::function fT std::function fell=[&](double t)->QPointF { return QPointF(x+a*cos(t)*cosa-b*sin(t)*sina, y+a*cos(t)*sina+b*sin(t)*cosa); }; - std::function fx = [&](double t) ->double { - return fTransform(fell(t)).x(); + std::function fxy = [&](double t) ->QPointF { + return fTransform(fell(t)); }; - std::function fy = [&](double t) ->double { - return fTransform(fell(t)).y(); - }; - JKQTPAdaptiveFunctionGraphEvaluator eval(fx, fy); + JKQTPAdaptiveFunctionGraphEvaluator eval(fxy); const QVector points=eval.evaluate(angle_start*JKQTPSTATISTICS_PI/180.0, angle_end*JKQTPSTATISTICS_PI/180.0); if (points.size()>0) { @@ -238,6 +235,17 @@ QVector JKQTPSimplyfyLineSegemnts(const QVector &points, doubl JKQTPAdaptiveFunctionGraphEvaluator::JKQTPAdaptiveFunctionGraphEvaluator(const std::function &fx_, const std::function &fy_, unsigned int minSamples_, unsigned int maxRefinementDegree_, double slopeTolerance_, double minPixelPerSample_): fx(fx_), fy(fy_), + fxy([&](double t)->QPointF { return QPointF(fx(t), fy(t)); }), + minSamples(minSamples_), + maxRefinementDegree(maxRefinementDegree_), + slopeTolerance(slopeTolerance_), + minPixelPerSample(minPixelPerSample_) +{ + +} + +JKQTPAdaptiveFunctionGraphEvaluator::JKQTPAdaptiveFunctionGraphEvaluator(const std::function &fxy_, unsigned int minSamples_, unsigned int maxRefinementDegree_, double slopeTolerance_, double minPixelPerSample_): + fxy(fxy_), minSamples(minSamples_), maxRefinementDegree(maxRefinementDegree_), slopeTolerance(slopeTolerance_), @@ -252,19 +260,19 @@ QVector JKQTPAdaptiveFunctionGraphEvaluator::evaluate(double tmin, doub double delta_t0=(tmax-tmin)/static_cast(minSamples); - intData.push_front(std::pair(tmin, QPointF(fx(tmin), fy(tmin)))); + intData.push_front(std::pair(tmin, fxy(tmin))); InternalList::iterator a=intData.begin(); //qDebug()<<"**************************************************"; for (double t=tmin+delta_t0; t(treal, QPointF(fx(treal), fy(treal)))); + intData.insert_after(a, std::pair(treal, fxy(treal))); InternalList::iterator b=a; b++; //qDebug()<<"t="< jkqtpPlotFunctionType; -/*! \brief simplified type of functions (without parameters) that may be plottet +/*! \brief simplified type of functions (without parameters) that may be plotted by JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph \ingroup jkqtplotter_functiongraphs This is the type of functions \f$ y=f(x) \f$ that may be plottet by JKQTPXFunctionLineGraph @@ -63,10 +63,11 @@ typedef std::function jkqtpSimplePlotFunctionType; 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 + The following image shows some example graphs: + \image html plot_functionplots.png - \see \ref JKQTPlotterFunctionPlots, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression() + \see \ref JKQTPlotterFunctionPlots, JKQTPYFunctionLineGraph, JKQTPXYFunctionLineGraph, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression() */ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin { Q_OBJECT @@ -94,6 +95,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr); /** \brief class constructor */ JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(SpecialFunction type, const QVector& params, const QString& title, JKQTBasePlotter* parent); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(SpecialFunction type, const QVector& params, const QString& title, JKQTPlotter* parent); /** \brief class destructor */ virtual ~JKQTPXFunctionLineGraph() override; @@ -292,7 +297,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public /** \brief fill the data array with data from the function plotFunction */ virtual void createPlotData( bool collectParams=true); - + /** \brief ensure that current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams and ierrorparams */ virtual void collectParameters(); /** \brief refine datapoints on the function graph between two evaluations \a a and \a b */ void refine(doublePair* a, doublePair* b, unsigned int degree=0); @@ -357,14 +362,20 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const; QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const; - - QVector iparams, ierrorparams; + /** \brief internal storage for the current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) */ + QVector iparams; + /** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */ + QVector ierrorparams; }; /*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$ \ingroup jkqtplotter_functiongraphs - \see \ref JKQTPlotterFunctionPlots + The following image shows some example graphs: + + \image html functionplot_fy.png + + \see \ref JKQTPlotterFunctionPlots , JKQTPXFunctionLineGraph, JKQTPXYFunctionLineGraph */ class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineGraph { Q_OBJECT @@ -381,6 +392,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineG JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr); /** \brief class constructor */ JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(SpecialFunction type, const QVector& params, const QString& title, JKQTBasePlotter* parent); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(SpecialFunction type, const QVector& params, const QString& title, JKQTPlotter* parent); /** \brief plots the graph to the plotter object specified as parent */ virtual void draw(JKQTPEnhancedPainter& painter) override; diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp new file mode 100644 index 0000000000..9f7e50fd24 --- /dev/null +++ b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp @@ -0,0 +1,514 @@ +/* + Copyright (c) 2020-2020 Jan W. Krieger () + + + + 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 + the Free Software Foundation, either version 2.1 of the License, or + (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 . +*/ + + + +#include "jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h" +#include "jkqtplotter/jkqtpbaseplotter.h" +#include +#include +#include +#include "jkqtplotter/jkqtptools.h" +#include "jkqtplotter/graphs/jkqtpimage.h" +#include "jkqtplotter/jkqtpbaseelements.h" +#include "jkqtplotter/jkqtplotter.h" + +#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgzgetPlotter()) +{ + +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCurveFunctionType &f, const QString &title_, double tmin_, double tmax_, JKQTBasePlotter *parent): + JKQTPXYFunctionLineGraph(parent) +{ + tmin=tmin_; + tmax=tmax_; + title=title_; + plotFunction=jkqtpParametricCurveFunctionType(); + simplePlotFunction=f; + data.clear(); +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCurveFunctionType &f, const QString &title_, double tmin_, double tmax_, JKQTPlotter *parent): + JKQTPXYFunctionLineGraph(f, title_, tmin_, tmax_, parent->getPlotter()) +{ + +} + + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpSimpleParametricCurveFunctionType &&f, const QString &title_, double tmin_, double tmax_, JKQTBasePlotter *parent): + JKQTPXYFunctionLineGraph(parent) +{ + tmin=tmin_; + tmax=tmax_; + title=title_; + plotFunction=jkqtpParametricCurveFunctionType(); + simplePlotFunction=std::move(f); + data.clear(); +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpSimpleParametricCurveFunctionType &&f, const QString &title_, double tmin_, double tmax_, JKQTPlotter *parent): + JKQTPXYFunctionLineGraph(std::forward(f), title_, tmin_, tmax_, parent->getPlotter()) +{ + +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpParametricCurveFunctionType &&f, const QString &title_, double tmin_, double tmax_, JKQTBasePlotter *parent): + JKQTPXYFunctionLineGraph(parent) +{ + tmin=tmin_; + tmax=tmax_; + title=title_; + simplePlotFunction=jkqtpSimpleParametricCurveFunctionType(); + plotFunction=std::move(f); + data.clear(); +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(jkqtpParametricCurveFunctionType &&f, const QString &title_, double tmin_, double tmax_, JKQTPlotter *parent): + JKQTPXYFunctionLineGraph(std::forward(f), title_, tmin_, tmax_, parent->getPlotter()) +{ + +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFunctionType &f, const QString &title_, double tmin_, double tmax_, JKQTBasePlotter *parent): + JKQTPXYFunctionLineGraph(parent) +{ + tmin=tmin_; + tmax=tmax_; + title=title_; + simplePlotFunction=jkqtpSimpleParametricCurveFunctionType(); + plotFunction=std::move(f); + data.clear(); +} + +JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFunctionType &f, const QString &title_, double tmin_, double tmax_, JKQTPlotter *parent): + JKQTPXYFunctionLineGraph(f, title_, tmin_, tmax_, parent->getPlotter()) +{ + +} + +JKQTPXYFunctionLineGraph::~JKQTPXYFunctionLineGraph() { + data.clear(); +} + + + +void JKQTPXYFunctionLineGraph::setPlotFunctionFunctor(const jkqtpParametricCurveFunctionType &__value) +{ + simplePlotFunction=jkqtpSimpleParametricCurveFunctionType(); + plotFunction = __value; + data.clear(); +} + +void JKQTPXYFunctionLineGraph::setPlotFunctionFunctor(const jkqtpSimpleParametricCurveFunctionType &__value) +{ + plotFunction=jkqtpParametricCurveFunctionType(); + simplePlotFunction=__value; + data.clear(); +} + +void JKQTPXYFunctionLineGraph::setPlotFunctionFunctor(jkqtpParametricCurveFunctionType &&__value) +{ + simplePlotFunction=jkqtpSimpleParametricCurveFunctionType(); + plotFunction = std::move(__value); + data.clear(); +} + +void JKQTPXYFunctionLineGraph::setPlotFunctionFunctor(jkqtpSimpleParametricCurveFunctionType &&__value) +{ + plotFunction=jkqtpParametricCurveFunctionType(); + simplePlotFunction=std::move(__value); + data.clear(); +} + +jkqtpParametricCurveFunctionType JKQTPXYFunctionLineGraph::getPlotFunctionFunctor() const +{ + return plotFunction; +} + +jkqtpSimpleParametricCurveFunctionType JKQTPXYFunctionLineGraph::getSimplePlotFunction() const +{ + return simplePlotFunction; +} + +void JKQTPXYFunctionLineGraph::setParams(void *__value) +{ + if (this->params != __value) { + this->params = __value; + data.clear(); + } +} + +void *JKQTPXYFunctionLineGraph::getParams() const +{ + return this->params; +} + + +void JKQTPXYFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + QPen p=getLinePen(painter, parent); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen np(Qt::NoPen); + const double y=rect.top()+rect.height()/2.0; + painter.setPen(np); + painter.setPen(p); + painter.drawLine(QLineF(rect.left(), y, rect.right(), y)); +} + +QColor JKQTPXYFunctionLineGraph::getKeyLabelColor() const { + return getLineColor(); +} + +bool JKQTPXYFunctionLineGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) +{ + if (data.size()==0) createPlotData(); + if (data.size()>0){ + bool start=true; + minx=0; + maxx=0; + smallestGreaterZero=0; + + for (auto const& d: data) { + if (JKQTPIsOKFloat(d.x())) { + if (start || d.x()>maxx) maxx=d.x(); + if (start || d.x()0){ + bool start=true; + miny=0; + maxy=0; + smallestGreaterZero=0; + + for (auto const& d: data) { + if (JKQTPIsOKFloat(d.y())) { + if (start || d.y()>maxy) maxy=d.y(); + if (start || d.y() QPointF { return plot->transform(func(t)); }, this, std::placeholders::_1); + + JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample); + data=evaluator.evaluate(tmin, tmax); + +} + +void JKQTPXYFunctionLineGraph::collectParameters() +{ + if (parent && parameterColumn>=0) { + iparams.clear(); + JKQTPDatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=static_cast(datastore->getRows(parameterColumn)); + + for (int i=imin; iget(parameterColumn,i); + iparams<=0 && !JKQTPIsOKFloat(iparams[i])) { + iparams.remove(i,1); + i--; + } + + //qDebug()<<"iparams:"; + //for (i=0; igetDatastore(); + if (datastore==nullptr) return; + + //qDebug()<<"start plot\n"; + createPlotData(); + //qDebug()<<"plot data created\n"; + + drawErrorsBefore(painter); + { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + + QPen p=getLinePen(painter, parent); + QPen np(Qt::NoPen); + + + { + painter.save(); auto __finalpaintline=JKQTPFinally([&painter]() {painter.restore();}); + painter.setPen(p); + painter.drawPolyline(data); + } + + + QColor c=getLineColor(); + c.setHsv(fmod(c.hue()+90, 360), c.saturation(), c.value()); + if (displaySamplePoints) { + painter.save(); auto __finalpaintsamplepoints=JKQTPFinally([&painter]() {painter.restore();}); + for (const auto& d: data) { + if (JKQTPIsOKFloat(d.x()) && JKQTPIsOKFloat(d.x())) { + JKQTPPlotSymbol(painter, d.x(), d.y(), JKQTPCross, 6,1*parent->getLineWidthMultiplier(), c, QColor(Qt::transparent)); + } + } + + } + } + drawErrorsAfter(painter); + //std::cout<<"plot done\n"; +} + + + + + +void JKQTPXYFunctionLineGraph::setParams(const QVector ¶ms) +{ + iparams=params; + setParams(&iparams); +} + +void JKQTPXYFunctionLineGraph::setCopiedParams(const double *params, int N) +{ + QVector v; + for (int i=0; i p; + p< p; + p< p; + p< p; + p< p; + p<parameterColumn = __value; +} + +int JKQTPXYFunctionLineGraph::getParameterColumn() const +{ + return this->parameterColumn; +} + +void JKQTPXYFunctionLineGraph::setParameterColumn(size_t __value) { + this->parameterColumn = static_cast(__value); +} + + +QVector JKQTPXYFunctionLineGraph::getInternalParams() const { + return iparams; +} + +void JKQTPXYFunctionLineGraph::setMinSamples(const unsigned int &__value) +{ + this->minSamples = __value; +} + +unsigned int JKQTPXYFunctionLineGraph::getMinSamples() const +{ + return this->minSamples; +} + +void JKQTPXYFunctionLineGraph::setMaxRefinementDegree(const unsigned int &__value) +{ + this->maxRefinementDegree = __value; +} + +unsigned int JKQTPXYFunctionLineGraph::getMaxRefinementDegree() const +{ + return this->maxRefinementDegree; +} + +void JKQTPXYFunctionLineGraph::setSlopeTolerance(double __value) +{ + this->slopeTolerance = __value; +} + +double JKQTPXYFunctionLineGraph::getSlopeTolerance() const +{ + return this->slopeTolerance; +} + +void JKQTPXYFunctionLineGraph::setMinPixelPerSample(double __value) +{ + this->minPixelPerSample = __value; +} + +double JKQTPXYFunctionLineGraph::getMinPixelPerSample() const +{ + return this->minPixelPerSample; +} + +void JKQTPXYFunctionLineGraph::setPlotRefinement(bool __value) +{ + this->plotRefinement = __value; +} + +bool JKQTPXYFunctionLineGraph::getPlotRefinement() const +{ + return this->plotRefinement; +} + +void JKQTPXYFunctionLineGraph::setDisplaySamplePoints(bool __value) +{ + this->displaySamplePoints = __value; +} + +bool JKQTPXYFunctionLineGraph::getDisplaySamplePoints() const +{ + return this->displaySamplePoints; +} + + +bool JKQTPXYFunctionLineGraph::usesColumn(int c) const +{ + return (c==parameterColumn); +} + +double JKQTPXYFunctionLineGraph::getTMin() const +{ + return tmin; +} + +double JKQTPXYFunctionLineGraph::getTMax() const +{ + return tmax; +} + +void JKQTPXYFunctionLineGraph::setTMin(double val) +{ + tmin=val; +} + +void JKQTPXYFunctionLineGraph::setTMax(double val) +{ + tmax=val; +} + +QPair JKQTPXYFunctionLineGraph::getTRange() const +{ + return QPair(tmin,tmax); +} + +void JKQTPXYFunctionLineGraph::setTRange(double tmin_, double tmax_) +{ + tmin=tmin_; + tmax=tmax_; +} + +void JKQTPXYFunctionLineGraph::setTRange(const QPair &range) +{ + tmin=range.first; + tmax=range.second; +} + diff --git a/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h new file mode 100644 index 0000000000..7d3edad10c --- /dev/null +++ b/lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h @@ -0,0 +1,275 @@ +/* + Copyright (c) 2020-2020 Jan W. Krieger () + + + + 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 + the Free Software Foundation, either version 2.1 of the License, or + (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 . +*/ + + + +#include +#include +#include +#include "jkqtplotter/graphs/jkqtpscatter.h" +#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" +#include "jkqtplotter/jkqtplotter_imexport.h" +#include "jkqtcommon/jkqtpgeometrytools.h" +#include + +#ifndef jkqtpevaluatedparametriccurve_H +#define jkqtpevaluatedparametriccurve_H + + + + +/*! \brief type of functions that may be plotted by JKQTPXYFunctionLineGraph + \ingroup jkqtplotter_functiongraphs + + This is the type of functions \f$ [x,y]=f(t, \vec{p}) \f$ that may be plottet by JKQTPXYFunctionLineGraph. + It is possible to supply parameters \f$ \vec{p} \f$ to the function that + 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 std::function jkqtpParametricCurveFunctionType; + +/*! \brief simplified type of functions (without parameters) that may be plotted by JKQTPXYFunctionLineGraph + \ingroup jkqtplotter_functiongraphs + + This is the type of functions \f$ [x,y]=f(t) \f$ that may be plottet by JKQTPXYFunctionLineGraph + and JKQTPYFunctionLineGraph. +*/ +typedef std::function jkqtpSimpleParametricCurveFunctionType; + + +/*! \brief This implements line plots where the data is taken from a user supplied function \f$ [x,y]=f(t) \f$ + The function is evaluated on a user-specified range \f$ t \in \left[t_\text{min}, t_\text{max}\right] \f$ + \ingroup jkqtplotter_functiongraphs + + 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 + necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$ + and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. The midpoint is added + to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f] + 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 shows a Lissajou's fugure drawn with this function + + \image html plot_evalcurve.png + + The source code for this example is: + \code + JKQTPXYFunctionLineGraph* func1=new JKQTPXYFunctionLineGraph(plot); + func1->setPlotFunctionFunctor([](double t) -> QPointF { + const double a=5; + const double b=4; + const double delta=JKQTPSTATISTICS_PI/4.0; + return QPointF(sin(a*t+delta), sin(b*t)); + }); + func1->setTRange(0, 2.0*JKQTPSTATISTICS_PI); + func1->setTitle("C++-inline function $[ sin(5{\\cdot}t+\\pi/4), sin(4{\\cdot}t) ]$"); + \endcode + + \see \ref JKQTPlotterEvalCurves , JKQTPAdaptiveFunctionGraphEvaluator, JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph + */ +class JKQTPLOTTER_LIB_EXPORT JKQTPXYFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin { + Q_OBJECT + public: + + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(JKQTBasePlotter* parent=nullptr); + + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCurveFunctionType & f, const QString& title, double tmin_=0, double tmax_=1, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(const jkqtpSimpleParametricCurveFunctionType & f, const QString& title, double tmin_, double tmax_, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(jkqtpSimpleParametricCurveFunctionType && f, const QString& title, double tmin_=0, double tmax_=1, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(jkqtpSimpleParametricCurveFunctionType && f, const QString& title, double tmin_, double tmax_, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFunctionType & f, const QString& title, double tmin_=0, double tmax_=1, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(const jkqtpParametricCurveFunctionType & f, const QString& title, double tmin_, double tmax_, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(jkqtpParametricCurveFunctionType && f, const QString& title, double tmin_=0, double tmax_=1, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXYFunctionLineGraph(jkqtpParametricCurveFunctionType && f, const QString& title, double tmin_, double tmax_, JKQTPlotter* parent); + + /** \brief class destructor */ + virtual ~JKQTPXYFunctionLineGraph() override; + + /** \brief plots the graph to the plotter object specified as parent */ + virtual void draw(JKQTPEnhancedPainter& painter) override; + /** \brief plots a key marker inside the specified rectangle \a rect */ + virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override; + /** \brief returns the color to be used for the key label */ + virtual QColor getKeyLabelColor() const override; + + /** \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. + */ + virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override; + /** \brief get the maximum and minimum y-value of the graph + */ + virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override; + + /** \brief sets a functor to be plotted + * + * \see plotFunction + */ + virtual void setPlotFunctionFunctor (jkqtpParametricCurveFunctionType && __value); + /** \brief sets a functor to be plotted + * + * \see plotFunction + */ + virtual void setPlotFunctionFunctor (const jkqtpParametricCurveFunctionType & __value); + /** \brief sets a functor to be plotted + * + * \see simplePlotFunction + */ + virtual void setPlotFunctionFunctor (jkqtpSimpleParametricCurveFunctionType && __value); + /** \brief sets a functor to be plotted + * + * \see simplePlotFunction + */ + virtual void setPlotFunctionFunctor (const jkqtpSimpleParametricCurveFunctionType & __value); + /*! \copydoc plotFunction */ \ + virtual jkqtpParametricCurveFunctionType getPlotFunctionFunctor () const; + /*! \copydoc simplePlotFunction */ \ + virtual jkqtpSimpleParametricCurveFunctionType getSimplePlotFunction () const; + + /*! \copydoc params */ + virtual void setParams(void* __value); + /*! \copydoc params */ + void* getParams() const; + /** \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!!!) */ + virtual void setParams(const QVector& params); + /** \brief sets the params from a copy of the given array of length \a N */ + void setCopiedParams(const double* params, int N); + /** \brief set an internal parameter vector as function parameters, initialized with {p1} */ + void setParamsV(double p1); + /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2} */ + void setParamsV(double p1, double p2); + /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3} */ + void setParamsV(double p1, double p2, double p3); + /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4} */ + void setParamsV(double p1, double p2, double p3, double p4); + /** \brief set an internal parameter vector as function parameters, initialized with {p1,p2,p3,p4,p5} */ + void setParamsV(double p1, double p2, double p3, double p4, double p5); + + /** \brief returns the currently set internal parameter vector */ + QVector getInternalParams() const; + + /*! \copydoc minSamples */ + void setMinSamples(const unsigned int & __value); + /*! \copydoc minSamples */ + unsigned int getMinSamples() const; + /*! \copydoc maxRefinementDegree */ + void setMaxRefinementDegree(const unsigned int & __value); + /*! \copydoc maxRefinementDegree */ + unsigned int getMaxRefinementDegree() const; + /*! \copydoc slopeTolerance */ + void setSlopeTolerance(double __value); + /*! \copydoc slopeTolerance */ + double getSlopeTolerance() const; + /*! \copydoc minPixelPerSample */ + void setMinPixelPerSample(double __value); + /*! \copydoc minPixelPerSample */ + double getMinPixelPerSample() const; + /*! \copydoc plotRefinement */ + void setPlotRefinement(bool __value); + /*! \copydoc plotRefinement */ + bool getPlotRefinement() const; + /*! \copydoc displaySamplePoints */ + void setDisplaySamplePoints(bool __value); + /*! \copydoc displaySamplePoints */ + bool getDisplaySamplePoints() const; + + /*! \copydoc parameterColumn */ + void setParameterColumn(int __value); + /*! \copydoc parameterColumn */ + int getParameterColumn() const; + /*! \copydoc parameterColumn */ + void setParameterColumn (size_t __value); + + + /** \copydoc JKQTPGraph::usesColumn() */ + virtual bool usesColumn(int c) const override; + + + /*! \copydoc tmin */ + double getTMin() const; + /*! \copydoc tmax */ + double getTMax() const; + /*! \copydoc tmin */ + void setTMin(double val); + /*! \copydoc tmax */ + void setTMax(double val); + /*! \brief returns the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */ + QPair getTRange() const; + /*! \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */ + void setTRange(double tmin_, double tmax_); + /*! \brief set the t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ */ + void setTRange(const QPair& range); + protected: + /** \brief lower bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 0 */ + double tmin; + /** \brief upper bound of t-value range for \f$ [x,y]=f(t), t \in \left[t_\text{min}, t_\text{max}\right] \f$ , i.e. \f$ t_\text{min} \f$ , default is 1 */ + double tmax; + + /** \brief plot data calculated by createPlotData() */ + QVector data; + + /** \brief fill the data array with data from the function plotFunction */ + virtual void createPlotData( bool collectParams=true); + /** \brief ensure that current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams */ + virtual void collectParameters(); + + /** \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 the function to be plotted */ + jkqtpParametricCurveFunctionType plotFunction; + /** \brief a simple function to be plotted, simplified form without parameters */ + jkqtpSimpleParametricCurveFunctionType simplePlotFunction; + /** \brief pointer to the parameters supplied to the plotting funtion */ + void* params; + /** \brief the minimum number of points to evaluate the function at */ + unsigned int minSamples; + /** \brief the maximum number of recursive refinement steps + * + * each step bisects the interval \f$ [a, b] \f$ into two halfes. So the maximum number + * of points plotted at all are thus: + * \f[ \mbox{minSamples} \cdot 2^{\mbox{maxRefinementDegree}} \f] + */ + unsigned int maxRefinementDegree; + /** \brief the tolerance for the difference of two subsequent slopes */ + double slopeTolerance; + /** \brief create one sample at least every \a minPixelPerSample pixels */ + double minPixelPerSample; + /** \brief switch on or off [default: on] the plot refinement algorithm */ + bool plotRefinement; + /** \brief if true [default: off] display the points where the function has been sampled */ + bool displaySamplePoints; + /** \brief internal storage for the current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) */ + QVector iparams; +}; + +#endif // jkqtpevaluatedparametriccurve_H diff --git a/screenshots/evalcurve.png b/screenshots/evalcurve.png new file mode 100644 index 0000000000..f44cd00696 Binary files /dev/null and b/screenshots/evalcurve.png differ diff --git a/screenshots/evalcurve_small.png b/screenshots/evalcurve_small.png new file mode 100644 index 0000000000..3638362acf Binary files /dev/null and b/screenshots/evalcurve_small.png differ