mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-26 02:21:43 +08:00
new: a new graph class JKQTPXYFunctionLineGraph draws parametric 2D curves (f(t) -> [x,y])
This commit is contained in:
parent
33a9cb5b2d
commit
c57c672f78
@ -86,6 +86,7 @@ addSimpleTest(datastore_regression)
|
|||||||
addSimpleTest(datastore_groupedstat)
|
addSimpleTest(datastore_groupedstat)
|
||||||
addSimpleTest(contourplot)
|
addSimpleTest(contourplot)
|
||||||
addSimpleTest(violinplot)
|
addSimpleTest(violinplot)
|
||||||
|
addSimpleTest(evalcurve)
|
||||||
#addSimpleTest(rgbimageplot_opencv)
|
#addSimpleTest(rgbimageplot_opencv)
|
||||||
#addSimpleTest(imageplot_opencv)
|
#addSimpleTest(imageplot_opencv)
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
|||||||
<tr><td> \image html parsedfunctionplot_small.png
|
<tr><td> \image html parsedfunctionplot_small.png
|
||||||
<td> \subpage JKQTPlotterParsedFunctionPlot
|
<td> \subpage JKQTPlotterParsedFunctionPlot
|
||||||
<td> `JKQTPXParsedFunctionLineGraph` <br> plotting functions with the internal math equation parser/evaluator
|
<td> `JKQTPXParsedFunctionLineGraph` <br> plotting functions with the internal math equation parser/evaluator
|
||||||
|
<tr><td> \image html evalcurve_small.png
|
||||||
|
<td> \subpage JKQTPlotterEvalCurves
|
||||||
|
<td> `JKQTPXYFunctionLineGraph`
|
||||||
<tr><td> \image html boxplot_small.png
|
<tr><td> \image html boxplot_small.png
|
||||||
<td> \subpage JKQTPlotterBoxplotsGraphs
|
<td> \subpage JKQTPlotterBoxplotsGraphs
|
||||||
<td> `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph`, ...
|
<td> `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph`, ...
|
||||||
|
@ -356,7 +356,10 @@ This group assembles graphs that show their data with symbols and optionally wit
|
|||||||
<th> Classes
|
<th> Classes
|
||||||
<tr>
|
<tr>
|
||||||
<td>\image html functionplot_small.png
|
<td>\image html functionplot_small.png
|
||||||
<td> JKQTPXParsedFunctionLineGraph, JKQTPYParsedFunctionLineGraph
|
<td> JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph
|
||||||
|
<tr>
|
||||||
|
<td>\image html evalcurve_small.png
|
||||||
|
<td> JKQTPXYFunctionLineGraph
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
\defgroup jkqtplotter_parsedFgraphs Parsed Function Graphs
|
\defgroup jkqtplotter_parsedFgraphs Parsed Function Graphs
|
||||||
@ -368,7 +371,7 @@ This group assembles graphs that show their data with symbols and optionally wit
|
|||||||
<th> Classes
|
<th> Classes
|
||||||
<tr>
|
<tr>
|
||||||
<td>\image html functionplot_small.png
|
<td>\image html functionplot_small.png
|
||||||
<td> JKQTPXFunctionLineGraph, JKQTPYFunctionLineGraph
|
<td> JKQTPXParsedFunctionLineGraph, JKQTPYParsedFunctionLineGraph
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
\defgroup jkqtplotter_barssticks Barcharts, Impulse-Charts, ...
|
\defgroup jkqtplotter_barssticks Barcharts, Impulse-Charts, ...
|
||||||
|
@ -25,6 +25,7 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
|
|||||||
<li>improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)</li>
|
<li>improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)</li>
|
||||||
<li>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)</li>
|
<li>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)</li>
|
||||||
<li>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</li>
|
<li>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</li>
|
||||||
|
<li>new: a new graph class JKQTPXYFunctionLineGraph draws parametric 2D curves ( \f$ [x,y] = f(t) \f$ ), see \ref JKQTPlotterEvalCurves for an example</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
\subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download
|
\subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download
|
||||||
|
BIN
doc/images/plot_evalcurve.png
Normal file
BIN
doc/images/plot_evalcurve.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -58,5 +58,6 @@ add_subdirectory(symbols_and_styles)
|
|||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
add_subdirectory(user_interaction)
|
add_subdirectory(user_interaction)
|
||||||
add_subdirectory(violinplot)
|
add_subdirectory(violinplot)
|
||||||
|
add_subdirectory(evalcurve)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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` <br> C++-style QVector as plot data <br> parametric curve plotting |
|
| [![](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` <br> C++-style QVector as plot data <br> 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` <br> diretly plotting C/C++-functions |
|
| [![](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` <br> 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` <br> plotting functions with the internal math equation parser/evaluator |
|
| [![](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` <br> 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/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` |
|
| [![](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` |
|
||||||
|
|
||||||
|
29
examples/evalcurve/CMakeLists.txt
Normal file
29
examples/evalcurve/CMakeLists.txt
Normal file
@ -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})
|
42
examples/evalcurve/README.md
Normal file
42
examples/evalcurve/README.md
Normal file
@ -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) .
|
||||||
|
|
||||||
|
|
||||||
|
|
52
examples/evalcurve/evalcurve.cpp
Normal file
52
examples/evalcurve/evalcurve.cpp
Normal file
@ -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 <QApplication>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QMap>
|
||||||
|
#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();
|
||||||
|
}
|
28
examples/evalcurve/evalcurve.pro
Normal file
28
examples/evalcurve/evalcurve.pro
Normal file
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
examples/evalcurve/evalcurve_and_lib.pro
Normal file
8
examples/evalcurve/evalcurve_and_lib.pro
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
|
SUBDIRS += jkqtplotterlib evalcurve
|
||||||
|
|
||||||
|
jkqtplotterlib.file = ../../qmake/staticlib/jkqtplotterlib/jkqtplotterlib.pro
|
||||||
|
|
||||||
|
evalcurve.file=$$PWD/evalcurve.pro
|
||||||
|
evalcurve.depends = jkqtplotterlib
|
@ -69,13 +69,10 @@ QVector<QPointF> JKQTPSplitEllipseIntoPoints(std::function<QPointF (QPointF)> fT
|
|||||||
std::function<QPointF(double)> fell=[&](double t)->QPointF {
|
std::function<QPointF(double)> fell=[&](double t)->QPointF {
|
||||||
return QPointF(x+a*cos(t)*cosa-b*sin(t)*sina, y+a*cos(t)*sina+b*sin(t)*cosa);
|
return QPointF(x+a*cos(t)*cosa-b*sin(t)*sina, y+a*cos(t)*sina+b*sin(t)*cosa);
|
||||||
};
|
};
|
||||||
std::function<double(double)> fx = [&](double t) ->double {
|
std::function<QPointF(double)> fxy = [&](double t) ->QPointF {
|
||||||
return fTransform(fell(t)).x();
|
return fTransform(fell(t));
|
||||||
};
|
};
|
||||||
std::function<double(double)> fy = [&](double t) ->double {
|
JKQTPAdaptiveFunctionGraphEvaluator eval(fxy);
|
||||||
return fTransform(fell(t)).y();
|
|
||||||
};
|
|
||||||
JKQTPAdaptiveFunctionGraphEvaluator eval(fx, fy);
|
|
||||||
|
|
||||||
const QVector<QPointF> points=eval.evaluate(angle_start*JKQTPSTATISTICS_PI/180.0, angle_end*JKQTPSTATISTICS_PI/180.0);
|
const QVector<QPointF> points=eval.evaluate(angle_start*JKQTPSTATISTICS_PI/180.0, angle_end*JKQTPSTATISTICS_PI/180.0);
|
||||||
if (points.size()>0) {
|
if (points.size()>0) {
|
||||||
@ -238,6 +235,17 @@ QVector<QPointF> JKQTPSimplyfyLineSegemnts(const QVector<QPointF> &points, doubl
|
|||||||
JKQTPAdaptiveFunctionGraphEvaluator::JKQTPAdaptiveFunctionGraphEvaluator(const std::function<double (double)> &fx_, const std::function<double (double)> &fy_, unsigned int minSamples_, unsigned int maxRefinementDegree_, double slopeTolerance_, double minPixelPerSample_):
|
JKQTPAdaptiveFunctionGraphEvaluator::JKQTPAdaptiveFunctionGraphEvaluator(const std::function<double (double)> &fx_, const std::function<double (double)> &fy_, unsigned int minSamples_, unsigned int maxRefinementDegree_, double slopeTolerance_, double minPixelPerSample_):
|
||||||
fx(fx_),
|
fx(fx_),
|
||||||
fy(fy_),
|
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<QPointF (double)> &fxy_, unsigned int minSamples_, unsigned int maxRefinementDegree_, double slopeTolerance_, double minPixelPerSample_):
|
||||||
|
fxy(fxy_),
|
||||||
minSamples(minSamples_),
|
minSamples(minSamples_),
|
||||||
maxRefinementDegree(maxRefinementDegree_),
|
maxRefinementDegree(maxRefinementDegree_),
|
||||||
slopeTolerance(slopeTolerance_),
|
slopeTolerance(slopeTolerance_),
|
||||||
@ -252,19 +260,19 @@ QVector<QPointF> JKQTPAdaptiveFunctionGraphEvaluator::evaluate(double tmin, doub
|
|||||||
|
|
||||||
double delta_t0=(tmax-tmin)/static_cast<double>(minSamples);
|
double delta_t0=(tmax-tmin)/static_cast<double>(minSamples);
|
||||||
|
|
||||||
intData.push_front(std::pair<double, QPointF>(tmin, QPointF(fx(tmin), fy(tmin))));
|
intData.push_front(std::pair<double, QPointF>(tmin, fxy(tmin)));
|
||||||
InternalList::iterator a=intData.begin();
|
InternalList::iterator a=intData.begin();
|
||||||
//qDebug()<<"**************************************************";
|
//qDebug()<<"**************************************************";
|
||||||
for (double t=tmin+delta_t0; t<tmax; t=t+delta_t0) {
|
for (double t=tmin+delta_t0; t<tmax; t=t+delta_t0) {
|
||||||
const double treal=t;
|
const double treal=t;
|
||||||
intData.insert_after(a, std::pair<double, QPointF>(treal, QPointF(fx(treal), fy(treal))));
|
intData.insert_after(a, std::pair<double, QPointF>(treal, fxy(treal)));
|
||||||
InternalList::iterator b=a; b++;
|
InternalList::iterator b=a; b++;
|
||||||
//qDebug()<<"t="<<t<<", dist(a,b)="<<std::distance(a,b);
|
//qDebug()<<"t="<<t<<", dist(a,b)="<<std::distance(a,b);
|
||||||
refine(intData, a, b, 0);
|
refine(intData, a, b, 0);
|
||||||
//qDebug()<<" after refine: dist(a,b)="<<std::distance(a,b);
|
//qDebug()<<" after refine: dist(a,b)="<<std::distance(a,b);
|
||||||
a=b;
|
a=b;
|
||||||
}
|
}
|
||||||
intData.insert_after(a, std::pair<double, QPointF>(tmax, QPointF(fx(tmax), fy(tmax))));
|
intData.insert_after(a, std::pair<double, QPointF>(tmax, fxy(tmax)));
|
||||||
auto b=a; b++;
|
auto b=a; b++;
|
||||||
refine(intData, a, b, 0);
|
refine(intData, a, b, 0);
|
||||||
// copy data to output data structure
|
// copy data to output data structure
|
||||||
@ -284,7 +292,7 @@ void JKQTPAdaptiveFunctionGraphEvaluator::refine(JKQTPAdaptiveFunctionGraphEvalu
|
|||||||
const double tmid=ta+(tb-ta)/2.0;
|
const double tmid=ta+(tb-ta)/2.0;
|
||||||
const QPointF pa=a->second;
|
const QPointF pa=a->second;
|
||||||
const QPointF pb=b->second;
|
const QPointF pb=b->second;
|
||||||
const QPointF pmid(fx(tmid), fy(tmid));
|
const QPointF pmid(fxy(tmid));
|
||||||
const double delta=QLineF(pa, pb).length();
|
const double delta=QLineF(pa, pb).length();
|
||||||
|
|
||||||
const double slope_a_mid=(pmid.y()-pa.y())/(pmid.x()-pa.x());
|
const double slope_a_mid=(pmid.y()-pa.y())/(pmid.x()-pa.x());
|
||||||
@ -299,13 +307,10 @@ void JKQTPAdaptiveFunctionGraphEvaluator::refine(JKQTPAdaptiveFunctionGraphEvalu
|
|||||||
|
|
||||||
QVector<QPointF> JKQTPSplitLineIntoPoints(const QLineF &line, std::function<QPointF (QPointF)> fTransform)
|
QVector<QPointF> JKQTPSplitLineIntoPoints(const QLineF &line, std::function<QPointF (QPointF)> fTransform)
|
||||||
{
|
{
|
||||||
std::function<double(double)> fx = [&line, &fTransform](double t) ->double {
|
std::function<QPointF(double)> fxy = [&line, &fTransform] (double t) ->QPointF {
|
||||||
return fTransform(line.p1()+t*(line.p2()-line.p1())).x();
|
return fTransform(line.p1()+t*(line.p2()-line.p1()));
|
||||||
};
|
};
|
||||||
std::function<double(double)> fy = [&line, &fTransform](double t) ->double {
|
JKQTPAdaptiveFunctionGraphEvaluator eval(fxy);
|
||||||
return fTransform(line.p1()+t*(line.p2()-line.p1())).y();
|
|
||||||
};
|
|
||||||
JKQTPAdaptiveFunctionGraphEvaluator eval(fx, fy);
|
|
||||||
|
|
||||||
return eval.evaluate(0.0,1.0);
|
return eval.evaluate(0.0,1.0);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
JKQTPAdaptiveFunctionGraphEvaluator(const std::function<double(double)>& fx_, const std::function<double(double)>& fy_, unsigned int minSamples_=10, unsigned int maxRefinementDegree_=5, double slopeTolerance_=0.005, double minPixelPerSample_=32);
|
JKQTPAdaptiveFunctionGraphEvaluator(const std::function<double(double)>& fx_, const std::function<double(double)>& fy_, unsigned int minSamples_=10, unsigned int maxRefinementDegree_=5, double slopeTolerance_=0.005, double minPixelPerSample_=32);
|
||||||
|
|
||||||
|
/** \brief class constructor
|
||||||
|
*
|
||||||
|
* \param fxy function \f$ [x,y]=f_{xy}(t) \f$
|
||||||
|
* \param minSamples the minimum number of points to evaluate the function at
|
||||||
|
* \param maxRefinementDegree 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]
|
||||||
|
* \param slopeTolerance the tolerance for the difference of two subsequent slopes
|
||||||
|
* \param minPixelPerSample create one sample at least every \a minPixelPerSample pixels
|
||||||
|
*/
|
||||||
|
JKQTPAdaptiveFunctionGraphEvaluator(const std::function<QPointF(double)>& fxy_, unsigned int minSamples_=10, unsigned int maxRefinementDegree_=5, double slopeTolerance_=0.005, double minPixelPerSample_=32);
|
||||||
|
|
||||||
/** \brief evaluate the function specified in the constructor over the given parameter range \a tmin ... \a tmax
|
/** \brief evaluate the function specified in the constructor over the given parameter range \a tmin ... \a tmax
|
||||||
*
|
*
|
||||||
* \param tmin lower parameter range limit \f$ t_\text{min} \f$
|
* \param tmin lower parameter range limit \f$ t_\text{min} \f$
|
||||||
@ -77,6 +90,8 @@ protected:
|
|||||||
std::function<double(double)> fx;
|
std::function<double(double)> fx;
|
||||||
/** \brief function \f$ f_y(t) \f$ */
|
/** \brief function \f$ f_y(t) \f$ */
|
||||||
std::function<double(double)> fy;
|
std::function<double(double)> fy;
|
||||||
|
/** \brief function \f$ [x,y]=f_{xy}(t) \f$ */
|
||||||
|
std::function<QPointF(double)> fxy;
|
||||||
/** \brief the minimum number of points to evaluate the function at */
|
/** \brief the minimum number of points to evaluate the function at */
|
||||||
unsigned int minSamples;
|
unsigned int minSamples;
|
||||||
/** \brief the maximum number of recursive refinement steps
|
/** \brief the maximum number of recursive refinement steps
|
||||||
|
@ -49,6 +49,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
|||||||
$$PWD/jkqtplotter/graphs/jkqtprange.h \
|
$$PWD/jkqtplotter/graphs/jkqtprange.h \
|
||||||
$$PWD/jkqtplotter/graphs/jkqtpspecialline.h \
|
$$PWD/jkqtplotter/graphs/jkqtpspecialline.h \
|
||||||
$$PWD/jkqtplotter/graphs/jkqtpbarchart.h \
|
$$PWD/jkqtplotter/graphs/jkqtpbarchart.h \
|
||||||
|
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h \
|
||||||
$$PWD/jkqtplotter/overlays/jkqtpbasicoverlays.h \
|
$$PWD/jkqtplotter/overlays/jkqtpbasicoverlays.h \
|
||||||
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.h \
|
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.h \
|
||||||
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.h \
|
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.h \
|
||||||
@ -98,6 +99,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
|||||||
$$PWD/jkqtplotter/graphs/jkqtprange.cpp \
|
$$PWD/jkqtplotter/graphs/jkqtprange.cpp \
|
||||||
$$PWD/jkqtplotter/graphs/jkqtpspecialline.cpp \
|
$$PWD/jkqtplotter/graphs/jkqtpspecialline.cpp \
|
||||||
$$PWD/jkqtplotter/graphs/jkqtpbarchart.cpp \
|
$$PWD/jkqtplotter/graphs/jkqtpbarchart.cpp \
|
||||||
|
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp \
|
||||||
$$PWD/jkqtplotter/overlays/jkqtpbasicoverlays.cpp \
|
$$PWD/jkqtplotter/overlays/jkqtpbasicoverlays.cpp \
|
||||||
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.cpp \
|
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.cpp \
|
||||||
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.cpp \
|
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.cpp \
|
||||||
|
@ -51,7 +51,7 @@ set(SOURCES_GRAPHS
|
|||||||
graphs/jkqtpgeobase.cpp
|
graphs/jkqtpgeobase.cpp
|
||||||
graphs/jkqtpgeolines.cpp
|
graphs/jkqtpgeolines.cpp
|
||||||
graphs/jkqtpgeoshapes.cpp
|
graphs/jkqtpgeoshapes.cpp
|
||||||
graphs/jkqtpimage.cpp
|
graphs/jkqtpimage.cpp
|
||||||
graphs/jkqtpimpulses.cpp
|
graphs/jkqtpimpulses.cpp
|
||||||
graphs/jkqtpparsedfunction.cpp
|
graphs/jkqtpparsedfunction.cpp
|
||||||
graphs/jkqtppeakstream.cpp
|
graphs/jkqtppeakstream.cpp
|
||||||
@ -62,6 +62,7 @@ set(SOURCES_GRAPHS
|
|||||||
graphs/jkqtpviolinplot.cpp
|
graphs/jkqtpviolinplot.cpp
|
||||||
graphs/jkqtpviolinplotstylingmixins.cpp
|
graphs/jkqtpviolinplotstylingmixins.cpp
|
||||||
graphs/jkqtpstatisticsadaptors.cpp
|
graphs/jkqtpstatisticsadaptors.cpp
|
||||||
|
graphs/jkqtpevaluatedparametriccurve.cpp
|
||||||
)
|
)
|
||||||
set(SOURCES_OVERLAYS
|
set(SOURCES_OVERLAYS
|
||||||
overlays/jkqtpbasicoverlays.cpp
|
overlays/jkqtpbasicoverlays.cpp
|
||||||
@ -118,6 +119,7 @@ set(HEADERS_GRAPHS
|
|||||||
graphs/jkqtprange.h
|
graphs/jkqtprange.h
|
||||||
graphs/jkqtpspecialline.h
|
graphs/jkqtpspecialline.h
|
||||||
graphs/jkqtpbarchart.h
|
graphs/jkqtpbarchart.h
|
||||||
|
graphs/jkqtpevaluatedparametriccurve.h
|
||||||
)
|
)
|
||||||
set(HEADERS_OVERLAY
|
set(HEADERS_OVERLAY
|
||||||
overlays/jkqtpbasicoverlays.h
|
overlays/jkqtpbasicoverlays.h
|
||||||
|
@ -92,13 +92,8 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent):
|
||||||
JKQTPXFunctionLineGraph(parent)
|
JKQTPXFunctionLineGraph(f, title_, parent->getPlotter())
|
||||||
{
|
{
|
||||||
title=title_;
|
|
||||||
plotFunction=jkqtpPlotFunctionType();
|
|
||||||
simplePlotFunction=f;
|
|
||||||
functionType=SpecialFunction::UserFunction;
|
|
||||||
clearData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent):
|
||||||
@ -112,15 +107,26 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f
|
|||||||
}
|
}
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent):
|
||||||
|
JKQTPXFunctionLineGraph(std::move(f), title_, parent->getPlotter())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||||
JKQTPXFunctionLineGraph(parent)
|
JKQTPXFunctionLineGraph(parent)
|
||||||
{
|
{
|
||||||
title=title_;
|
title=title_;
|
||||||
plotFunction=jkqtpPlotFunctionType();
|
functionType=type;
|
||||||
simplePlotFunction=std::move(f);
|
setParams(params);
|
||||||
functionType=SpecialFunction::UserFunction;
|
|
||||||
clearData();
|
clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPXFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title, JKQTPlotter *parent):
|
||||||
|
JKQTPXFunctionLineGraph(type, params, title, parent->getPlotter())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() {
|
||||||
clearData();
|
clearData();
|
||||||
@ -592,6 +598,18 @@ JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTBasePlotter *parent):
|
||||||
|
JKQTPXFunctionLineGraph(type, params, title_, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPYFunctionLineGraph::SpecialFunction type, const QVector<double> ¶ms, const QString &title_, JKQTPlotter *parent):
|
||||||
|
JKQTPXFunctionLineGraph(type, params, title_, parent->getPlotter())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||||
#ifdef JKQTBP_AUTOTIMER
|
#ifdef JKQTBP_AUTOTIMER
|
||||||
JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::draw");
|
JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::draw");
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief type of functions that may be plottet
|
/*! \brief type of functions that may be plotted by JKQTPXFunctionLineGraph and JKQTPYFunctionLineGraph
|
||||||
\ingroup jkqtplotter_functiongraphs
|
\ingroup jkqtplotter_functiongraphs
|
||||||
|
|
||||||
This is the type of functions \f$ y=f(x, \vec{p}) \f$ that may be plottet by JKQTPXFunctionLineGraph
|
This is the type of functions \f$ y=f(x, \vec{p}) \f$ that may be plottet by JKQTPXFunctionLineGraph
|
||||||
@ -43,7 +43,7 @@
|
|||||||
*/
|
*/
|
||||||
typedef std::function<double(double, void*)> jkqtpPlotFunctionType;
|
typedef std::function<double(double, void*)> 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
|
\ingroup jkqtplotter_functiongraphs
|
||||||
|
|
||||||
This is the type of functions \f$ y=f(x) \f$ that may be plottet by JKQTPXFunctionLineGraph
|
This is the type of functions \f$ y=f(x) \f$ that may be plottet by JKQTPXFunctionLineGraph
|
||||||
@ -63,10 +63,11 @@ typedef std::function<double(double)> jkqtpSimplePlotFunctionType;
|
|||||||
In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
|
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.
|
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
|
\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 {
|
class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -94,6 +95,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public
|
|||||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||||
/** \brief class constructor */
|
/** \brief class constructor */
|
||||||
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
||||||
|
/** \brief class constructor */
|
||||||
|
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTBasePlotter* parent);
|
||||||
|
/** \brief class constructor */
|
||||||
|
JKQTPXFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTPlotter* parent);
|
||||||
|
|
||||||
/** \brief class destructor */
|
/** \brief class destructor */
|
||||||
virtual ~JKQTPXFunctionLineGraph() override;
|
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 */
|
/** \brief fill the data array with data from the function plotFunction */
|
||||||
virtual void createPlotData( bool collectParams=true);
|
virtual void createPlotData( bool collectParams=true);
|
||||||
|
/** \brief ensure that current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) are stored in iparams and ierrorparams */
|
||||||
virtual void collectParameters();
|
virtual void collectParameters();
|
||||||
/** \brief refine datapoints on the function graph between two evaluations \a a and \a b */
|
/** \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);
|
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;
|
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const;
|
||||||
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
|
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
|
||||||
|
/** \brief internal storage for the current function parameters for plotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||||
QVector<double> iparams, ierrorparams;
|
QVector<double> iparams;
|
||||||
|
/** \brief internal storage for the current error function parameters for errorPlotFunction (which may stem from different sources, as direct data, a datastore column ...) */
|
||||||
|
QVector<double> ierrorparams;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
|
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
|
||||||
\ingroup jkqtplotter_functiongraphs
|
\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 {
|
class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineGraph {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -381,6 +392,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineG
|
|||||||
JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr);
|
||||||
/** \brief class constructor */
|
/** \brief class constructor */
|
||||||
JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent);
|
||||||
|
/** \brief class constructor */
|
||||||
|
JKQTPYFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTBasePlotter* parent);
|
||||||
|
/** \brief class constructor */
|
||||||
|
JKQTPYFunctionLineGraph(SpecialFunction type, const QVector<double>& params, const QString& title, JKQTPlotter* parent);
|
||||||
|
|
||||||
/** \brief plots the graph to the plotter object specified as parent */
|
/** \brief plots the graph to the plotter object specified as parent */
|
||||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||||
|
514
lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp
Normal file
514
lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp
Normal file
@ -0,0 +1,514 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2020-2020 Jan W. Krieger (<jan@jkrieger.de>)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h"
|
||||||
|
#include "jkqtplotter/jkqtpbaseplotter.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <iostream>
|
||||||
|
#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) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(JKQTBasePlotter* parent):
|
||||||
|
JKQTPGraph(parent)
|
||||||
|
{
|
||||||
|
tmin=0.0;
|
||||||
|
tmax=1.0;
|
||||||
|
params=nullptr;
|
||||||
|
minSamples=100;
|
||||||
|
maxRefinementDegree=7;
|
||||||
|
slopeTolerance=0.005;
|
||||||
|
minPixelPerSample=32;
|
||||||
|
plotRefinement=true;
|
||||||
|
displaySamplePoints=false;
|
||||||
|
|
||||||
|
initLineStyle(parent, parentPlotStyle);
|
||||||
|
|
||||||
|
parameterColumn=-1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPXYFunctionLineGraph::JKQTPXYFunctionLineGraph(JKQTPlotter* parent):
|
||||||
|
JKQTPXYFunctionLineGraph(parent->getPlotter())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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<jkqtpSimpleParametricCurveFunctionType>(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<jkqtpParametricCurveFunctionType>(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()<minx) minx=d.x();
|
||||||
|
double xvsgz;
|
||||||
|
xvsgz=d.x(); SmallestGreaterZeroCompare_xvsgz();
|
||||||
|
start=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !start;
|
||||||
|
} else {
|
||||||
|
smallestGreaterZero=minx=maxx=0; return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKQTPXYFunctionLineGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero)
|
||||||
|
{
|
||||||
|
if (data.size()==0) createPlotData();
|
||||||
|
if (data.size()>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()<miny) miny=d.y();
|
||||||
|
double xvsgz;
|
||||||
|
xvsgz=d.x(); SmallestGreaterZeroCompare_xvsgz();
|
||||||
|
start=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !start;
|
||||||
|
} else {
|
||||||
|
smallestGreaterZero=miny=maxy=0; return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::createPlotData(bool collectParams) {
|
||||||
|
#ifdef JKQTBP_AUTOTIMER
|
||||||
|
JKQTPAutoOutputTimer jkaat(QString("JKQTPXYFunctionLineGraph[%1]::createPlotData()").arg(title));
|
||||||
|
#endif
|
||||||
|
data.clear();
|
||||||
|
if (collectParams) collectParameters();
|
||||||
|
|
||||||
|
if (parent==nullptr) return;
|
||||||
|
if (!plotFunction && !simplePlotFunction) return;
|
||||||
|
|
||||||
|
jkqtpSimpleParametricCurveFunctionType func;
|
||||||
|
if (plotFunction) func=std::bind(plotFunction, std::placeholders::_1, params);
|
||||||
|
else if (simplePlotFunction) func=simplePlotFunction;
|
||||||
|
|
||||||
|
jkqtpSimpleParametricCurveFunctionType fTransformedFunc= std::bind([&](const JKQTPXYFunctionLineGraph* plot, double t) -> 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<int>(datastore->getRows(parameterColumn));
|
||||||
|
|
||||||
|
for (int i=imin; i<imax; i++) {
|
||||||
|
double xv=datastore->get(parameterColumn,i);
|
||||||
|
iparams<<xv;
|
||||||
|
}
|
||||||
|
//qDebug()<<"iparams_beforeclean:";
|
||||||
|
//for (int i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
|
||||||
|
int i=iparams.size()-1;
|
||||||
|
while (i>=0 && !JKQTPIsOKFloat(iparams[i])) {
|
||||||
|
iparams.remove(i,1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug()<<"iparams:";
|
||||||
|
//for (i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
|
||||||
|
|
||||||
|
params=&iparams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||||
|
#ifdef JKQTBP_AUTOTIMER
|
||||||
|
JKQTPAutoOutputTimer jkaaot("JKQTPXYFunctionLineGraph::draw");
|
||||||
|
#endif
|
||||||
|
if (parent==nullptr) return;
|
||||||
|
JKQTPDatastore* datastore=parent->getDatastore();
|
||||||
|
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<double> ¶ms)
|
||||||
|
{
|
||||||
|
iparams=params;
|
||||||
|
setParams(&iparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setCopiedParams(const double *params, int N)
|
||||||
|
{
|
||||||
|
QVector<double> v;
|
||||||
|
for (int i=0; i<N; i++) { v<<params[i]; }
|
||||||
|
setParams(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParamsV(double p1) {
|
||||||
|
QVector<double> p;
|
||||||
|
p<<p1;
|
||||||
|
setParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParamsV(double p1, double p2) {
|
||||||
|
QVector<double> p;
|
||||||
|
p<<p1<<p2;
|
||||||
|
setParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParamsV(double p1, double p2, double p3) {
|
||||||
|
QVector<double> p;
|
||||||
|
p<<p1<<p2<<p3;
|
||||||
|
setParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParamsV(double p1, double p2, double p3, double p4) {
|
||||||
|
QVector<double> p;
|
||||||
|
p<<p1<<p2<<p3<<p4;
|
||||||
|
setParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParamsV(double p1, double p2, double p3, double p4, double p5) {
|
||||||
|
QVector<double> p;
|
||||||
|
p<<p1<<p2<<p3<<p4<<p5;
|
||||||
|
setParams(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParameterColumn(int __value)
|
||||||
|
{
|
||||||
|
this->parameterColumn = __value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JKQTPXYFunctionLineGraph::getParameterColumn() const
|
||||||
|
{
|
||||||
|
return this->parameterColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setParameterColumn(size_t __value) {
|
||||||
|
this->parameterColumn = static_cast<int>(__value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVector<double> 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<double, double> JKQTPXYFunctionLineGraph::getTRange() const
|
||||||
|
{
|
||||||
|
return QPair<double, double>(tmin,tmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setTRange(double tmin_, double tmax_)
|
||||||
|
{
|
||||||
|
tmin=tmin_;
|
||||||
|
tmax=tmax_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPXYFunctionLineGraph::setTRange(const QPair<double, double> &range)
|
||||||
|
{
|
||||||
|
tmin=range.first;
|
||||||
|
tmax=range.second;
|
||||||
|
}
|
||||||
|
|
275
lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h
Normal file
275
lib/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2020-2020 Jan W. Krieger (<jan@jkrieger.de>)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPair>
|
||||||
|
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
||||||
|
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||||
|
#include "jkqtplotter/jkqtplotter_imexport.h"
|
||||||
|
#include "jkqtcommon/jkqtpgeometrytools.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#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<QPointF(double, void*)> 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<QPointF(double)> 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<double>& 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<double> 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<double,double> 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<double,double>& 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<QPointF> 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<double> iparams;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // jkqtpevaluatedparametriccurve_H
|
BIN
screenshots/evalcurve.png
Normal file
BIN
screenshots/evalcurve.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
BIN
screenshots/evalcurve_small.png
Normal file
BIN
screenshots/evalcurve_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Loading…
Reference in New Issue
Block a user