improved arrows in geometric elements:

- JKQTPGeoLine, JKQTPGeoPolyLines and JKQTPGeoInfiniteLine support decorators
- improved decorator drawing
- more decorator types
- improved example geometry
- added specific example geo_arrows
- improved documentation
- code cleanup
This commit is contained in:
jkriege2 2020-08-23 13:13:53 +02:00
parent 9cba3fec25
commit 4e1c09c24b
55 changed files with 752 additions and 280 deletions

View File

@ -56,9 +56,6 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html parsedfunctionplot_small.png
<td> \subpage JKQTPlotterParsedFunctionPlot
<td> `JKQTPXParsedFunctionLineGraph` <br> plotting functions with the internal math equation parser/evaluator
<tr><td> \image html geometric_small.png
<td> \subpage JKQTPlotterGeometricGraphs
<td> `JKQTPPlotObject`, `JKQTPGeoArc`, `JKQTPGeoLine`, `JKQTPGeoRectangle`, ...
<tr><td> \image html boxplot_small.png
<td> \subpage JKQTPlotterBoxplotsGraphs
<td> `JKQTPBoxplotVerticalGraph`, `JKQTPBoxplotHorizontalGraph`, ...
@ -68,6 +65,18 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
</table>
\subsection jkqtp_extut_geometric Geometric Forms, Arrows, Annotaions ...
<table>
<tr><th> Screenshot <th> Description <th> Notes
<tr><td> \image html geometric_small.png
<td> \subpage JKQTPlotterGeometricGraphs
<td> `JKQTPPlotObject`, `JKQTPGeoArc`, `JKQTPGeoLine`, `JKQTPGeoRectangle`, ...
<tr><td> \image html geo_arrows_small.png
<td> \subpage JKQTPlotterGeometricArrows
<td> `JKQTPGeoArrow`, ...
</table>
\subsection jkqtp_extut_keyaxesstyles Styling the Plot, Keys, Axes, ...
<table>

View File

@ -429,7 +429,7 @@ This group assembles graphs that show their data with symbols and optionally wit
<td>\image html geo_line_small.png
<td> JKQTPGeoLine, JKQTPGeoInfiniteLine, JKQTPGeoPolyLines
<tr>
<td>\image html geo_arrow_small.png
<td>\image html geo_arrows_small.png
<td> JKQTPGeoArrow
<tr>
<td>\image html geo_rect_small.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 B

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 875 B

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -12,6 +12,7 @@ add_subdirectory(jkqtmathtext_test)
add_subdirectory(jkqtplot_test)
add_subdirectory(geo_arrows)
add_subdirectory(advplotstyling)
add_subdirectory(barchart)
add_subdirectory(boxplot)

View File

@ -22,12 +22,18 @@ 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/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/geometric_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geometric) | [Plotting Geometric Objects](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geometric) | |
| [![](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` |
## Styling the Plot, Keys, Axes, ...
| Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/geometric_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geometric) | [Plotting Geometric Objects](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geometric) | |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/geo_arrows_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geo_arrows) | [Plotting Arrows](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geo_arrows) | |
## Styling the Plot, Keys, Axes, ...
| Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/logaxes_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/logaxes) | [logarithmic axes](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/logaxes) | `JKQTPXYLineGraph` and `JKQTPGeoText` <br> C++ vector of data <br> logarithmic axes and styling <br> plot line styles <br> internal LaTeX parser <br> add commenting text to a graph |

View File

@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.0)
set(EXAMPLE_NAME geo_arrows)
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})

View File

@ -0,0 +1,76 @@
# Example (JKQTPlotter): Plotting Arrows {#JKQTPlotterGeometricArrows}
This project shows the capabilities of JKQTPlotter to also draw arrows as geometric elements, using JKQTPGeoArrow. The arrow head/tail are defined by the enum values in JKQTPLineDecoratorStyle.
The source code of the main application can be found in [`geo_arrows.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/geo_arrows/geo_arrows.cpp). First a plot is generated. Then several types of arrows are plotted onto the JKQtPlotter.
## Different types of arrows
A first table shows all available arrow tips in different sizes.
```.cpp
for (size_t i=0; i<static_cast<size_t>(JKQTPLineDecoratorCount); i++) {
auto const decor=static_cast<JKQTPLineDecoratorStyle>(i);
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.1, arr_y, 0.3, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 0.2));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.4, arr_y, 0.6, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 0.5));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.7, arr_y, 0.9, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 1));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 1.0, arr_y, 1.3, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 2));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 1.4, arr_y, 1.7, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 3));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.05, a->getY2(), "\\verb{"+JKQTPLineDecoratorStyle2String(decor)+"}", 12, a->getLineColor()));
arr_y+=arr_deltay;
}
```
Here is the resulting table:
![geo_arrow_tips](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/geo_arrow_tips.png)
Note how the head-size scales with the line-width, but not linearly, but rather sub-linearly, so the tips do not grow too strongly.
Also note that all arrows end at the designated line-end (here indicated by dashed grey lines), even circles and rectangle:
![geo_arrow_tipsatlineend](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/geo_arrow_tipsatlineend.png)
## Classes with support for arrows
You can use JKQTPGeoArrow and JKQTPGeoLine to draw arrows (JKQTPGeoArrow is just a convenience class that enables arrows by default, otherwise it is equal to JKQTPGeoLine).
In addition, also other classes can show line-decorators:
- JKQTPGeoLine
- JKQTPGeoPolyLines
- JKQTPGeoInfiniteLine
.
Here is an example of how to actiavate them for a JKQTPGeoPolyLines:
```.cpp
QVector<QPointF> points; points<<QPointF(3, 0.6)<<QPointF(4, 0.5)<<QPointF(3, 1.2)<<QPointF(4, 1.0);
JKQTPGeoPolyLines* polyLine=new JKQTPGeoPolyLines(&plot, points, QColor("blue"));
polyLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
polyLine->setTailDecoratorStyle(JKQTPCircleDecorator);
plot.addGraph(polyLine);
```
Here is the result:
![geo_arrow_polylines](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/geo_arrow_polylines.png)
For the class JKQTPGeoInfiniteLine the start can be decorated with an arrow (only if two_sided==false!):
```.cpp
JKQTPGeoInfiniteLine* infLine=new JKQTPGeoInfiniteLine(&plot, 1.5, 0.2, 1, 0.25, QColor("blue"), 2);
infLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
plot.addGraph(infLine);
```
Here is the result:
![geo_arrow_polylines](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/geo_arrow_inflines.png)
## Screenshot
The result of the complete example looks like this:
![geo_arrows](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/geo_arrows.png)

View File

@ -0,0 +1,103 @@
/** \example geo_arrows.cpp
* Shows how to plot arrows as geometric elements with JKQTPlotter
*
* \ref JKQTPlotterGeometricArrows
*/
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpgeometric.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// 1. create a plotter window
JKQTPlotter plot;
// 2. format graph:
// 2.1 set the graph scales manually
plot.setXY(0,4.05,0,3.15);
// 2.2 set the asxpect ratio to 1
plot.getPlotter()->setMaintainAspectRatio(true);
plot.getPlotter()->setAspectRatio(4.05/3.05);
plot.getPlotter()->setMaintainAxisAspectRatio(true);
plot.getPlotter()->setAxisAspectRatio(4.05/3.05);
// 2.3 set the asxpect ratio to 1
plot.getXAxis()->setDrawGrid(false);
plot.getYAxis()->setDrawGrid(false);
// 3.1 demonastrate all arrow heads
JKQTPGeoArrow* a;
double arr_y=0.1;
double arr_deltay=2.9/static_cast<double>(JKQTPLineDecoratorCount);
plot.addGraph(new JKQTPGeoText(&plot, 0.1, 3.0, "w_{line}=0.2", 12, QColor("darkred")));
plot.addGraph(new JKQTPGeoText(&plot, 0.4, 3.0, "w_{line}=0.5", 12, QColor("darkred")));
plot.addGraph(new JKQTPGeoText(&plot, 0.7, 3.0, "w_{line}=1", 12, QColor("darkred")));
plot.addGraph(new JKQTPGeoText(&plot, 1.0, 3.0, "w_{line}=2", 12, QColor("darkred")));
plot.addGraph(new JKQTPGeoText(&plot, 1.4, 3.0, "w_{line}=3", 12, QColor("darkred")));
for (size_t i=0; i<static_cast<size_t>(JKQTPLineDecoratorCount); i++) {
auto const decor=static_cast<JKQTPLineDecoratorStyle>(i);
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.1, arr_y, 0.3, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 0.2));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.4, arr_y, 0.6, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 0.5));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.7, arr_y, 0.9, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 1));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 1.0, arr_y, 1.3, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 2));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 1.4, arr_y, 1.7, arr_y+0.05, QColor("red"), decor, JKQTPNoDecorator, 3));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.05, a->getY2(), "\\verb{"+JKQTPLineDecoratorStyle2String(decor)+"}", 12, a->getLineColor()));
arr_y+=arr_deltay;
}
// 3.2 note that all decorators are drawn in a way that lets them end at the intended end-point of the line, even circles!
for (size_t i=0; i<6; i++) {
plot.addGraph(a=new JKQTPGeoArrow(&plot, 3+static_cast<double>(i)*0.15, 3, 3+static_cast<double>(i)*0.15, 2.75, QColor("blue"), static_cast<JKQTPLineDecoratorStyle>(i*4+1), static_cast<JKQTPLineDecoratorStyle>(i*4+2), static_cast<double>(i+1)*0.5));
plot.addGraph(a=new JKQTPGeoArrow(&plot, 3+static_cast<double>(i)*0.15, 2.5, 3+static_cast<double>(i)*0.15, 2.75, QColor("red"), static_cast<JKQTPLineDecoratorStyle>(i*4+3), static_cast<JKQTPLineDecoratorStyle>(i*4+4), static_cast<double>(i+1)*0.5));
}
plot.addGraph(new JKQTPGeoLine(&plot, 2.9, 2.5, 4.0, 2.5, QColor("silver"), 0.25, Qt::DashLine));
plot.addGraph(new JKQTPGeoLine(&plot, 2.9, 2.75, 4.0, 2.75, QColor("silver"), 0.25, Qt::DashLine));
plot.addGraph(new JKQTPGeoLine(&plot, 2.9, 3, 4.6, 3, QColor("silver"), 0.25, Qt::DashLine));
// 3.3 a JKQTPGeoLine with and without errow heads:
JKQTPGeoLine* line=new JKQTPGeoLine(&plot, 2.9, 2.3, 3.6, 2.4, QColor("red"), 2.0);
JKQTPGeoLine* line_heads=new JKQTPGeoLine(&plot, 2.9, 2.1, 3.6, 2.2, QColor("red"), 2.0);
line_heads->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
line_heads->setTailDecoratorStyle(JKQTPCircleDecorator);
plot.addGraph(line);
plot.addGraph(line_heads);
plot.addGraph(new JKQTPGeoSymbol(&plot, line->getX1(), line->getY1(), JKQTPCirclePlus, 8, QColor("silver")));
plot.addGraph(new JKQTPGeoSymbol(&plot, line->getX2(), line->getY2(), JKQTPCirclePlus, 8, QColor("silver")));
plot.addGraph(new JKQTPGeoSymbol(&plot, line_heads->getX1(), line_heads->getY1(), JKQTPCirclePlus, 8, QColor("silver")));
plot.addGraph(new JKQTPGeoSymbol(&plot, line_heads->getX2(), line_heads->getY2(), JKQTPCirclePlus, 8, QColor("silver")));
// 3.4 also the class JKQTPGeoPolyLines can decorate its start/end with arrows
QVector<QPointF> points; points<<QPointF(3, 0.8)<<QPointF(4, 0.7)<<QPointF(3, 1.2)<<QPointF(4, 1.0);
JKQTPGeoPolyLines* polyLine=new JKQTPGeoPolyLines(&plot, points, QColor("blue"));
polyLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
polyLine->setTailDecoratorStyle(JKQTPCircleDecorator);
plot.addGraph(polyLine);
// 3.5 also the class JKQTPGeoInfiniteLine can decorate its start with arrows (only if two_sided==false!)
JKQTPGeoInfiniteLine* infLine=new JKQTPGeoInfiniteLine(&plot, 3.5, 0.2, 1, 0.25, QColor("blue"), 2);
infLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
plot.addGraph(infLine);
plot.addGraph(new JKQTPGeoSymbol(&plot, infLine->getX(), infLine->getY(), JKQTPCirclePlus, 8, QColor("silver")));
plot.addGraph(new JKQTPGeoArrow(&plot, infLine->getX(), infLine->getY(), infLine->getX()+infLine->getDx(), infLine->getY()+infLine->getDy(), QColor("silver"), JKQTPArrow, JKQTPNoDecorator, 1));
/*
infLine=new JKQTPGeoInfiniteLine(&plot, 3.5, 0.1, -1, 0.25, QColor("darkblue"), 2);
infLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
infLine->setTwoSided(true);
plot.addGraph(infLine);
plot.addGraph(new JKQTPGeoSymbol(&plot, infLine->getX(), infLine->getY(), JKQTPCirclePlus, 8, QColor("silver")));
plot.addGraph(new JKQTPGeoArrow(&plot, infLine->getX(), infLine->getY(), infLine->getX()+infLine->getDx(), infLine->getY()+infLine->getDy(), QColor("silver"), JKQTPArrow, JKQTPNoDecorator, 1));
*/
// 4. show plotter and make it a decent size
plot.show();
plot.resize(1200,800);
return app.exec();
}

View File

@ -0,0 +1,27 @@
# source code for this simple demo
SOURCES = geo_arrows.cpp
# configure Qt
CONFIG += link_prl qt
QT += core gui xml svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
# output executable name
TARGET = geo_arrows
# include JKQTPlotter source code
DEPENDPATH += ../../lib ../../staticlib
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

View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += jkqtplotterlib geo_arrows
jkqtplotterlib.file = ../../qmake/staticlib/jkqtplotterlib/jkqtplotterlib.pro
geo_arrows.file=$$PWD/geo_arrows.pro
geo_arrows.depends = jkqtplotterlib

View File

@ -59,79 +59,21 @@ int main(int argc, char* argv[])
// 3.3 some arrows
plot.addGraph(new JKQTPGeoText(&plot, 0.1,2.95, "\\textbf{Arrows:}", 14, QColor("red")));
JKQTPGeoArrow* a;
double arr_y=2.9;
double arr_deltay=0.9/static_cast<double>(JKQTPLineDecoratorCount);
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPArrow, JKQTPNoDecorator, 2));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledArrow, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPFilledArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPTriangleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPTriangleArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledTriangleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPTriangleFilledArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPTriangleDecoratorAndStop, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPTriangleArrowAndStop", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledTriangleDecoratorAndStop, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPTriangleFilledArrowAndStop", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPDoubleArrow, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPDoubleArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledDoubleArrow, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPFilledDoubleArrow", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPCircleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPCircleDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledCircleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPFilledCircleDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPRectangleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPRectangleDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPFilledRectangleDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPFilledRectangleDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPArrowAndStop, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPArrowAndStop", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPDoubleArrowAndStop, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPDoubleArrowAndStop", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPVerticalDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPVerticalDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(a=new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.9, arr_y, QColor("red"), JKQTPBracketDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoText(&plot, a->getX2()+0.02, a->getY2(), "JKQTPBracketDecorator", 6, a->getLineColor()));
arr_y-=arr_deltay;
plot.addGraph(new JKQTPGeoArrow(&plot, 0.3, 2.1, 0.1, 2.9, QColor("green"), JKQTPTriangleDecoratorAndBar, JKQTPDiamondDecoratorAndBar, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.2, 2.1, 0.2, 2.9, QColor("blue"), JKQTPNoDecorator, JKQTPFilledTriangleDecoratorAndBar, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.1, 2.1, 0.3, 2.9, QColor("orange"), JKQTPDoubleArrowAndBar, JKQTPNoDecorator, 3));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.1, 2.05, 0.9, 2.05, QColor("blue"), JKQTPNoDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.1, 2.9, 0.75, 2.9, QColor("blue"), JKQTPNoDecorator, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.3, 2.1, 0.1, 2.45, QColor("green"), JKQTPTriangleDecoratorAndStop, JKQTPTriangleDecoratorAndStop, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.2, 2.1, 0.2, 2.45, QColor("blue"), JKQTPNoDecorator, JKQTPFilledTriangleDecoratorAndStop, 3));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.1, 2.1, 0.3, 2.45, QColor("orange"), JKQTPFilledTriangleDecoratorAndStop, JKQTPNoDecorator, 5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.6, 2.1, 0.4, 2.9, QColor("green"), JKQTPTriangleDecorator, JKQTPTriangleDecorator, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.5, 2.1, 0.5, 2.9, QColor("blue"), JKQTPNoDecorator, JKQTPFilledArrow, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.4, 2.1, 0.6, 2.9, QColor("orange"), JKQTPFilledArrow, JKQTPNoDecorator, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.6, 2.1, 0.4, 2.45, QColor("green"), JKQTPTriangleDecorator, JKQTPTriangleDecorator, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.5, 2.1, 0.5, 2.45, QColor("blue"), JKQTPNoDecorator, JKQTPArrowAndStop, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.4, 2.1, 0.6, 2.45, QColor("orange"), JKQTPArrowAndStop, JKQTPNoDecorator, 4));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.7, 2.1, 0.7, 2.5, QColor("green"), JKQTPArrowAndBar, JKQTPFilledArrow, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.8, 2.1, 0.8, 2.5, QColor("orange"), JKQTPArrowAndBar, JKQTPFilledArrow, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.9, 2.1, 0.9, 2.5, QColor("orange"), JKQTPArrowAndBar, JKQTPFilledArrow, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.4, 2.5, 0.4, 2.65, QColor("green"), JKQTPArrowAndStop, JKQTPFilledArrow, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.45, 2.5, 0.45, 2.65, QColor("blue"), JKQTPArrowAndStop, JKQTPFilledArrow, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.5, 2.5, 0.5, 2.65, QColor("orange"), JKQTPArrowAndStop, JKQTPFilledArrow, 1.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.55, 2.5, 0.55, 2.65, QColor("blue"), JKQTPArrowAndStop, JKQTPFilledArrow, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.6, 2.5, 0.6, 2.65, QColor("orange"), JKQTPArrowAndStop, JKQTPFilledArrow, 2.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.4, 2.7, 0.4, 2.9, QColor("green"), JKQTPTriangleDecoratorAndStop, JKQTPFilledCircleDecorator, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.45, 2.7, 0.45, 2.9, QColor("blue"), JKQTPTriangleDecoratorAndStop, JKQTPFilledCircleDecorator, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.5, 2.7, 0.5, 2.9, QColor("orange"), JKQTPTriangleDecoratorAndStop, JKQTPFilledCircleDecorator, 1.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.55, 2.7, 0.55, 2.9, QColor("blue"), JKQTPTriangleDecoratorAndStop, JKQTPFilledCircleDecorator, 2));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.6, 2.7, 0.6, 2.9, QColor("orange"), JKQTPTriangleDecoratorAndStop, JKQTPFilledCircleDecorator, 2.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.7, 2.7, 0.7, 2.9, QColor("green"), JKQTPTriangleDecoratorAndBar, JKQTPFilledCircleDecorator, 0.5));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.8, 2.7, 0.8, 2.9, QColor("orange"), JKQTPTriangleDecoratorAndBar, JKQTPFilledCircleDecorator, 1));
plot.addGraph(new JKQTPGeoArrow(&plot, 0.9, 2.7, 0.9, 2.9, QColor("orange"), JKQTPTriangleDecoratorAndBar, JKQTPFilledCircleDecorator, 2));

View File

@ -413,18 +413,26 @@ QString JKQTPLineDecoratorStyle2String(JKQTPLineDecoratorStyle pos)
case JKQTPFilledArrow: return "filled_arrow";
case JKQTPTriangleDecorator: return "triangle";
case JKQTPFilledTriangleDecorator: return "filled_triangle";
case JKQTPTriangleDecoratorAndStop: return "triangle_stop";
case JKQTPFilledTriangleDecoratorAndStop: return "filled_triangle_stop";
case JKQTPTriangleDecoratorAndBar: return "triangle_bar";
case JKQTPFilledTriangleDecoratorAndBar: return "filled_triangle_bar";
case JKQTPDoubleArrow: return "double_arrow";
case JKQTPFilledDoubleArrow: return "filled_double_arrow";
case JKQTPCircleDecorator: return "circle";
case JKQTPFilledCircleDecorator: return "filled_circle";
case JKQTPRectangleDecorator: return "rectangle";
case JKQTPFilledRectangleDecorator: return "filled_rectangle";
case JKQTPArrowAndStop: return "arrow_stop";
case JKQTPDoubleArrowAndStop: return "double_arrow_stop";
case JKQTPVerticalDecorator: return "vertical_line";
case JKQTPArrowAndBar: return "arrow_bar";
case JKQTPDoubleArrowAndBar: return "double_arrow_bar";
case JKQTPBarDecorator: return "bar";
case JKQTPBracketDecorator: return "bracket";
case JKQTPHalfBarDecorator: return "half_bar";
case JKQTPSkewedBarDecorator: return "skewed_bar";
case JKQTPHarpoonDecorator: return "harpoon";
case JKQTPHarpoonDecoratorAndBar: return "harpoon_bar";
case JKQTPDiamondDecorator: return "diamond";
case JKQTPFilledDiamondDecorator: return "filled_diamond";
case JKQTPDiamondDecoratorAndBar: return "diamond_bar";
case JKQTPFilledDiamondDecoratorAndBar: return "filled_diamond_bar";
case JKQTPLineDecoratorCount: JKQTPLineDecoratorStyle2String(JKQTPMaxLineDecoratorID);
}
return "";
@ -438,17 +446,25 @@ QString JKQTPLineDecoratorStyle2NameString(JKQTPLineDecoratorStyle pos)
case JKQTPFilledArrow: return QObject::tr("filled arrow");
case JKQTPTriangleDecorator: return QObject::tr("triangle");
case JKQTPFilledTriangleDecorator: return QObject::tr("filled triangle");
case JKQTPTriangleDecoratorAndStop: return QObject::tr("triangle with stop");
case JKQTPFilledTriangleDecoratorAndStop: return QObject::tr("filled triangle with stop");
case JKQTPTriangleDecoratorAndBar: return QObject::tr("triangle, with bar");
case JKQTPFilledTriangleDecoratorAndBar: return QObject::tr("filled triangle, with bar");
case JKQTPDoubleArrow: return QObject::tr("double arrow");
case JKQTPFilledDoubleArrow: return QObject::tr("filled double arrow");
case JKQTPCircleDecorator: return QObject::tr("circle");
case JKQTPFilledCircleDecorator: return QObject::tr("filled circle");
case JKQTPRectangleDecorator: return QObject::tr("rectangle");
case JKQTPFilledRectangleDecorator: return QObject::tr("filled rectangle");
case JKQTPArrowAndStop: return QObject::tr("arrow with stop");
case JKQTPDoubleArrowAndStop: return QObject::tr("double arrow with stop");
case JKQTPVerticalDecorator: return QObject::tr("vertical line");
case JKQTPArrowAndBar: return QObject::tr("arrow, with bar");
case JKQTPDoubleArrowAndBar: return QObject::tr("double arrow, with bar");
case JKQTPBarDecorator: return QObject::tr("full bar");
case JKQTPHalfBarDecorator: return QObject::tr("half bar");
case JKQTPSkewedBarDecorator: return QObject::tr("skewed bar");
case JKQTPHarpoonDecorator: return QObject::tr("harpoon");
case JKQTPHarpoonDecoratorAndBar: return QObject::tr("harpoon, with bar");
case JKQTPDiamondDecorator: return QObject::tr("diamond");
case JKQTPFilledDiamondDecorator: return QObject::tr("filled diamond");
case JKQTPDiamondDecoratorAndBar: return QObject::tr("diamond, with bar");
case JKQTPFilledDiamondDecoratorAndBar: return QObject::tr("filled diamond, with bar");
case JKQTPBracketDecorator: return QObject::tr("bracket");
case JKQTPLineDecoratorCount: JKQTPLineDecoratorStyle2NameString(JKQTPMaxLineDecoratorID);
}
@ -463,18 +479,32 @@ JKQTPLineDecoratorStyle String2JKQTPLineDecoratorStyle(const QString &pos)
if (s=="filled_arrow") return JKQTPFilledArrow;
if (s=="triangle") return JKQTPTriangleDecorator;
if (s=="filled_triangle") return JKQTPFilledTriangleDecorator;
if (s=="triangle_stop") return JKQTPTriangleDecoratorAndStop;
if (s=="filled_triangle_stop") return JKQTPFilledTriangleDecoratorAndStop;
if (s=="triangle_bar") return JKQTPTriangleDecoratorAndBar;
if (s=="filled_triangle_bar") return JKQTPFilledTriangleDecoratorAndBar;
if (s=="double_arrow") return JKQTPDoubleArrow;
if (s=="filled_double_arrow") return JKQTPFilledDoubleArrow;
if (s=="circle") return JKQTPCircleDecorator;
if (s=="filled_circle") return JKQTPFilledCircleDecorator;
if (s=="rectangle") return JKQTPRectangleDecorator;
if (s=="filled_rectangle") return JKQTPFilledRectangleDecorator;
if (s=="arrow_stop") return JKQTPArrowAndStop;
if (s=="double_arrow_stop") return JKQTPDoubleArrowAndStop;
if (s=="vertical_line") return JKQTPVerticalDecorator;
if (s=="arrow_bar") return JKQTPArrowAndBar;
if (s=="double_arrow_bar") return JKQTPDoubleArrowAndBar;
if (s=="bar" || s=="vertical_line") return JKQTPBarDecorator;
if (s=="half_bar") return JKQTPHalfBarDecorator;
if (s=="skewed_bar") return JKQTPSkewedBarDecorator;
if (s=="harpoon") return JKQTPHarpoonDecorator;
if (s=="harpoon_bar") return JKQTPHarpoonDecoratorAndBar;
if (s=="diamond") return JKQTPDiamondDecorator;
if (s=="filled_diamond") return JKQTPFilledDiamondDecorator;
if (s=="diamond_bar") return JKQTPDiamondDecoratorAndBar;
if (s=="filled_diamond_bar") return JKQTPFilledDiamondDecoratorAndBar;
if (s=="bracket") return JKQTPBracketDecorator;
return JKQTPNoDecorator;
}
double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor)
{
if (line_width<=0.75) return 3.0+(decoratorSizeFactor*0.75-3.0)/(0.75*0.75)*line_width*line_width;
if (line_width<=1.0) return decoratorSizeFactor*line_width;
return decoratorSizeFactor*pow(line_width, 0.7);
}

View File

@ -155,6 +155,14 @@ JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString&
/** \brief symbols that can be used to plot a datapoint for a graph
* \ingroup jkqtptools_drawing
*
* \image html geo_arrow_tips.png
*
* Note that all arrows end at the designated line-end (here indicated by dashed grey lines), even circles and rectangle:
*
* \image html geo_arrow_tipsatlineend.png
*
* \see \ref JKQTPlotterGeometricArrows and \ref JKQTPlotterGeometricGraphs
*/
enum JKQTPLineDecoratorStyle {
JKQTPNoDecorator=0, /*!< \brief no decorator, i.e. a simple line-end */
@ -162,21 +170,29 @@ enum JKQTPLineDecoratorStyle {
JKQTPFilledArrow, /*!< \brief a nice filled arrow tip \image html JKQTPFilledArrow.png */
JKQTPTriangleDecorator, /*!< \brief a triangular arrow tip \image html JKQTPTriangleDecorator.png */
JKQTPFilledTriangleDecorator, /*!< \brief a triangular filled arrow tip \image html JKQTPFilledTriangleDecorator.png */
JKQTPTriangleDecoratorAndStop, /*!< \brief a triangular arrow tip with a stop-line \image html JKQTPTriangleDecoratorAndStop.png */
JKQTPFilledTriangleDecoratorAndStop, /*!< \brief a triangular filled arrow tip with a stop-line \image html JKQTPFilledTriangleDecoratorAndStop.png */
JKQTPTriangleDecoratorAndBar, /*!< \brief a triangular arrow tip, with vertical bar \image html JKQTPTriangleDecoratorAndBar.png */
JKQTPFilledTriangleDecoratorAndBar, /*!< \brief a triangular filled arrow tip, with vertical bar \image html JKQTPFilledTriangleDecoratorAndBar.png */
JKQTPDoubleArrow, /*!< \brief a nice double-arrow tip \image html JKQTPDoubleArrow.png*/
JKQTPFilledDoubleArrow, /*!< \brief a nice filled double-arrow tip \image html JKQTPFilledDoubleArrow.png */
JKQTPCircleDecorator, /*!< \brief an open circle tip \image html JKQTPCircleDecorator.png */
JKQTPFilledCircleDecorator, /*!< \brief a filled circle tip \image html JKQTPFilledCircleDecorator.png */
JKQTPRectangleDecorator, /*!< \brief an open rectangle tip \image html JKQTPRectangleDecorator.png */
JKQTPFilledRectangleDecorator, /*!< \brief a filled rectangle tip \image html JKQTPFilledRectangleDecorator.png */
JKQTPArrowAndStop, /*!< \brief a simple arrow tip, unfilled with stop-line \image html JKQTPArrowAndStop.png */
JKQTPDoubleArrowAndStop, /*!< \brief a simple double-arrow tip, unfilled with stop-line \image html JKQTPDoubleArrowAndStop.png */
JKQTPVerticalDecorator, /*!< \brief a simple vertical stop-line \image html JKQTPVerticalDecorator.png */
JKQTPArrowAndBar, /*!< \brief a simple arrow tip, unfilled, with vertical bar \image html JKQTPArrowAndBar.png */
JKQTPDoubleArrowAndBar, /*!< \brief a simple double-arrow tip, unfilled, with vertical bar \image html JKQTPDoubleArrowAndBar.png */
JKQTPBarDecorator, /*!< \brief a full vertical bar \image html JKQTPBarDecorator.png */
JKQTPBracketDecorator, /*!< \brief a vertical bracket decorator \image html JKQTPBracketDecorator.png */
JKQTPDiamondDecorator, /*!< \brief an open diamond tip \image html JKQTPDiamondDecorator.png */
JKQTPDiamondDecoratorAndBar, /*!< \brief an open diamond tip \image html JKQTPDiamondDecoratorAndBar.png */
JKQTPFilledDiamondDecorator, /*!< \brief a filled diamond tip \image html JKQTPFilledDiamondDecorator.png */
JKQTPFilledDiamondDecoratorAndBar, /*!< \brief a filled diamond tip \image html JKQTPFilledDiamondDecoratorAndBar.png */
JKQTPHalfBarDecorator, /*!< \brief a half vertical bar \image html JKQTPHalfBarDecorator.png */
JKQTPHarpoonDecorator, /*!< \brief an harpoon arrow \image html JKQTPHarpoonDecorator.png */
JKQTPHarpoonDecoratorAndBar, /*!< \brief an harpoon arrow, with vertical bar \image html JKQTPHarpoonDecoratorAndBar.png */
JKQTPSkewedBarDecorator, /*!< \brief a skewed vertical bar \image html JKQTPSkewedBarDecorator.png */
JKQTPLineDecoratorCount, /*!< \brief can be used to iterate over all symbols using: <code>for (int i=0; i<static_cast<int>(JKQTPSymbolCount); i++) { JKQTPLineDecoratorStyle s=static_cast<JKQTPLineDecoratorStyle>(i); ... }</code> */
JKQTPMaxLineDecoratorID=JKQTPLineDecoratorCount-1, /*!< \brief points to the last available symbol, can be used to iterate over all symbols: <code>for (int i=0; i<=static_cast<int>(JKQTPMaxSymbolID); i++) { JKQTPLineDecoratorStyle s=static_cast<JKQTPLineDecoratorStyle>(i); ... }</code> */
JKQTPLineDecoratorCount, /*!< \brief can be used to iterate over all symbols using: <code>for (int i=0; i<static_cast<int>(JKQTPLineDecoratorCount); i++) { JKQTPLineDecoratorStyle s=static_cast<JKQTPLineDecoratorStyle>(i); ... }</code> */
JKQTPMaxLineDecoratorID=JKQTPLineDecoratorCount-1, /*!< \brief points to the last available symbol, can be used to iterate over all symbols: <code>for (int i=0; i<=static_cast<int>(JKQTPMaxLineDecoratorID); i++) { JKQTPLineDecoratorStyle s=static_cast<JKQTPLineDecoratorStyle>(i); ... }</code> */
JKQTPDefaultLineDecorator=JKQTPFilledArrow /*!< \brief a default symbol used for plotting */
};
@ -209,7 +225,9 @@ JKQTCOMMON_LIB_EXPORT JKQTPLineDecoratorStyle String2JKQTPLineDecoratorStyle(con
template <class TPainter>
inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double angle_rad, JKQTPLineDecoratorStyle style, double size, QPointF* line_start=nullptr);
/** \brief calculates the tail decorator size from the line width \a line_width, using decoratorSizeFactor and a non-linear scaling function that levels off towards small \a line_width and increases sub-linearly for large ones, so the arrow heads to not grow too much */
JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor)
;
/** \brief rotate a rectangle by given angle (rotates all points around the center of the rectangle and returns it as a QPolygonF)
* \ingroup jkqtptools_drawing
@ -923,7 +941,9 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
static double tan__default_theta_open_tip=tan(default_theta_open_tip);
static double default_theta_closed_tip=50.0/2.0 /180.0*JKQTPSTATISTICS_PI;
static double tan__default_theta_closed_tip=tan(default_theta_closed_tip);
const QPen pinit=painter.pen();
QPen pinit=painter.pen();
pinit.setCapStyle(Qt::FlatCap);
pinit.setJoinStyle(Qt::RoundJoin);
QPen p0=pinit;
p0.setWidthF(0);
{
@ -934,25 +954,31 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
switch(style) {
case JKQTPArrow:
case JKQTPArrowAndStop: {
case JKQTPArrowAndBar: {
const QPointF poly[3] = {
QPointF(size, -tan__default_theta_open_tip*size),
QPointF(0,0),
QPointF(size, tan__default_theta_open_tip*size)
};
painter.setPen(pinit);
if (style==JKQTPArrowAndStop) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
if (style==JKQTPArrowAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
painter.drawPolyline(poly, 3);
} break;
case JKQTPHarpoonDecorator:
case JKQTPHarpoonDecoratorAndBar: {
painter.setPen(pinit);
if (style==JKQTPHarpoonDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
painter.drawLine(QPointF(0,0), QPointF(size, tan__default_theta_open_tip*size));
} break;
case JKQTPDoubleArrow:
case JKQTPDoubleArrowAndStop: {
case JKQTPDoubleArrowAndBar: {
const QPointF poly[3] = {
QPointF(size, -tan__default_theta_open_tip*size),
QPointF(0,0),
QPointF(size, tan__default_theta_open_tip*size)
};
painter.setPen(pinit);
if (style==JKQTPDoubleArrowAndStop) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
if (style==JKQTPDoubleArrowAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
painter.drawPolyline(poly, 3);
painter.translate(4.0*pinit.widthF(),0);
painter.drawPolyline(poly, 3);
@ -968,16 +994,16 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
};
painter.drawPolygon(poly, 4);
if (style==JKQTPFilledDoubleArrow) {
painter.translate(0.25*size, 0);
painter.translate(0.5*size, 0);
painter.drawPolygon(poly, 4);
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
if (line_start) *line_start=QPointF(x,y)+QPointF(1.25*size*cos(angle_rad),1.25*size*sin(angle_rad));
} else {
if (line_start) *line_start=QPointF(x,y)+QPointF(0.75*size*cos(angle_rad),0.75*size*sin(angle_rad));
}
} break;
case JKQTPTriangleDecorator:
case JKQTPTriangleDecoratorAndStop: {
case JKQTPTriangleDecoratorAndBar: {
const QPointF poly[3] = {
QPointF(size, -tan__default_theta_closed_tip*size),
QPointF(0,0),
@ -986,12 +1012,12 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
painter.setBrush(Qt::NoBrush);
painter.setPen(pinit);
painter.drawConvexPolygon(poly, 3);
if (style==JKQTPTriangleDecoratorAndStop) painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
if (style==JKQTPTriangleDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
} break;
case JKQTPFilledTriangleDecorator:
case JKQTPFilledTriangleDecoratorAndStop: {
case JKQTPFilledTriangleDecoratorAndBar: {
const QPointF poly[3] = {
QPointF(size, -tan__default_theta_closed_tip*size),
QPointF(0,0),
@ -999,7 +1025,7 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
};
painter.setPen(p0);
painter.drawConvexPolygon(poly, 3);
if (style==JKQTPFilledTriangleDecoratorAndStop) {
if (style==JKQTPFilledTriangleDecoratorAndBar) {
painter.setPen(pinit);
painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
}
@ -1007,7 +1033,37 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
} break;
case JKQTPDiamondDecorator:
case JKQTPDiamondDecoratorAndBar: {
const QPointF poly[4] = {
QPointF(0,0),
QPointF(size/2.0, -tan__default_theta_closed_tip*size),
QPointF(size,0),
QPointF(size/2.0, tan__default_theta_closed_tip*size)
};
painter.setBrush(Qt::NoBrush);
painter.setPen(pinit);
painter.drawConvexPolygon(poly, 4);
if (style==JKQTPDiamondDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
} break;
case JKQTPFilledDiamondDecorator:
case JKQTPFilledDiamondDecoratorAndBar: {
const QPointF poly[4] = {
QPointF(0,0),
QPointF(size/2.0, -tan__default_theta_closed_tip*size),
QPointF(size,0),
QPointF(size/2.0, tan__default_theta_closed_tip*size)
};
painter.setPen(p0);
painter.drawConvexPolygon(poly, 4);
if (style==JKQTPFilledDiamondDecoratorAndBar) {
painter.setPen(pinit);
painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
}
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
} break;
case JKQTPCircleDecorator:
case JKQTPFilledCircleDecorator: {
@ -1017,8 +1073,8 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
} else {
painter.setPen(p0);
}
painter.drawEllipse(QRectF(-size/2.0,-size/2.0,size,size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size/2.0*cos(angle_rad),size/2.0*sin(angle_rad));
painter.drawEllipse(QRectF(0,-size/2.0,size,size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
} break;
case JKQTPRectangleDecorator:
@ -1029,14 +1085,25 @@ inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double
} else {
painter.setPen(p0);
}
painter.drawRect(QRectF(-size/2.0,-size/2.0,size,size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size/2.0*cos(angle_rad),size/2.0*sin(angle_rad));
painter.drawRect(QRectF(0,-size/2.0,size,size));
if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
} break;
case JKQTPVerticalDecorator: {
case JKQTPBarDecorator: {
painter.setPen(pinit);
painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
} break;
case JKQTPHalfBarDecorator: {
painter.setPen(pinit);
painter.drawLine(QPointF(0,0), QPointF(0,tan__default_theta_open_tip*size));
} break;
case JKQTPSkewedBarDecorator: {
painter.setPen(pinit);
painter.drawLine(QPointF(0.25*size,-tan__default_theta_open_tip*size), QPointF(-0.25*size,tan__default_theta_open_tip*size));
} break;
case JKQTPBracketDecorator: {
const QPointF poly[4] = {
QPointF(-size*0.2,-tan__default_theta_open_tip*size),

View File

@ -253,7 +253,7 @@ QColor JKQTPGeoText::getKeyLabelColor() const {
JKQTPGeoLine::JKQTPGeoLine(JKQTBasePlotter* parent, double x1, double y1, double x2, double y2, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoBaseDecoratedLine(color, lineWidth, JKQTPNoDecorator, JKQTPNoDecorator, style, parent)
{
this->x1=x1;
this->y1=y1;
@ -267,12 +267,14 @@ JKQTPGeoLine::JKQTPGeoLine(JKQTPlotter* parent, double x1, double y1, double x2,
}
JKQTPGeoLine::JKQTPGeoLine(JKQTBasePlotter *parent, double x1, double y1, double x2, double y2):
JKQTPGeoBaseLine(parent)
JKQTPGeoBaseDecoratedLine(parent)
{
this->x1=x1;
this->y1=y1;
this->x2=x2;
this->y2=y2;
setHeadDecoratorStyle(JKQTPNoDecorator);
setTailDecoratorStyle(JKQTPNoDecorator);
}
JKQTPGeoLine::JKQTPGeoLine(JKQTPlotter *parent, double x1, double y1, double x2, double y2):
@ -305,13 +307,20 @@ void JKQTPGeoLine::draw(JKQTPEnhancedPainter& painter) {
reserveHitTestData(2);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
QLineF l(QPointF(transformX(x1), transformY(y1)), QPointF(transformX(x2), transformY(y2)));
if (l.length()>0) {
painter.drawLine(l);
painter.setBrush(getLineColor());
QPointF xx1(transformX(x1),transformY(y1));
QPointF xx2(transformX(x2), transformY(y2));
const double angle1=atan2(xx2.y()-xx1.y(), xx2.x()-xx1.x());
const double angle2=atan2(xx1.y()-xx2.y(), xx1.x()-xx2.x());
if ( QLineF(xx1, xx2).length()>0) {
QPointF lx1=xx1, lx2=xx2;
JKQTPPlotLineDecorator(painter, xx1.x(), xx1.y(), angle1, getTailDecoratorStyle(), calcTailDecoratorSize(getLinePen(painter, getParent()).widthF()), &lx1);
JKQTPPlotLineDecorator(painter, xx2.x(), xx2.y(), angle2, getHeadDecoratorStyle(), calcHeadDecoratorSize(getLinePen(painter, getParent()).widthF()), &lx2);
// draw corrected line
painter.drawLine(QLineF(lx1, lx2));
addHitTestData(x1, y1);
addHitTestData(x2, y2);
}
}
void JKQTPGeoLine::setX1(double __value)
@ -362,12 +371,10 @@ double JKQTPGeoLine::getY2() const
JKQTPGeoArrow::JKQTPGeoArrow(JKQTBasePlotter* parent, double x1, double y1, double x2, double y2, QColor color, JKQTPLineDecoratorStyle headStyle, JKQTPLineDecoratorStyle tailStyle, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseDecoratedLine(color, lineWidth, headStyle, tailStyle, style, parent)
JKQTPGeoLine(parent, x1,y1,x2,y2,color, lineWidth, style)
{
this->x1=x1;
this->y1=y1;
this->x2=x2;
this->y2=y2;
setHeadDecoratorStyle(headStyle);
setTailDecoratorStyle(tailStyle);
}
JKQTPGeoArrow::JKQTPGeoArrow(JKQTPlotter* parent, double x1, double y1, double x2, double y2, QColor color, JKQTPLineDecoratorStyle headStyle, JKQTPLineDecoratorStyle tailStyle, double lineWidth, Qt::PenStyle style):
@ -376,94 +383,10 @@ JKQTPGeoArrow::JKQTPGeoArrow(JKQTPlotter* parent, double x1, double y1, double x
}
bool JKQTPGeoArrow::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
minx=qMin(x1, x2);
maxx=qMax(x1, x2);
smallestGreaterZero=0;
double xvsgz;
xvsgz=x1; SmallestGreaterZeroCompare_xvsgz();
xvsgz=x2; SmallestGreaterZeroCompare_xvsgz();
return true;
}
bool JKQTPGeoArrow::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
miny=qMin(y1, y2);
maxy=qMax(y1, y2);
smallestGreaterZero=0;
double xvsgz;
xvsgz=y1; SmallestGreaterZeroCompare_xvsgz();
xvsgz=y2; SmallestGreaterZeroCompare_xvsgz();
return true;
}
void JKQTPGeoArrow::draw(JKQTPEnhancedPainter& painter) {
clearHitTestData();
reserveHitTestData(2);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
painter.setBrush(getLineColor());
QPointF xx1(transformX(x1),transformY(y1));
QPointF xx2(transformX(x2), transformY(y2));
const double angle1=atan2(xx2.y()-xx1.y(), xx2.x()-xx1.x());
const double angle2=atan2(xx1.y()-xx2.y(), xx1.x()-xx2.x());
if ( QLineF(xx1, xx2).length()>0) {
QPointF lx1=xx1, lx2=xx2;
JKQTPPlotLineDecorator(painter, xx1.x(), xx1.y(), angle1, getTailDecoratorStyle(), getTailDecoratorSizeFactor()*getLinePen(painter, getParent()).widthF(), &lx1);
JKQTPPlotLineDecorator(painter, xx2.x(), xx2.y(), angle2, getHeadDecoratorStyle(), getHeadDecoratorSizeFactor()*getLinePen(painter, getParent()).widthF(), &lx2);
// draw corrected line
painter.drawLine(QLineF(lx1, lx2));
addHitTestData(x1, y1);
addHitTestData(x2, y2);
}
}
void JKQTPGeoArrow::setX1(double __value)
{
this->x1 = __value;
}
double JKQTPGeoArrow::getX1() const
{
return this->x1;
}
void JKQTPGeoArrow::setY1(double __value)
{
this->y1 = __value;
}
double JKQTPGeoArrow::getY1() const
{
return this->y1;
}
void JKQTPGeoArrow::setX2(double __value)
{
this->x2 = __value;
}
double JKQTPGeoArrow::getX2() const
{
return this->x2;
}
void JKQTPGeoArrow::setY2(double __value)
{
this->y2 = __value;
}
double JKQTPGeoArrow::getY2() const
{
return this->y2;
}
JKQTPGeoInfiniteLine::JKQTPGeoInfiniteLine(JKQTBasePlotter* parent, double x, double y, double dx, double dy, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoBaseDecoratedHeadLine(color, lineWidth, JKQTPNoDecorator, style, parent)
{
this->x=x;
this->y=y;
@ -621,8 +544,16 @@ void JKQTPGeoInfiniteLine::draw(JKQTPEnhancedPainter& painter) {
QString(", \\ensuremath{\\mathrm{\\mathbf{d}}y/\\mathrm{\\mathbf{d}}x\\;=\\;%1/%2\\;=\\;%3\\;=\\;%4\\degree}").arg(jkqtp_floattolatexqstr(dy, 3)).arg(jkqtp_floattolatexqstr(dx, 3)).arg(jkqtp_floattolatexqstr(dy/dx, 3)).arg(jkqtp_floattolatexqstr(atan2(dy,dx), 1)));
addHitTestData(x1, y1);
addHitTestData(x2, y2);
}
if (two_sided==false && x>=xmin && x<=xmax && y>=ymin && y<=ymax) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
painter.setBrush(getLineColor());
QPointF xx1(transformX(x),transformY(y));
const double angle1=atan2(l.dy(), l.dx());
JKQTPPlotLineDecorator(painter, xx1.x(), xx1.y(), angle1, getHeadDecoratorStyle(), calcHeadDecoratorSize(getLinePen(painter, getParent()).widthF()));
}
}
}
@ -682,23 +613,24 @@ bool JKQTPGeoInfiniteLine::getTwoSided() const
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTBasePlotter* parent, const QVector<QPointF>& points, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoBaseDecoratedLine(color, lineWidth, JKQTPNoDecorator, JKQTPNoDecorator, style, parent)
{
this->points=points;
}
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTPlotter* parent, const QVector<QPointF>& points, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoPolyLines(parent->getPlotter(), points, color, lineWidth, style)
{
this->points=points;
}
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTBasePlotter *parent, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoBaseDecoratedLine(color, lineWidth, JKQTPNoDecorator, JKQTPNoDecorator, style, parent)
{
}
JKQTPGeoPolyLines::JKQTPGeoPolyLines(JKQTPlotter *parent, QColor color, double lineWidth, Qt::PenStyle style):
JKQTPGeoBaseLine(color, lineWidth, style, parent)
JKQTPGeoPolyLines(parent->getPlotter(), color, lineWidth, style)
{
}
@ -745,17 +677,32 @@ bool JKQTPGeoPolyLines::getYMinMax(double& miny, double& maxy, double& smallestG
void JKQTPGeoPolyLines::draw(JKQTPEnhancedPainter& painter) {
clearHitTestData();
if (points.size()>=2) {
reserveHitTestData(points.size());
QPainterPath path=transformToLinePath(points);
QVector<QPointF> path=transform(points);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
painter.drawPath(path);
painter.setBrush(getLineColor());
// potentially draw line-end decorators/arrows
const double angle1=atan2(path[1].y()-path[0].y(), path[1].x()-path[0].x());
const double angle2=atan2(path[path.size()-2].y()-path[path.size()-1].y(), path[path.size()-2].x()-path[path.size()-1].x());
QPointF xx1=path[0], xx2=path[path.size()-1];
QPointF lx1=xx1, lx2=xx2;
JKQTPPlotLineDecorator(painter, xx1.x(), xx1.y(), angle1, getTailDecoratorStyle(), calcTailDecoratorSize(getLinePen(painter, getParent()).widthF()), &lx1);
JKQTPPlotLineDecorator(painter, xx2.x(), xx2.y(), angle2, getHeadDecoratorStyle(), calcHeadDecoratorSize(getLinePen(painter, getParent()).widthF()), &lx2);
path[0]=lx1;
path[path.size()-1]=lx2;
// draw corrected line
painter.drawPolyline(path.data(), path.size());
for (const auto& p:points) {
addHitTestData(p.x(), p.y());
}
}
}
void JKQTPGeoPolyLines::setPoints(const QVector<QPointF> &__value)
{
@ -1478,6 +1425,60 @@ QColor JKQTPGeoSymbol::getKeyLabelColor() const
return getSymbolColor();
}
JKQTPGeoBaseDecoratedHeadLine::JKQTPGeoBaseDecoratedHeadLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, Qt::PenStyle style, JKQTBasePlotter *parent):
JKQTPPlotObject(parent)
{
setLineColor(color);
setLineWidth(lineWidth);
setLineStyle(style);
setHeadDecoratorStyle(headStyle);
}
JKQTPGeoBaseDecoratedHeadLine::JKQTPGeoBaseDecoratedHeadLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, Qt::PenStyle style, JKQTPlotter *parent):
JKQTPGeoBaseDecoratedHeadLine(color, lineWidth, headStyle, style, parent->getPlotter())
{
}
JKQTPGeoBaseDecoratedHeadLine::JKQTPGeoBaseDecoratedHeadLine(JKQTBasePlotter *parent):
JKQTPPlotObject(parent)
{
}
JKQTPGeoBaseDecoratedHeadLine::JKQTPGeoBaseDecoratedHeadLine(JKQTPlotter *parent):
JKQTPPlotObject(parent->getPlotter())
{
}
void JKQTPGeoBaseDecoratedHeadLine::setAlpha(float alpha)
{
auto color=getLineColor();
color.setAlphaF(alpha);
setLineColor(color);
}
void JKQTPGeoBaseDecoratedHeadLine::setColor(QColor c)
{
setLineColor(c);
}
void JKQTPGeoBaseDecoratedHeadLine::drawKeyMarker(JKQTPEnhancedPainter &painter, QRectF &rect)
{
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
double y=rect.top()+rect.height()/2.0;
if (rect.width()>0) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
}
QColor JKQTPGeoBaseDecoratedHeadLine::getKeyLabelColor() const
{
return getLineColor();
}
JKQTPGeoBaseDecoratedLine::JKQTPGeoBaseDecoratedLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, JKQTPLineDecoratorStyle tailStyle, Qt::PenStyle style, JKQTBasePlotter *parent):
JKQTPPlotObject(parent)
{

View File

@ -79,6 +79,64 @@ public:
protected:
};
/*! \brief This JKQTPPlotObject is used as base class for geometric drawing
elements that consist of lines with one decorated end (i.e. no filling of any kind is done)
\ingroup jkqtplotter_geoplots
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoBaseDecoratedHeadLine: public JKQTPPlotObject, public JKQTPGraphDecoratedHeadLineStyleMixin {
Q_OBJECT
public:
/*! \brief class contructor
\param color color of drawing
\param lineWidth lineWidth of drawing
\param headStyle style of the head decoration
\param style line style of drawing
\param parent the parent plotter object
*/
explicit JKQTPGeoBaseDecoratedHeadLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, Qt::PenStyle style=Qt::SolidLine, JKQTBasePlotter* parent=nullptr);
/*! \brief class contructor
\param color color of drawing
\param lineWidth lineWidth of drawing
\param headStyle style of the head decoration
\param style line style of drawing
\param parent the parent plotter object
*/
explicit JKQTPGeoBaseDecoratedHeadLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, Qt::PenStyle style, JKQTPlotter* parent);
/*! \brief class contructor
*/
explicit JKQTPGeoBaseDecoratedHeadLine(JKQTBasePlotter* parent);
/*! \brief class contructor
*/
explicit JKQTPGeoBaseDecoratedHeadLine(JKQTPlotter* parent);
/** \brief sets the alpha-channel of the \a color (i.e. its transparency) */
virtual void setAlpha(float alpha);
/** \brief set line color */
virtual void setColor(QColor c);
/** \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;
protected:
};
/*! \brief This JKQTPPlotObject is used as base class for geometric drawing
elements that consist of lines with decorated ends (i.e. no filling of any kind is done)
\ingroup jkqtplotter_geoplots
@ -107,13 +165,9 @@ public:
\param parent the parent plotter object
*/
explicit JKQTPGeoBaseDecoratedLine(QColor color, double lineWidth, JKQTPLineDecoratorStyle headStyle, JKQTPLineDecoratorStyle tailStyle, Qt::PenStyle style, JKQTPlotter* parent);
/*! \brief class contructor
*/
/*! \brief class contructor */
explicit JKQTPGeoBaseDecoratedLine(JKQTBasePlotter* parent);
/*! \brief class contructor
*/
/*! \brief class contructor */
explicit JKQTPGeoBaseDecoratedLine(JKQTPlotter* parent);
@ -355,15 +409,30 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGeoText: public JKQTPPlotObject, public JKQTPG
QPen getPen(JKQTPEnhancedPainter& painter);
};
/*! \brief This JKQTPPlotObject is used to draw a line
/*! \brief This JKQTPPlotObject is used to draw a line, optionally line-end decorations (aka arrows) are pssible, but switched off by default.
\ingroup jkqtplotter_geoplots
\image html JKQTPGeoLine_HeadTail.png
\image html plot_geoline.png
\see \ref JKQTPlotterGeometricGraphs
You can also activate line-end decorators (aka arrows) for this poly-line, by using code like this:
\code
line->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
line->setTailDecoratorStyle(JKQTPCircleDecorator);
\endcode
This results in arrows drawn at the start (aka x1/y1, =tail) and end (aka x2/y2, =head) of the line.
\note The convenience class JKQTPGeoArrow activates line-end decorations (aka arows) by default and allows to select them in the constructor.
\see JKQTPGeoArrow, \ref JKQTPlotterGeometricGraphs and \ref JKQTPlotterGeometricArrows
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoLine: public JKQTPGeoBaseLine {
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoLine: public JKQTPGeoBaseDecoratedLine {
Q_OBJECT
public:
/*! \brief class constructor
@ -451,15 +520,19 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGeoLine: public JKQTPGeoBaseLine {
};
/*! \brief This JKQTPPlotObject is used to draw a line with decorations (e.g. arrows)
/*! \brief This convenience specialisation of JKQTPGeoLine is used to draw a line with decorations (e.g. arrows)
\ingroup jkqtplotter_geoplots
This class does not add any functionality on top of JKQTPGeoLine, just activates line-end markers by default!
\image html JKQTPGeoLine_HeadTail.png
\image html plot_geoarrows.png
\see \ref JKQTPlotterGeometricGraphs
\see JKQTPLineDecoratorStyle, JKQTPGeoLine, \ref JKQTPlotterGeometricArrows and \ref JKQTPlotterGeometricGraphs
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoArrow: public JKQTPGeoBaseDecoratedLine {
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoArrow: public JKQTPGeoLine {
Q_OBJECT
public:
/*! \brief class constructor
@ -489,43 +562,12 @@ public:
*/
JKQTPGeoArrow(JKQTPlotter* parent, double x1, double y1, double x2, double y2, QColor color, JKQTPLineDecoratorStyle headStyle=JKQTPDefaultLineDecorator, JKQTPLineDecoratorStyle tailStyle=JKQTPNoDecorator, double lineWidth=1.0, Qt::PenStyle style=Qt::SolidLine);
/** \copydoc JKQTPPlotObject::getXMinMax() */
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
/** \copydoc JKQTPPlotObject::getYMinMax() */
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter) override;
/*! \copydoc x1 */
void setX1(double __value);
/*! \copydoc x1 */
double getX1() const;
/*! \copydoc y1 */
void setY1(double __value);
/*! \copydoc y1 */
double getY1() const;
/*! \copydoc x2 */
void setX2(double __value);
/*! \copydoc x2 */
double getX2() const;
/*! \copydoc y2 */
void setY2(double __value);
/*! \copydoc y2 */
double getY2() const;
protected:
/** \brief x-coordinate of first point of line */
double x1;
/** \brief y-coordinate of first point of line */
double y1;
/** \brief x-coordinate of second point of line */
double x2;
/** \brief y-coordinate of second point of line */
double y2;
};
/*! \brief This JKQTPPlotObject is used to draw an infinite line
\ingroup jkqtplotter_geoplots
@ -534,10 +576,12 @@ protected:
\image html plot_geoinfiniteline.png
\see \ref JKQTPlotterGeometricGraphs
You can add a decorator to the head of the line (i.e. the given start point (x,y) ) iff this line is one-sided, i.e. two_sided \c ==false .
\see \ref JKQTPlotterGeometricGraphs and \ref JKQTPlotterGeometricArrows
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoInfiniteLine: public JKQTPGeoBaseLine {
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoInfiniteLine: public JKQTPGeoBaseDecoratedHeadLine {
Q_OBJECT
public:
/*! \brief class constructor
@ -614,10 +658,19 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGeoInfiniteLine: public JKQTPGeoBaseLine {
\image html plot_geolines.png
\see \ref JKQTPlotterGeometricGraphs
You can also activate line-end decorators (aka arrows) for this poly-line, by using code like this:
\code
polyLine->setHeadDecoratorStyle(JKQTPFilledDoubleArrow);
polyLine->setTailDecoratorStyle(JKQTPCircleDecorator);
\endcode
This results in arrows drawn at the start (=tail) and end (=head) of the poly-line:
\image html geo_arrow_polylines.png
\see \ref JKQTPlotterGeometricGraphs and \ref JKQTPlotterGeometricArrows
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoPolyLines: public JKQTPGeoBaseLine {
class JKQTPLOTTER_LIB_EXPORT JKQTPGeoPolyLines: public JKQTPGeoBaseDecoratedLine {
Q_OBJECT
public:
/*! \brief class constructor

View File

@ -456,7 +456,7 @@ JKQTPGraphDecoratedLineStyleMixin::JKQTPGraphDecoratedLineStyleMixin():
{
m_headDecoratorStyle=JKQTPLineDecoratorStyle::JKQTPDefaultLineDecorator;
m_tailDecoratorStyle=JKQTPLineDecoratorStyle::JKQTPNoDecorator;
m_tailDecoratorSizeFactor=m_headDecoratorSizeFactor=9.0;
m_tailDecoratorSizeFactor=m_headDecoratorSizeFactor=8.0;
}
void JKQTPGraphDecoratedLineStyleMixin::initDecoratedLineStyle(JKQTBasePlotter *parent, int &parentPlotStyle)
@ -508,3 +508,60 @@ double JKQTPGraphDecoratedLineStyleMixin::getTailDecoratorSizeFactor() const
{
return m_tailDecoratorSizeFactor;
}
double JKQTPGraphDecoratedLineStyleMixin::calcTailDecoratorSize(double line_width) const
{
return JKQTPLineDecoratorStyleCalcDecoratorSize(line_width, m_tailDecoratorSizeFactor);
}
double JKQTPGraphDecoratedLineStyleMixin::calcHeadDecoratorSize(double line_width) const
{
return JKQTPLineDecoratorStyleCalcDecoratorSize(line_width, m_headDecoratorSizeFactor);
}
JKQTPGraphDecoratedHeadLineStyleMixin::JKQTPGraphDecoratedHeadLineStyleMixin():
JKQTPGraphLineStyleMixin()
{
m_headDecoratorStyle=JKQTPLineDecoratorStyle::JKQTPDefaultLineDecorator;
m_headDecoratorSizeFactor=8.0;
}
void JKQTPGraphDecoratedHeadLineStyleMixin::initDecoratedHeadLineStyle(JKQTBasePlotter *parent, int &parentPlotStyle)
{
initLineStyle(parent, parentPlotStyle);
}
JKQTPGraphDecoratedHeadLineStyleMixin::~JKQTPGraphDecoratedHeadLineStyleMixin()
{
}
void JKQTPGraphDecoratedHeadLineStyleMixin::setHeadDecoratorStyle(const JKQTPLineDecoratorStyle &__value)
{
m_headDecoratorStyle=__value;
}
JKQTPLineDecoratorStyle JKQTPGraphDecoratedHeadLineStyleMixin::getHeadDecoratorStyle() const
{
return m_headDecoratorStyle;
}
void JKQTPGraphDecoratedHeadLineStyleMixin::setHeadDecoratorSizeFactor(const double &__value)
{
m_headDecoratorSizeFactor=__value;
}
double JKQTPGraphDecoratedHeadLineStyleMixin::getHeadDecoratorSizeFactor() const
{
return m_headDecoratorSizeFactor;
}
double JKQTPGraphDecoratedHeadLineStyleMixin::calcHeadDecoratorSize(double line_width) const
{
return JKQTPLineDecoratorStyleCalcDecoratorSize(line_width, m_headDecoratorSizeFactor);
}

View File

@ -145,6 +145,57 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGraphLineStyleMixin {
/*! \brief This Mix-In class provides setter/getter methods, storage and other facilities for the graph line style of lines
with a decorator (i.e. an arrow) at their head. It extends JKQTPGraphLineStyleMixin
\ingroup jkqtplotter_basegraphs_stylemixins
supported properties:
- head/ arrow style
.
\see JKQTPGraphDecoratedLineStyleMixin for a Mix-In for both ends
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGraphDecoratedHeadLineStyleMixin: public JKQTPGraphLineStyleMixin {
Q_GADGET
public:
/** \brief class constructor */
JKQTPGraphDecoratedHeadLineStyleMixin();
/** \brief initiaize the line style (from the parent plotter) */
void initDecoratedHeadLineStyle(JKQTBasePlotter *parent, int &parentPlotStyle);
virtual ~JKQTPGraphDecoratedHeadLineStyleMixin();
/** \brief set the head decorator style */
void setHeadDecoratorStyle(const JKQTPLineDecoratorStyle & __value);
/** \brief get the head decorator style */
JKQTPLineDecoratorStyle getHeadDecoratorStyle() const;
/** \copydoc m_headDecoratorSizeFactor */
void setHeadDecoratorSizeFactor(const double & __value);
/** \copydoc m_headDecoratorSizeFactor */
double getHeadDecoratorSizeFactor() const;
/** \brief calculates the tail decorator size from the line width \a line_width, using m_headDecoratorSizeFactor and a non-linear scaling function
*
* \see JKQTPLineDecoratorStyleCalcDecoratorSize()
*/
double calcHeadDecoratorSize(double line_width) const;
Q_PROPERTY(JKQTPLineDecoratorStyle headDecoratorStyle MEMBER m_headDecoratorStyle READ getHeadDecoratorStyle WRITE setHeadDecoratorStyle)
Q_PROPERTY(double headDecoratorSizeFactor MEMBER m_headDecoratorSizeFactor READ getHeadDecoratorSizeFactor WRITE setHeadDecoratorSizeFactor)
private:
/** \brief head decorator style */
JKQTPLineDecoratorStyle m_headDecoratorStyle;
/** \brief head decorator size-factor, used to calculate the size of the arrow from the line width */
double m_headDecoratorSizeFactor;
};
/*! \brief This Mix-In class provides setter/getter methods, storage and other facilities for the graph line style of lines
with decorators (i.e. arrows) at their ends. It extends JKQTPGraphLineStyleMixin
\ingroup jkqtplotter_basegraphs_stylemixins
@ -152,6 +203,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGraphLineStyleMixin {
supported properties:
- head/tail arrow style
.
\see JKQTPGraphDecoratedHeadLineStyleMixin for a Mix-In for one end (head) only
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPGraphDecoratedLineStyleMixin: public JKQTPGraphLineStyleMixin {
Q_GADGET
@ -181,6 +234,17 @@ public:
/** \copydoc m_tailDecoratorSizeFactor */
double getTailDecoratorSizeFactor() const;
/** \brief calculates the tail decorator size from the line width \a line_width, using m_tailDecoratorSizeFactor and a non-linear scaling function
*
* \see JKQTPLineDecoratorStyleCalcDecoratorSize()
*/
double calcTailDecoratorSize(double line_width) const;
/** \brief calculates the tail decorator size from the line width \a line_width, using m_headDecoratorSizeFactor and a non-linear scaling function
*
* \see JKQTPLineDecoratorStyleCalcDecoratorSize()
*/
double calcHeadDecoratorSize(double line_width) const;
Q_PROPERTY(JKQTPLineDecoratorStyle headDecoratorStyle MEMBER m_headDecoratorStyle READ getHeadDecoratorStyle WRITE setHeadDecoratorStyle)
@ -202,7 +266,6 @@ private:
/*! \brief This Mix-In class provides setter/getter methods, storage and other facilities for the graph symbols style
\ingroup jkqtplotter_basegraphs_stylemixins

BIN
screenshots/geo_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB