mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-11-15 10:05:47 +08:00
NEW: JKQTPGeoBezierCurve for drawing bezier curves of degree 1-4 (+example)
This commit is contained in:
parent
4e7431ff77
commit
2365caf83b
@ -61,7 +61,7 @@ This software is licensed under the term of the [GNU Lesser General Public Licen
|
|||||||
- [contour plots](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__imagelots__contour.html)
|
- [contour plots](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__imagelots__contour.html)
|
||||||
- [vector field graphs/quiver plots](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__vectorfieldgraphs.html)
|
- [vector field graphs/quiver plots](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__vectorfieldgraphs.html)
|
||||||
- [financial graphs (candlestick/OHLC)](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__financialgraphs.html)
|
- [financial graphs (candlestick/OHLC)](https://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__financialgraphs.html)
|
||||||
- [geometric forms](http://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__geoplots.html) / [annotations](http://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__annotations.html)
|
- [geometric forms (lines, rectangles, polygons, circles, bezier-curves, ...)](http://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__geoplots.html) / [annotations (labels, text, ranges, ...)](http://jkriege2.github.io/JKQtPlotter/group__jkqtplotter__annotations.html)
|
||||||
- can be easily extended by deriving a new graph from [JKQTPPlotElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_plot_element.html), [JKQTPPlotAnnotationElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_plot_annotation_element.html), [JKQTPGeometricPlotElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_geometric_plot_element.html), [JKQTPGraph](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_graph.html)
|
- can be easily extended by deriving a new graph from [JKQTPPlotElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_plot_element.html), [JKQTPPlotAnnotationElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_plot_annotation_element.html), [JKQTPGeometricPlotElement](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_geometric_plot_element.html), [JKQTPGraph](http://jkriege2.github.io/JKQtPlotter/class_j_k_q_t_p_graph.html)
|
||||||
- optional: [OpenCV interface](http://jkriege2.github.io/JKQtPlotter/group__jkqtpinterfaceopencv.html), [CImg interfaces](http://jkriege2.github.io/JKQtPlotter/group__jkqtpinterfacecimg.html)
|
- optional: [OpenCV interface](http://jkriege2.github.io/JKQtPlotter/group__jkqtpinterfaceopencv.html), [CImg interfaces](http://jkriege2.github.io/JKQtPlotter/group__jkqtpinterfacecimg.html)
|
||||||
- CMake-based build system
|
- CMake-based build system
|
||||||
|
@ -248,6 +248,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
|||||||
vectorfield
|
vectorfield
|
||||||
paramvectorfield
|
paramvectorfield
|
||||||
financialgraphs
|
financialgraphs
|
||||||
|
geo_bezier
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -279,6 +280,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
|||||||
vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip,JKQTPVectorFieldGraphAutoscaleLength,JKQTPVectorFieldGraphLengthFromData,JKQTPVectorFieldGraphIgnoreLength,JKQTPVectorFieldGraphIgnoreLengthAutoscaleLineWidthFromLength,JKQTPVectorFieldGraphAutoscaleLengthAutoscaleLineWidthFromLength/--iteratefunctorsteps
|
vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip,JKQTPVectorFieldGraphAutoscaleLength,JKQTPVectorFieldGraphLengthFromData,JKQTPVectorFieldGraphIgnoreLength,JKQTPVectorFieldGraphIgnoreLengthAutoscaleLineWidthFromLength,JKQTPVectorFieldGraphAutoscaleLengthAutoscaleLineWidthFromLength/--iteratefunctorsteps
|
||||||
paramvectorfield/JKQTPParametrizedVectorFieldGraph,JKQTPParametrizedVectorFieldGraphColorFromMagnitude,JKQTPParametrizedVectorFieldGraphColorFromAngle,JKQTPParametrizedVectorFieldGraphDefaultColor/--iteratefunctorsteps
|
paramvectorfield/JKQTPParametrizedVectorFieldGraph,JKQTPParametrizedVectorFieldGraphColorFromMagnitude,JKQTPParametrizedVectorFieldGraphColorFromAngle,JKQTPParametrizedVectorFieldGraphDefaultColor/--iteratefunctorsteps
|
||||||
financialgraphs/JKQTPFinancialGraph,JKQTPFinancialGraphCandleStick,JKQTPFinancialGraphSetCandlestickTwoColor,JKQTPFinancialGraphSetCandlestickTwoColor2,JKQTPFinancialGraphSetCandlestickOneColor,JKQTPFinancialGraphOHLC,JKQTPFinancialGraphSetOHLCTwoColor,JKQTPFinancialGraphSidyBySide/--iteratefunctorsteps
|
financialgraphs/JKQTPFinancialGraph,JKQTPFinancialGraphCandleStick,JKQTPFinancialGraphSetCandlestickTwoColor,JKQTPFinancialGraphSetCandlestickTwoColor2,JKQTPFinancialGraphSetCandlestickOneColor,JKQTPFinancialGraphOHLC,JKQTPFinancialGraphSetOHLCTwoColor,JKQTPFinancialGraphSidyBySide/--iteratefunctorsteps
|
||||||
|
geo_bezier/JKQTPGeoBezierCurveGraphic,JKQTPGeoBezierCurveMath,JKQTPGeoBezierCurveLogMath,JKQTPGeoBezierCurveLogGraphic/--iteratefunctorsteps
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -289,7 +291,6 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach(ex ${JKQTPlotter_GenerateDocScreenshots_From})
|
foreach(ex ${JKQTPlotter_GenerateDocScreenshots_From})
|
||||||
set(example ${ex})
|
set(example ${ex})
|
||||||
set(basename ${ex})
|
set(basename ${ex})
|
||||||
|
@ -119,6 +119,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
|||||||
<tr><td> \image html geo_arrows_small.png
|
<tr><td> \image html geo_arrows_small.png
|
||||||
<td> \subpage JKQTPlotterGeometricArrows
|
<td> \subpage JKQTPlotterGeometricArrows
|
||||||
<td> `JKQTPGeoArrow`, ...
|
<td> `JKQTPGeoArrow`, ...
|
||||||
|
<tr><td> \image html geo_bezier_small.png
|
||||||
|
<td> \subpage JKQTPlotterGeometricBezier
|
||||||
|
<td> `JKQTPGeoBezierCurve`, ...
|
||||||
<tr><td> \image html geo_coordinateaxis0_small.png
|
<tr><td> \image html geo_coordinateaxis0_small.png
|
||||||
<td> \subpage JKQTPlotterGeometricCoordinateAxis0
|
<td> \subpage JKQTPlotterGeometricCoordinateAxis0
|
||||||
<td> `JKQTPCoordinateAxisStyle::drawMode0`, `JKQTPGeoPolygon`, `JKQTPGeoEllipse`
|
<td> `JKQTPCoordinateAxisStyle::drawMode0`, `JKQTPGeoPolygon`, `JKQTPGeoEllipse`
|
||||||
|
@ -302,6 +302,9 @@ This group assembles graphs that add (textual) labels to the datapoints in a plo
|
|||||||
<tr>
|
<tr>
|
||||||
<td>\image html geo_arrows_small.png
|
<td>\image html geo_arrows_small.png
|
||||||
<td> JKQTPGeoArrow
|
<td> JKQTPGeoArrow
|
||||||
|
<tr>
|
||||||
|
<td>\image html geo_bezier_small.png
|
||||||
|
<td> JKQTPGeoBezierCurve
|
||||||
<tr>
|
<tr>
|
||||||
<td>\image html geo_rect_small.png
|
<td>\image html geo_rect_small.png
|
||||||
<td> JKQTPGeoRectangle
|
<td> JKQTPGeoRectangle
|
||||||
|
@ -12,7 +12,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
|
|||||||
<li>data management: allow for other datatypes than double, would be good to have, double, float, ints, bool, string ... as for images</li>
|
<li>data management: allow for other datatypes than double, would be good to have, double, float, ints, bool, string ... as for images</li>
|
||||||
<li>data management: binding for the <a href="https://eigen.tuxfamily.org/index.php?title=Main_Page">Eigen library</a></li>
|
<li>data management: binding for the <a href="https://eigen.tuxfamily.org/index.php?title=Main_Page">Eigen library</a></li>
|
||||||
<li>graphic elements: annotation graphic element with text positionable like legend, or with (0..1),(0..1)-coordinates within plot</li>
|
<li>graphic elements: annotation graphic element with text positionable like legend, or with (0..1),(0..1)-coordinates within plot</li>
|
||||||
<li>graphic elements: cubic/bezier curves for graphic elements</li>
|
|
||||||
<li>graphic elements: make coordinate systems selectable for all: x/y-axis, 0..1/0..1, topleft/topright... </li>
|
<li>graphic elements: make coordinate systems selectable for all: x/y-axis, 0..1/0..1, topleft/topright... </li>
|
||||||
<li>graphs: barchart/ranges chart with (x,y1,y2) or (x1,x2,y)</li>
|
<li>graphs: barchart/ranges chart with (x,y1,y2) or (x1,x2,y)</li>
|
||||||
<li>graphs: gant-chart as simplified vector field with (x,y1,y2) or (x1,x2,y), or (x,y,dx), (x,y,dy) ... different head/tail style</li>
|
<li>graphs: gant-chart as simplified vector field with (x,y1,y2) or (x1,x2,y), or (x,y,dx), (x,y,dy) ... different head/tail style</li>
|
||||||
|
@ -135,6 +135,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
|||||||
<li>NEW: JKQTPFinancialGraph for drawing candlestick or OHLC graphs of financial data, such as stock amrket prices (+example \ref JKQTPlotterFinancialChartExample)</li>
|
<li>NEW: JKQTPFinancialGraph for drawing candlestick or OHLC graphs of financial data, such as stock amrket prices (+example \ref JKQTPlotterFinancialChartExample)</li>
|
||||||
<li>NEW: stacked barcharts may have a small separation (default 1pt)</li>
|
<li>NEW: stacked barcharts may have a small separation (default 1pt)</li>
|
||||||
<li>NEW: autoscaling for barcharts works now, also when stacked and unstacked charts are combined in one plot</li>
|
<li>NEW: autoscaling for barcharts works now, also when stacked and unstacked charts are combined in one plot</li>
|
||||||
|
<li>NEW: JKQTPGeoBezierCurve for drawing bezier curves of degree 1-4 (+example \ref JKQTPlotterGeometricBezier)</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
|
||||||
<li>JKQTMathText:<ul>
|
<li>JKQTMathText:<ul>
|
||||||
|
BIN
doc/images/JKQTPGeoBezierCurveGraphic.png
Normal file
BIN
doc/images/JKQTPGeoBezierCurveGraphic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
doc/images/JKQTPGeoBezierCurveLogGraphic.png
Normal file
BIN
doc/images/JKQTPGeoBezierCurveLogGraphic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
doc/images/JKQTPGeoBezierCurveLogMath.png
Normal file
BIN
doc/images/JKQTPGeoBezierCurveLogMath.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
doc/images/JKQTPGeoBezierCurveMath.png
Normal file
BIN
doc/images/JKQTPGeoBezierCurveMath.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -72,6 +72,7 @@ if (JKQtPlotter_BUILD_LIB_JKQTPLOTTER)
|
|||||||
add_subdirectory(financialgraphs)
|
add_subdirectory(financialgraphs)
|
||||||
add_subdirectory(functionplot)
|
add_subdirectory(functionplot)
|
||||||
add_subdirectory(geo_arrows)
|
add_subdirectory(geo_arrows)
|
||||||
|
add_subdirectory(geo_bezier)
|
||||||
add_subdirectory(geo_simple)
|
add_subdirectory(geo_simple)
|
||||||
add_subdirectory(geo_coordinateaxis0)
|
add_subdirectory(geo_coordinateaxis0)
|
||||||
add_subdirectory(geometric)
|
add_subdirectory(geometric)
|
||||||
|
30
examples/geo_bezier/CMakeLists.txt
Normal file
30
examples/geo_bezier/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.23)
|
||||||
|
|
||||||
|
set(EXAMPLE_NAME geo_bezier)
|
||||||
|
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_link_libraries(${EXENAME} JKQTPExampleToolsLib)
|
||||||
|
target_include_directories(${EXENAME} PRIVATE ../../lib)
|
||||||
|
target_link_libraries(${EXENAME} ${jkqtplotter_namespace}JKQTPlotter${jkqtplotter_LIBNAME_VERSION_PART})
|
||||||
|
|
||||||
|
# precomiled headers to speed up compilation
|
||||||
|
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
|
||||||
|
target_precompile_headers(${EXENAME} REUSE_FROM jkqtptest_simpletest)
|
||||||
|
endif (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
|
||||||
|
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
#Installation of Qt DLLs on Windows
|
||||||
|
jkqtplotter_deployqt(${EXENAME})
|
34
examples/geo_bezier/README.md
Normal file
34
examples/geo_bezier/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Example (JKQTPlotter): Plotting Arrows {#JKQTPlotterGeometricBezier}
|
||||||
|
|
||||||
|
This project shows the capabilities of JKQTPlotter to also draw arrows as geometric elements, using JKQTPGeoBezierCurve.
|
||||||
|
|
||||||
|
The source code of the main application can be found in [`geo_bezier.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geo_bezier/geo_bezier.cpp). First a plot is generated. Then several types of bezier curves are added to the plot and their control points shown.
|
||||||
|
|
||||||
|
|
||||||
|
Here is an example for drawing a cubic bézier curve:
|
||||||
|
```.cpp
|
||||||
|
JKQTPGeoBezierCurve* bezCubic=new JKQTPGeoBezierCurve(&plot);
|
||||||
|
bezCubic->setCubic(QPointF(0.25,0.25), QPointF(0.8,2.5), QPointF(3.25,0.2), QPointF(3.75,2.75));
|
||||||
|
bezCubic->setLineColor(QColor("maroon"));
|
||||||
|
bezCubic->setHeadDecoratorSizeFactor(JKQTPArrow);
|
||||||
|
bezCubic->setTailDecoratorSizeFactor(JKQTPArrow);
|
||||||
|
plot.addGraph(bezCubic);
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally we also add symbols for each control point and a poly-line connecting them:
|
||||||
|
```.cpp
|
||||||
|
JKQTPGeoPolyLines* l2;
|
||||||
|
plot.addGraph(l2=new JKQTPGeoPolyLines(&plot, bezCubic->getPoints()));
|
||||||
|
l2->setLineColor(QColor("darkgrey"));
|
||||||
|
l2->setLineWidth(1);
|
||||||
|
JKQTPXYScatterGraph* scatCubic=new JKQTPXYScatterGraph(&plot);
|
||||||
|
scatCubic->setXYColumns(plot.getDatastore()->addCopiedPoints(bezCubic->getPoints()));
|
||||||
|
scatCubic->setSymbolColor(QColor("blue"));
|
||||||
|
scatCubic->setSymbolType(JKQTPCircle);
|
||||||
|
plot.addGraph(scatCubic);
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is the resulting plot:
|
||||||
|
|
||||||
|
![geo_bezier](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/geo_bezier.png)
|
||||||
|
|
149
examples/geo_bezier/geo_bezier.cpp
Normal file
149
examples/geo_bezier/geo_bezier.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/** \example geo_bezier.cpp
|
||||||
|
* Shows how to plot bezier curves as geometric elements with JKQTPlotter
|
||||||
|
*
|
||||||
|
* \ref JKQTPlotterGeometricBezier
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jkqtpexampleapplication.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include "jkqtplotter/jkqtplotter.h"
|
||||||
|
#include "jkqtplotter/graphs/jkqtpgeolines.h"
|
||||||
|
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
JKQTPAppSettingController highDPIController(argc, argv);
|
||||||
|
JKQTPExampleApplication app(argc, argv);
|
||||||
|
|
||||||
|
|
||||||
|
// 1. create a plotter window
|
||||||
|
JKQTPlotter plot;
|
||||||
|
|
||||||
|
// 2. format graph:
|
||||||
|
// 2.1 set the graph scales manually
|
||||||
|
plot.setXY(0.05,10.05,0.05,3.15);
|
||||||
|
// 2.2 set the asxpect ratio to 1
|
||||||
|
plot.getPlotter()->setMaintainAspectRatio(true);
|
||||||
|
plot.getPlotter()->setAspectRatio(10.05/3.05);
|
||||||
|
plot.getPlotter()->setMaintainAxisAspectRatio(true);
|
||||||
|
plot.getPlotter()->setAxisAspectRatio(10.05/3.05);
|
||||||
|
// 2.3 set the asxpect ratio to 1
|
||||||
|
plot.getXAxis()->setDrawGrid(false);
|
||||||
|
plot.getYAxis()->setDrawGrid(false);
|
||||||
|
|
||||||
|
auto fx1=[&](double i) { return 0.25+(3.0-i)*9.0/4.0;};
|
||||||
|
auto fx2=[&](double i) { return (4.0-i)*9.0/4.0;};
|
||||||
|
|
||||||
|
// 3.1 demonastrate linear bezier curve
|
||||||
|
JKQTPGeoBezierCurve* bezLine=new JKQTPGeoBezierCurve(&plot);
|
||||||
|
bezLine->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezLine->setLine(QPointF(fx1(0),0.25), QPointF(fx2(0),2.75));
|
||||||
|
bezLine->setLineColor(QColor("maroon"));
|
||||||
|
plot.addGraph(bezLine);
|
||||||
|
JKQTPXYScatterGraph* scatLine=new JKQTPXYScatterGraph(&plot);
|
||||||
|
scatLine->setXYColumns(plot.getDatastore()->addCopiedPoints(bezLine->getPoints()));
|
||||||
|
scatLine->setSymbolColor(QColor("blue"));
|
||||||
|
scatLine->setSymbolType(JKQTPCircle);
|
||||||
|
plot.addGraph(scatLine);
|
||||||
|
|
||||||
|
// 3.2 demonastrate quad bezier curve
|
||||||
|
JKQTPGeoPolyLines* l1;
|
||||||
|
JKQTPGeoBezierCurve* bezQuad=new JKQTPGeoBezierCurve(&plot);
|
||||||
|
bezQuad->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezQuad->setQuad(QPointF(fx1(1),0.25), QPointF(fx1(1)+0.25,2.5), QPointF(fx2(1),2.75));
|
||||||
|
bezQuad->setLineColor(QColor("maroon"));
|
||||||
|
plot.addGraph(bezQuad);
|
||||||
|
plot.addGraph(l1=new JKQTPGeoPolyLines(&plot, bezQuad->getPoints()));
|
||||||
|
l1->setLineColor(QColor("darkgrey"));
|
||||||
|
l1->setLineWidth(1);
|
||||||
|
JKQTPXYScatterGraph* scatQuad=new JKQTPXYScatterGraph(&plot);
|
||||||
|
scatQuad->setXYColumns(plot.getDatastore()->addCopiedPoints(bezQuad->getPoints()));
|
||||||
|
scatQuad->setSymbolColor(QColor("blue"));
|
||||||
|
scatQuad->setSymbolType(JKQTPCircle);
|
||||||
|
plot.addGraph(scatQuad);
|
||||||
|
|
||||||
|
// 3.3 demonastrate cubic bezier curve
|
||||||
|
JKQTPGeoPolyLines* l2;
|
||||||
|
JKQTPGeoBezierCurve* bezCubic=new JKQTPGeoBezierCurve(&plot);
|
||||||
|
bezCubic->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezCubic->setCubic(QPointF(fx1(2),0.25), QPointF(fx1(2)+0.4,2.5), QPointF(fx2(2)-0.25,0.2), QPointF(fx2(2),2.75));
|
||||||
|
bezCubic->setLineColor(QColor("maroon"));
|
||||||
|
bezCubic->setHeadDecoratorStyle(JKQTPArrow);
|
||||||
|
bezCubic->setTailDecoratorStyle(JKQTPArrow);
|
||||||
|
plot.addGraph(bezCubic);
|
||||||
|
plot.addGraph(l2=new JKQTPGeoPolyLines(&plot, bezCubic->getPoints()));
|
||||||
|
l2->setLineColor(QColor("darkgrey"));
|
||||||
|
l2->setLineWidth(1);
|
||||||
|
JKQTPXYScatterGraph* scatCubic=new JKQTPXYScatterGraph(&plot);
|
||||||
|
scatCubic->setXYColumns(plot.getDatastore()->addCopiedPoints(bezCubic->getPoints()));
|
||||||
|
scatCubic->setSymbolColor(QColor("blue"));
|
||||||
|
scatCubic->setSymbolType(JKQTPCircle);
|
||||||
|
plot.addGraph(scatCubic);
|
||||||
|
|
||||||
|
|
||||||
|
// 3.4 demonastrate quartic bezier curve
|
||||||
|
JKQTPGeoPolyLines* l3;
|
||||||
|
JKQTPGeoBezierCurve* bezQuart=new JKQTPGeoBezierCurve(&plot);
|
||||||
|
bezQuart->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezQuart->setQuartic(QPointF(fx1(3),2.25), QPointF((fx2(3)+fx1(3))/2.0,2), QPointF(fx1(3),0.75), QPointF((fx2(3)+fx1(3))/2.0,1.5), QPointF(fx2(3),0.2));
|
||||||
|
bezQuart->setLineColor(QColor("maroon"));
|
||||||
|
bezQuart->setHeadDecoratorStyle(JKQTPArrow);
|
||||||
|
bezQuart->setTailDecoratorStyle(JKQTPArrow);
|
||||||
|
plot.addGraph(bezQuart);
|
||||||
|
plot.addGraph(l3=new JKQTPGeoPolyLines(&plot, bezQuart->getPoints()));
|
||||||
|
l3->setLineColor(QColor("darkgrey"));
|
||||||
|
l3->setLineWidth(1);
|
||||||
|
JKQTPXYScatterGraph* scatQuartic=new JKQTPXYScatterGraph(&plot);
|
||||||
|
scatQuartic->setXYColumns(plot.getDatastore()->addCopiedPoints(bezQuart->getPoints()));
|
||||||
|
scatQuartic->setSymbolColor(QColor("blue"));
|
||||||
|
scatQuartic->setSymbolType(JKQTPCircle);
|
||||||
|
plot.addGraph(scatQuartic);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 4. show plotter and make it a decent size
|
||||||
|
plot.show();
|
||||||
|
plot.resize(600/plot.devicePixelRatioF(),250/plot.devicePixelRatioF());
|
||||||
|
|
||||||
|
|
||||||
|
app.addExportStepFunctor([&](){
|
||||||
|
bezLine->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezQuad->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezCubic->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezQuart->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
plot.redrawPlot();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.addExportStepFunctor([&](){
|
||||||
|
plot.getPlotter()->setMaintainAspectRatio(false);
|
||||||
|
plot.getPlotter()->setMaintainAxisAspectRatio(false);
|
||||||
|
plot.setXY(0.2,8.8,0.15,3.9);
|
||||||
|
bezLine->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezQuad->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezCubic->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
bezQuart->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
l1->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
l2->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
l3->setDrawMode(JKQTPGeometricPlotElement::DrawAsMathematicalCurve);
|
||||||
|
plot.getXAxis()->setLogAxis(true);
|
||||||
|
plot.getYAxis()->setLogAxis(true);
|
||||||
|
plot.redrawPlot();
|
||||||
|
});
|
||||||
|
app.addExportStepFunctor([&](){
|
||||||
|
plot.getPlotter()->setMaintainAspectRatio(false);
|
||||||
|
plot.getPlotter()->setMaintainAxisAspectRatio(false);
|
||||||
|
plot.getXAxis()->setLogAxis(true);
|
||||||
|
plot.getYAxis()->setLogAxis(true);
|
||||||
|
bezLine->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezQuad->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezCubic->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
bezQuart->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
l1->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
l2->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
l3->setDrawMode(JKQTPGeometricPlotElement::DrawAsGraphicElement);
|
||||||
|
plot.redrawPlot();
|
||||||
|
});
|
||||||
|
return app.exec();
|
||||||
|
}
|
@ -333,8 +333,8 @@ inline T jkqtp_sqr(const T& v) {
|
|||||||
\ingroup jkqtptools_math_basic
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T jkqtp_pow4(T x) {
|
inline T jkqtp_pow4(T x) {
|
||||||
const T xx=x*x;
|
const T xx=x*x;
|
||||||
return xx*xx;
|
return xx*xx;
|
||||||
}
|
}
|
||||||
@ -529,6 +529,7 @@ inline double jkqtp_polyEval(double x, PolyItP firstP, PolyItP lastP) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief a C++-functor, which evaluates a polynomial
|
/*! \brief a C++-functor, which evaluates a polynomial
|
||||||
\ingroup jkqtptools_math_basic
|
\ingroup jkqtptools_math_basic
|
||||||
*/
|
*/
|
||||||
@ -578,12 +579,79 @@ QString jkqtp_polynomialModel2Latex(PolyItP firstP, PolyItP lastP) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Calculates a factorial \f$ n!=n\cdot(n-1)\cdot(n-2)\cdot...\cdot2\cdot1 \f$
|
||||||
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <class T=int>
|
||||||
|
#ifdef __cpp_consteval
|
||||||
|
consteval
|
||||||
|
#else
|
||||||
|
constexpr
|
||||||
|
#endif
|
||||||
|
T jkqtp_factorial(T n) {
|
||||||
|
T result = 1;
|
||||||
|
for (T i =1; i <= n; i++){
|
||||||
|
result = result*i;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Calculates a combination \f$ \left(\stackrel{n}{k}\right)=\frac{n!}{k!\cdot(n-k)!} \f$
|
||||||
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <class T=int>
|
||||||
|
#ifdef __cpp_consteval
|
||||||
|
consteval
|
||||||
|
#else
|
||||||
|
constexpr
|
||||||
|
#endif
|
||||||
|
T jkqtp_combination(T n, T k) {
|
||||||
|
if (n==k) return 1;
|
||||||
|
if (k==0) return 1;
|
||||||
|
if (k>n) return 0;
|
||||||
|
return jkqtp_factorial(n)/(jkqtp_factorial(k)*jkqtp_factorial(n-k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief creates a functor that evaluates the Bernstein polynomial \f$ B_i^n(t):=\left(\stackrel{n}{i}\right)\cdot t^i\cdot(1-t)^{n-1},\ \ \ \ 0\leq i\leq n \f$
|
||||||
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::function<T(T)> jkqtp_makeBernstein(int n, int i){
|
||||||
|
if (n==0 && i==0) return [=](T t) { return 1; };
|
||||||
|
if (n==1 && i==0) return [=](T t) { return (1.0-t); };
|
||||||
|
if (n==1 && i==1) return [=](T t) { return t; };
|
||||||
|
if (n==2 && i==0) return [=](T t) { return jkqtp_sqr(1.0-t); };
|
||||||
|
if (n==2 && i==1) return [=](T t) { return T(2.0)*t*(1.0-t); };
|
||||||
|
if (n==2 && i==2) return [=](T t) { return jkqtp_sqr(t); };
|
||||||
|
if (n==3 && i==0) return [=](T t) { return T(1)*jkqtp_cube(1.0-t); };
|
||||||
|
if (n==3 && i==1) return [=](T t) { return T(3)*t*jkqtp_sqr(1.0-t); };
|
||||||
|
if (n==3 && i==2) return [=](T t) { return T(3)*jkqtp_sqr(t)*(1.0-t); };
|
||||||
|
if (n==3 && i==3) return [=](T t) { return T(1)*jkqtp_cube(t); };
|
||||||
|
if (n==4 && i==0) return [=](T t) { return T(1)*jkqtp_pow4(1.0-t); };
|
||||||
|
if (n==4 && i==1) return [=](T t) { return T(4)*t*jkqtp_cube(1.0-t); };
|
||||||
|
if (n==4 && i==2) return [=](T t) { return T(6)*jkqtp_sqr(t)*jkqtp_sqr(1.0-t); };
|
||||||
|
if (n==4 && i==3) return [=](T t) { return T(4)*jkqtp_cube(t)*(1.0-t); };
|
||||||
|
if (n==4 && i==4) return [=](T t) { return T(1)*jkqtp_pow4(t); };
|
||||||
|
const T fac=jkqtp_combination<int64_t>(n,i);
|
||||||
|
return [=](T t) { return fac*pow(t,i)*pow(1.0-t,n-i); };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief calculate the grwates common divisor (GCD) of \a a and \a b
|
/*! \brief calculate the grwates common divisor (GCD) of \a a and \a b
|
||||||
\ingroup jkqtptools_math_basic
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
*/
|
*/
|
||||||
JKQTCOMMON_LIB_EXPORT uint64_t jkqtp_gcd(uint64_t a, uint64_t b);
|
JKQTCOMMON_LIB_EXPORT uint64_t jkqtp_gcd(uint64_t a, uint64_t b);
|
||||||
|
|
||||||
|
|
||||||
/*! \brief calculates numeratur integer part \a intpart , \a num and denominator \a denom of a fraction, representing a given floating-point number \a input
|
/*! \brief calculates numeratur integer part \a intpart , \a num and denominator \a denom of a fraction, representing a given floating-point number \a input
|
||||||
\ingroup jkqtptools_math_basic
|
\ingroup jkqtptools_math_basic
|
||||||
|
|
||||||
|
@ -521,6 +521,8 @@ JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTBasePlotter* parent, const QVector<QPoi
|
|||||||
JKQTPGeoBaseDecoratedLine(parent)
|
JKQTPGeoBaseDecoratedLine(parent)
|
||||||
{
|
{
|
||||||
this->points=points;
|
this->points=points;
|
||||||
|
setHeadDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
setTailDecoratorStyle(JKQTPNoDecorator);
|
||||||
}
|
}
|
||||||
|
|
||||||
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTPlotter* parent, const QVector<QPointF>& points):
|
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTPlotter* parent, const QVector<QPointF>& points):
|
||||||
@ -845,3 +847,226 @@ bool JKQTPGeoArc::getYMinMax(double& miny, double& maxy, double& smallestGreater
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTBasePlotter *parent, const QPointF &start, const QPointF &control1, const QPointF &end):
|
||||||
|
JKQTPGeoBaseDecoratedLine(parent)
|
||||||
|
{
|
||||||
|
setQuad(start,control1,end);
|
||||||
|
setHeadDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
setTailDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTPlotter *parent, const QPointF &start, const QPointF &control1, const QPointF &end):
|
||||||
|
JKQTPGeoBezierCurve(parent->getPlotter(),start,control1,end)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTBasePlotter *parent, const QPointF &start, const QPointF &control1, const QPointF &control2, const QPointF &end):
|
||||||
|
JKQTPGeoBaseDecoratedLine(parent)
|
||||||
|
{
|
||||||
|
setCubic(start,control1,control2,end);
|
||||||
|
setHeadDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
setTailDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTPlotter *parent, const QPointF &start, const QPointF &control1, const QPointF &control2, const QPointF &end):
|
||||||
|
JKQTPGeoBezierCurve(parent->getPlotter(),start,control1,control2,end)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTBasePlotter *parent):
|
||||||
|
JKQTPGeoBaseDecoratedLine(parent)
|
||||||
|
{
|
||||||
|
setHeadDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
setTailDecoratorStyle(JKQTPNoDecorator);
|
||||||
|
}
|
||||||
|
|
||||||
|
JKQTPGeoBezierCurve::JKQTPGeoBezierCurve(JKQTPlotter *parent):
|
||||||
|
JKQTPGeoBezierCurve(parent->getPlotter())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKQTPGeoBezierCurve::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
||||||
|
minx=0;
|
||||||
|
maxx=0;
|
||||||
|
smallestGreaterZero=0;
|
||||||
|
if (points.size()>0) {
|
||||||
|
minx=points[0].x();
|
||||||
|
maxx=points[0].x();
|
||||||
|
for (int i=1; i<points.size(); i++) {
|
||||||
|
double x=points[i].x();
|
||||||
|
if (x>maxx) maxx=x;
|
||||||
|
if (x<minx) minx=x;
|
||||||
|
double xvsgz;
|
||||||
|
xvsgz=x; SmallestGreaterZeroCompare_xvsgz();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
//qDebug()<<"getXMinMax"<<minx<<maxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JKQTPGeoBezierCurve::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
||||||
|
miny=0;
|
||||||
|
maxy=0;
|
||||||
|
smallestGreaterZero=0;
|
||||||
|
if (points.size()>0) {
|
||||||
|
miny=points[0].y();
|
||||||
|
maxy=points[0].y();
|
||||||
|
for (int i=1; i<points.size(); i++) {
|
||||||
|
double y=points[i].y();
|
||||||
|
if (y>maxy) maxy=y;
|
||||||
|
if (y<miny) miny=y;
|
||||||
|
double xvsgz;
|
||||||
|
xvsgz=y; SmallestGreaterZeroCompare_xvsgz();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
//qDebug()<<"getYMinMax"<<miny<<maxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPGeoBezierCurve::draw(JKQTPEnhancedPainter& painter) {
|
||||||
|
clearHitTestData();
|
||||||
|
if (points.size()>=2) {
|
||||||
|
reserveHitTestData(points.size());
|
||||||
|
|
||||||
|
double angle1, angle2;
|
||||||
|
QPointF xx1, xx2;
|
||||||
|
bool doDrawDecorator=false;
|
||||||
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||||
|
painter.setPen(getLinePen(painter, parent));
|
||||||
|
painter.setBrush(Qt::NoBrush);
|
||||||
|
if ((points.size()<=4) && ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis()))) {
|
||||||
|
const QVector<QPointF> path=transform(points);
|
||||||
|
angle1=atan2(path[1].y()-path[0].y(), path[1].x()-path[0].x());
|
||||||
|
angle2=atan2(path[path.size()-2].y()-path[path.size()-1].y(), path[path.size()-2].x()-path[path.size()-1].x());
|
||||||
|
xx1=path[0];
|
||||||
|
xx2=path[path.size()-1];
|
||||||
|
QPainterPath ppath;
|
||||||
|
if (path.size()>0) ppath.moveTo(path[0]);
|
||||||
|
if (path.size()==2) ppath.lineTo(path[1]);
|
||||||
|
else if (path.size()==3) ppath.quadTo(path[1], path[2]);
|
||||||
|
else if (path.size()==4) ppath.cubicTo(path[1], path[2], path[3]);
|
||||||
|
|
||||||
|
// draw corrected line
|
||||||
|
if (path.size()>0) {
|
||||||
|
painter.drawPath(ppath);
|
||||||
|
doDrawDecorator=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (points.size()>1) {
|
||||||
|
std::function<QPointF(double)> plotfunc;
|
||||||
|
const auto B2_0=jkqtp_makeBernstein<double>(2,0);
|
||||||
|
const auto B2_1=jkqtp_makeBernstein<double>(2,1);
|
||||||
|
const auto B2_2=jkqtp_makeBernstein<double>(2,2);
|
||||||
|
const auto B3_0=jkqtp_makeBernstein<double>(3,0);
|
||||||
|
const auto B3_1=jkqtp_makeBernstein<double>(3,1);
|
||||||
|
const auto B3_2=jkqtp_makeBernstein<double>(3,2);
|
||||||
|
const auto B3_3=jkqtp_makeBernstein<double>(3,3);
|
||||||
|
const auto B4_0=jkqtp_makeBernstein<double>(4,0);
|
||||||
|
const auto B4_1=jkqtp_makeBernstein<double>(4,1);
|
||||||
|
const auto B4_2=jkqtp_makeBernstein<double>(4,2);
|
||||||
|
const auto B4_3=jkqtp_makeBernstein<double>(4,3);
|
||||||
|
const auto B4_4=jkqtp_makeBernstein<double>(4,4);
|
||||||
|
if (points.size()==2) plotfunc=[&](double t) -> QPointF { return points[0]+t*(points[1]-points[0]); };
|
||||||
|
else if (points.size()==3) plotfunc=[&](double t) -> QPointF { return points[0]*B2_0(t)+points[1]*B2_1(t)+points[2]*B2_2(t); };
|
||||||
|
else if (points.size()==4) plotfunc=[&](double t) -> QPointF { return points[0]*B3_0(t)+points[1]*B3_1(t)+points[2]*B3_2(t)+points[3]*B3_3(t); };
|
||||||
|
else if (points.size()==5) plotfunc=[&](double t) -> QPointF { return points[0]*B4_0(t)+points[1]*B4_1(t)+points[2]*B4_2(t)+points[3]*B4_3(t)+points[4]*B4_4(t); };
|
||||||
|
|
||||||
|
if (plotfunc) {
|
||||||
|
std::function<QPointF(double)> fTransformedFunc= std::bind([plotfunc](const JKQTPPlotElement* plot, double t) -> QPointF { return plot->transform(plotfunc(t)); }, this, std::placeholders::_1);
|
||||||
|
const int minSamples=10;
|
||||||
|
const int maxRefinementDegree=5;
|
||||||
|
const double slopeTolerance=0.005;
|
||||||
|
const int minPixelPerSample=32;
|
||||||
|
const double maxConsecutiveAngleDegree=0.2;
|
||||||
|
JKQTPAdaptiveFunctionGraphEvaluator evaluator(fTransformedFunc, minSamples, maxRefinementDegree, slopeTolerance, minPixelPerSample);
|
||||||
|
QVector<QPointF> data=evaluator.evaluate(0,1);
|
||||||
|
data=JKQTPSimplyfyLineSegemnts(data, maxConsecutiveAngleDegree);
|
||||||
|
|
||||||
|
painter.drawPolylineFast(data.data(), data.size());
|
||||||
|
doDrawDecorator=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// potentially draw line-end decorators/arrows
|
||||||
|
if (doDrawDecorator) {
|
||||||
|
painter.setBrush(getLineColor());
|
||||||
|
JKQTPPlotLineDecorator(painter, xx1.x(), xx1.y(), angle1, getTailDecoratorStyle(), calcTailDecoratorSize(getLinePen(painter, getParent()).widthF()));
|
||||||
|
JKQTPPlotLineDecorator(painter, xx2.x(), xx2.y(), angle2, getHeadDecoratorStyle(), calcHeadDecoratorSize(getLinePen(painter, getParent()).widthF()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (const auto& p:points) {
|
||||||
|
addHitTestData(p.x(), p.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void JKQTPGeoBezierCurve::setPoints(const QVector<QPointF> &__value)
|
||||||
|
{
|
||||||
|
const int maxPoints=5;
|
||||||
|
if (points.size()<2 || points.size()>maxPoints) throw std::runtime_error("JKQTPGeoBezierCurve only supports 2, 3 ... or "+std::to_string(maxPoints)+" points, but you supplied "+std::to_string(__value.size())+"!");
|
||||||
|
points=__value;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QPointF> JKQTPGeoBezierCurve::getPoints() const
|
||||||
|
{
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JKQTPGeoBezierCurve::getStart() const
|
||||||
|
{
|
||||||
|
return points[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JKQTPGeoBezierCurve::getEnd() const
|
||||||
|
{
|
||||||
|
return points.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JKQTPGeoBezierCurve::getControl1() const
|
||||||
|
{
|
||||||
|
return points[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JKQTPGeoBezierCurve::getControl2() const
|
||||||
|
{
|
||||||
|
return points[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPGeoBezierCurve::setLine(const QPointF &start, const QPointF &end)
|
||||||
|
{
|
||||||
|
points={start,end};
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPGeoBezierCurve::setQuad(const QPointF &start, const QPointF &control1, const QPointF &end)
|
||||||
|
{
|
||||||
|
points={start,control1,end};
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPGeoBezierCurve::setCubic(const QPointF &start, const QPointF &control1, const QPointF &control2, const QPointF &end)
|
||||||
|
{
|
||||||
|
points={start,control1,control2,end};
|
||||||
|
}
|
||||||
|
|
||||||
|
void JKQTPGeoBezierCurve::setQuartic(const QPointF &start, const QPointF &control1, const QPointF &control2, const QPointF &control3, const QPointF &end)
|
||||||
|
{
|
||||||
|
points={start,control1,control2,control3,end};
|
||||||
|
}
|
||||||
|
|
||||||
|
int JKQTPGeoBezierCurve::getDegree() const
|
||||||
|
{
|
||||||
|
return points.size()-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JKQTPGeoBezierCurve::getNumberOfCOntrolPoints() const
|
||||||
|
{
|
||||||
|
return points.size();
|
||||||
|
}
|
||||||
|
@ -452,6 +452,127 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGeoPolyLines: public JKQTPGeoBaseDecoratedLine
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief This JKQTPGeometricPlotElement is used to draw a bezier curve
|
||||||
|
* \ingroup jkqtplotter_geoplots
|
||||||
|
*
|
||||||
|
* \image html JKQTPlotterGeometricBezierGraphic.png "drawn with JKQTPGeometricPlotElement::DrawMode::DrawAsGraphicElement"
|
||||||
|
*
|
||||||
|
* \see \ref JKQTPlotterGeometricBezier, JKQTPGeoBaseDecoratedLine
|
||||||
|
*
|
||||||
|
* \section JKQTPGeoBezierCurveDrawMode DrawMode for JKQTPGeoBezierCurve
|
||||||
|
* This class support JKQTPGeometricPlotElement::DrawMode::DrawAsMathematicalCurve , which will only have a significant effect with logarithmic axes.
|
||||||
|
* THe image above is the default JKQTPGeometricPlotElement::DrawMode::DrawAsGraphicElement on a linear axis.
|
||||||
|
*
|
||||||
|
* On logarithmic axes (x&y) the two modes draw very different shapes:
|
||||||
|
*
|
||||||
|
* \image html JKQTPlotterGeometricBezierLogMath.png "drawn with JKQTPGeometricPlotElement::DrawMode::DrawAsMathematicalCurve"
|
||||||
|
* \image html JKQTPlotterGeometricBezierLogGraphic.png "drawn with JKQTPGeometricPlotElement::DrawMode::DrawAsGraphicElement"
|
||||||
|
*
|
||||||
|
* For DrawAsGraphicElement only the control points are converted to screen-coordinates, but drawing takes place in the (linear) screen-system.
|
||||||
|
* For DrawAsMathematicalCurve drawing is done in the log-coordinate system.
|
||||||
|
*
|
||||||
|
* \section JKQTPGeoBezierCurveDecorators Line-End Decorators for JKQTPGeoBezierCurve
|
||||||
|
*
|
||||||
|
* You can also activate line-end decorators (aka arrows) for this poly-line, by using code like this:
|
||||||
|
* \code
|
||||||
|
* bezier->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
|
||||||
|
* bezier->setTailDecoratorStyle(JKQTPCircleDecorator);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \see \ref JKQTPlotterGeometricBezier
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoBezierCurve: public JKQTPGeoBaseDecoratedLine {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
/** \brief class constructor with start, end and one control point (i.e. a quadratic bezier curve)
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
* \param points points on the polygon
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTBasePlotter* parent, const QPointF& start, const QPointF& control1, const QPointF& end);
|
||||||
|
/** \brief class constructor with start, end and one control point (i.e. a quadratic bezier curve)
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
* \param points points on the polygon
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTPlotter* parent, const QPointF& start, const QPointF& control1, const QPointF& end);
|
||||||
|
/** \brief class constructor with start, end and two control points (i.e. a cubic bezier curve)
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
* \param points points on the polygon
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTBasePlotter* parent, const QPointF& start, const QPointF& control1, const QPointF& control2, const QPointF& end);
|
||||||
|
/** \brief class constructor with start, end and two control points (i.e. a cubic bezier curve)
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
* \param points points on the polygon
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTPlotter* parent, const QPointF& start, const QPointF& control1, const QPointF& control2, const QPointF& end);
|
||||||
|
/** \brief class constructor
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTBasePlotter* parent);
|
||||||
|
/** \brief class constructor
|
||||||
|
*
|
||||||
|
* \param parent the parent plotter object
|
||||||
|
*/
|
||||||
|
JKQTPGeoBezierCurve(JKQTPlotter* parent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** \copydoc JKQTPPlotElement::getXMinMax() */
|
||||||
|
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
||||||
|
/** \copydoc JKQTPPlotElement::getYMinMax() */
|
||||||
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||||
|
|
||||||
|
/** \brief plots the graph to the plotter object specified as parent
|
||||||
|
*
|
||||||
|
* \note This function support JKQTPGeometricPlotElement::DrawMode::DrawAsMathematicalCurve. If set,
|
||||||
|
* and non-linear axes are chosen, the points of the poly-line will be possibly
|
||||||
|
* connected by curves, instead of straight lines. In the mode
|
||||||
|
* JKQTPGeometricPlotElement::DrawMode::DrawAsGraphicElement the points are connected by straight
|
||||||
|
* lines, independent of the linearity or non-linearity of the coordinate axes.
|
||||||
|
*/
|
||||||
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||||
|
|
||||||
|
/** \copydoc points */
|
||||||
|
void setPoints(const QVector<QPointF> & __value);
|
||||||
|
/** \copydoc points */
|
||||||
|
QVector<QPointF> getPoints() const;
|
||||||
|
|
||||||
|
/** \brief get the start point of the curve */
|
||||||
|
QPointF getStart()const;
|
||||||
|
/** \brief get the end point of the curve */
|
||||||
|
QPointF getEnd()const;
|
||||||
|
/** \brief get the control point 1 of the curve */
|
||||||
|
QPointF getControl1()const;
|
||||||
|
/** \brief get the control point 2 of the curve */
|
||||||
|
QPointF getControl2()const;
|
||||||
|
/** \brief set a linear bezier curve (2 control points) */
|
||||||
|
void setLine(const QPointF& start, const QPointF& end);
|
||||||
|
/** \brief set a quadratic bezier curve (3 control points) */
|
||||||
|
void setQuad(const QPointF& start, const QPointF& control1, const QPointF& end);
|
||||||
|
/** \brief set a cubic bezier curve (4 control points) */
|
||||||
|
void setCubic(const QPointF& start, const QPointF& control1, const QPointF& control2, const QPointF& end);
|
||||||
|
/** \brief set a cubic bezier curve (5 control points) */
|
||||||
|
void setQuartic(const QPointF& start, const QPointF& control1, const QPointF& control2, const QPointF& control3, const QPointF& end);
|
||||||
|
/** \brief get the degree of the curve (number of points -1) */
|
||||||
|
int getDegree() const;
|
||||||
|
/** \brief get the number of control points (including start and end) */
|
||||||
|
int getNumberOfCOntrolPoints() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** \brief list with all control points of the bezier curve
|
||||||
|
*
|
||||||
|
* \note This class supports at most 4 points are alllowed
|
||||||
|
*/
|
||||||
|
QVector<QPointF> points;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** \brief This JKQTPGeometricPlotElement is used to draw an arc
|
/** \brief This JKQTPGeometricPlotElement is used to draw an arc
|
||||||
* \ingroup jkqtplotter_geoplots
|
* \ingroup jkqtplotter_geoplots
|
||||||
*
|
*
|
||||||
|
@ -714,6 +714,119 @@ void JKQTPDatastore::copyColumnData(size_t toColumn, size_t fromColumn)
|
|||||||
setColumnImageWidth(toColumn, getColumnImageWidth(static_cast<int>(fromColumn)));
|
setColumnImageWidth(toColumn, getColumnImageWidth(static_cast<int>(fromColumn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const std::list<QPoint> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const std::list<QPointF> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const std::vector<QPoint> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const std::vector<QPointF> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const QList<QPoint> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const QList<QPointF> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION<QT_VERSION_CHECK(6,0,0)
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const QVector<QPoint> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::pair<size_t, size_t> JKQTPDatastore::addCopiedPoints(const QVector<QPointF> &points, const QString &namex, const QString &namey)
|
||||||
|
{
|
||||||
|
const auto cx=addColumn(points.size(),namex);
|
||||||
|
const auto cy=addColumn(points.size(),namey);
|
||||||
|
int i=0;
|
||||||
|
for (const auto& p: points) {
|
||||||
|
set(cx, i, p.x());
|
||||||
|
set(cy, i, p.y());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return {cx,cy};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
size_t JKQTPDatastore::addLinearColumn(size_t rows, double start, double end, const QString& name) {
|
size_t JKQTPDatastore::addLinearColumn(size_t rows, double start, double end, const QString& name) {
|
||||||
|
@ -824,6 +824,25 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPDatastore{
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief add two columns to the datastore. They will be filled with the values from \a points (first column: x-value, second column: y-value)
|
||||||
|
*
|
||||||
|
* \param points list of datapoints to add
|
||||||
|
* \param namex name for the column with the x-values
|
||||||
|
* \param namey name for the column with the y-values
|
||||||
|
* \return the IDs of the newly created column
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const QList<QPointF>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const QList<QPoint>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
#if QT_VERSION<QT_VERSION_CHECK(6,0,0)
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const QVector<QPointF>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const QVector<QPoint>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
#endif
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const std::vector<QPointF>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const std::vector<QPoint>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const std::list<QPointF>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
std::pair<size_t,size_t> addCopiedPoints(const std::list<QPoint>& points, const QString& namex=QString(""), const QString &namey=QString(""));
|
||||||
|
|
||||||
/** \brief add one column to the datastore. It will be filled with the values from \a first ... \a last
|
/** \brief add one column to the datastore. It will be filled with the values from \a first ... \a last
|
||||||
*
|
*
|
||||||
* \tparam TIterator a standard C++ iterator
|
* \tparam TIterator a standard C++ iterator
|
||||||
|
BIN
screenshots/geo_bezier.png
Normal file
BIN
screenshots/geo_bezier.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
screenshots/geo_bezier_small.png
Normal file
BIN
screenshots/geo_bezier_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
Loading…
Reference in New Issue
Block a user