JKQTPlotter trunk/v5.0.0
an extensive Qt5+Qt6 Plotter framework (including a feature-richt plotter widget, a speed-optimized, but limited variant and a LaTeX equation renderer!), written fully in C/C++ and without external dependencies
Loading...
Searching...
No Matches
jkqtpdrawingtools.h
1/*
2 Copyright (c) 2008-2024 Jan W. Krieger (<jan@jkrieger.de>)
3
4
5
6 This software is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20
21#ifndef JKQTPDRAWINGTOOLS_H_INCLUDED
22#define JKQTPDRAWINGTOOLS_H_INCLUDED
23#include "jkqtcommon/jkqtcommon_imexport.h"
24#include <QPaintDevice>
25#include <QPainter>
26#include <QPolygonF>
27#include <QPolygon>
28#include <QRectF>
29#include <QRect>
30#include <QLineF>
31#include <QLine>
32#include <array>
33#include <QPainterPath>
34#include <QColor>
35#include <QVector>
36#include <vector>
37#include <forward_list>
38#include <cmath>
39#include <utility>
40#include <QDebug>
41#include <QVector>
42#include <QGuiApplication>
43#include <QDataStream>
44#include <ostream>
45#include "jkqtcommon/jkqtpmathtools.h"
46#include "jkqtcommon/jkqtpconcurrencytools.h"
47#include "jkqtcommon/jkqtpcodestructuring.h"
48
49class JKQTPEnhancedPainter; // forward
50
51
52
53/** \brief functor used to draw a custom JKQTPGraphSymbols
54 * \ingroup jkqtptools_drawing
55 *
56 * Draw the symbol with these properties:
57 * - center at (0,0)
58 * - width 1, i.e. x=-0.5...0.5
59 * - height 1, i.e. y=-0.5...0.5
60 * - you can assume that a proper pen and brush is set with the correct properties
61 * - scaling to the final size is donw by JKQTPPlotSymbol()
62 * - drawing is protected by surronding \c p.save(); and \c p.restore(); in JKQTPPlotSymbol()
63 * .
64 *
65 * As an example, the following code-snippet:
66 * \code
67 * [](QPainter& p) {
68 * p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3);
69 * p.setBrush(Qt::NoBrush);
70 * p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3);
71 * p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3);
72 * };
73 * \endcode
74 * generates this symbol: \image html symbols/symbol_custom.png
75 */
76typedef std::function<void(QPainter& p)> JKQTPCustomGraphSymbolFunctor;
77
78/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter
79 \ingroup jkqtptools_drawing
80 */
82 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color" in a certain context
83 *
84 * \see JKQTPReplaceCurrentColor() , JKQTFillStyleSummmary
85 */
87 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color", but with 10% transparency in a certain context
88 *
89 * \see JKQTPReplaceCurrentColor(), JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
90 */
92 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color", but with 25% transparency in a certain context
93 *
94 * \see JKQTPReplaceCurrentColor(), JKQTPlotterDrawingTools::CurrentColorPlaceholder, ... , JKQTFillStyleSummmary
95 */
97 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color", but with 50% transparency in a certain context
98 *
99 * \see JKQTPReplaceCurrentColor(), JKQTPlotterDrawingTools::CurrentColorPlaceholder, JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
100 */
102 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color", but with 75% transparency in a certain context
103 *
104 * \see JKQTPReplaceCurrentColor(), JKQTPlotterDrawingTools::CurrentColorPlaceholder, JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
105 */
107 /** \brief a special placeholder that can be used to indicate that a color should be replaced by the "current color", but with 90% transparency in a certain context
108 *
109 * \see JKQTPReplaceCurrentColor(), JKQTPlotterDrawingTools::CurrentColorPlaceholder, JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
110 */
112 /** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
113 */
115 /** \brief stores all custom JKQTPGraphSymbols registered using JKQTPRegisterCustomGraphSymbol
116 * \ingroup jkqtptools_drawing
117 * \internal
118 */
122};
123
124
125
126/*! \brief check whether \a col equals JKQTPlotterDrawingTools::CurrentColorPlaceholder (or one of its variants) and then replace it by \a currentColor
127 \ingroup jkqtptools_drawing
128
129 \see JKQTPlotterDrawingTools::CurrentColorPlaceholder, JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
130 */
131JKQTCOMMON_LIB_EXPORT void JKQTPReplaceCurrentColor(QColor& col, const QColor& currentColor);
132/*! \brief check whether any color in \a grad equals JKQTPlotterDrawingTools::CurrentColorPlaceholder (or one of its variants) and then replace it by \a currentColor
133 \ingroup jkqtptools_drawing
134
135 \see JKQTPlotterDrawingTools::CurrentColorPlaceholder, JKQTPlotterDrawingTools::CurrentColorPlaceholder_Trans10, ... , JKQTFillStyleSummmary
136 */
137JKQTCOMMON_LIB_EXPORT void JKQTPReplaceCurrentColor(QGradient& grad, const QColor& currentColor);
138
139
140/** \brief symbols that can be used to plot a datapoint for a graph
141 * \ingroup jkqtptools_drawing
142 */
143enum JKQTPGraphSymbols: uint64_t {
144 JKQTPNoSymbol=0, /*!< \brief plots no symbol at all (usefull together with error bars) */
145 JKQTPDot, /*!< \brief a small dot \image html symbols/symbol_dot.png */
146 JKQTPCross, /*!< \brief a X cross \image html symbols/symbol_cross.png */
147 JKQTPPlus, /*!< \brief a + cross \image html symbols/symbol_plus.png */
148 JKQTPCircle, /*!< \brief an unfilled circle \image html symbols/symbol_circle.png */
149 JKQTPFilledCircle, /*!< \brief a filled circle \image html symbols/symbol_filled_circle.png */
150 JKQTPRect, /*!< \brief an unfilled rectangle \image html symbols/symbol_rect.png */
151 JKQTPFilledRect, /*!< \brief a filled rectangle \image html symbols/symbol_filled_rect.png */
152 JKQTPTriangle, /*!< \brief an unfilled triangle (tip at top) \image html symbols/symbol_triangle.png */
153 JKQTPFilledTriangle, /*!< \brief a filled triangle (tip at top) \image html symbols/symbol_filled_triangle.png */
154 JKQTPDiamond, /*!< \brief an unfilled diamond \image html symbols/symbol_diamond.png */
155 JKQTPFilledDiamond, /*!< \brief a filled diamond \image html symbols/symbol_filled_diamond.png */
156 JKQTPstar, /*!< \brief an unfilled diamond \image html symbols/symbol_star.png */
157 JKQTPFilledStar, /*!< \brief a filled diamond \image html symbols/symbol_filled_star.png */
158 JKQTPPentagon, /*!< \brief an unfilled pentagon \image html symbols/symbol_pentagon.png */
159 JKQTPFilledPentagon, /*!< \brief a filled pentagon \image html symbols/symbol_filled_pentagon.png */
160 JKQTPAsterisc, /*!< \brief an asterisc star with 5 arms \image html symbols/symbol_asterisc.png */
161 JKQTPHourglass, /*!< \brief an hour glass symbol \image html symbols/symbol_hourglass.png */
162 JKQTPFilledHourglass, /*!< \brief a filled hour glass symbol \image html symbols/symbol_filled_hourglass.png */
163 JKQTPCurvedTriangle, /*!< \brief a curved triangle\image html symbols/symbol_curved_triangle.png */
164 JKQTPFilledCurvedTriangle, /*!< \brief a filled curved triangle\image html symbols/symbol_filled_curved_triangle.png */
165 JKQTPHexagon, /*!< \brief an unfilled hexagon \image html symbols/symbol_hexagon.png */
166 JKQTPFilledHexagon, /*!< \brief a filled hexagon \image html symbols/symbol_filled_hexagon.png */
167
168 JKQTPRectCross, /*!< \brief a square symbol with a cross inside \image html symbols/symbol_rect_cross.png */
169 JKQTPRectPlus, /*!< \brief a square symbol with a plus inside \image html symbols/symbol_rect_plus.png */
170 JKQTPRectTriangle, /*!< \brief a square symbol with a triangle inside \image html symbols/symbol_rect_triangle.png */
171 JKQTPRectDownTriangle, /*!< \brief a square symbol with a triangle (tip to the bottom) inside \image html symbols/symbol_rect_downtriangle.png */
172 JKQTPRectLeftTriangle, /*!< \brief a square symbol with a triangle (tip to the left) inside \image html symbols/symbol_rect_lefttriangle.png */
173 JKQTPRectRightTriangle, /*!< \brief a square symbol with a triangle (tip to the right) inside \image html symbols/symbol_rect_righttriangle.png */
174
175 JKQTPCircleCross, /*!< \brief a circle symbol with a cross inside \image html symbols/symbol_circle_cross.png */
176 JKQTPCirclePlus, /*!< \brief a circle symbol with a plus inside \image html symbols/symbol_circle_plus.png */
177 JKQTPCirclePeace, /*!< \brief a circled peace symbol \image html symbols/symbol_circle_peace.png */
178
179 JKQTPDiamondPlus, /*!< \brief a diamond symbol with a plus inside \image html symbols/symbol_diamond_plus.png */
180 JKQTPDiamondCross, /*!< \brief a diamond symbol with a cross inside \image html symbols/symbol_diamond_cross.png */
181
182 JKQTPTripod, /*!< \brief a tripod symbol \image html symbols/symbol_tripod.png */
183 JKQTPDownTripod, /*!< \brief a tripod symbol, pointing down \image html symbols/symbol_down_tripod.png */
184 JKQTPLeftTripod, /*!< \brief a tripod symbol, pointing to the left \image html symbols/symbol_left_tripod.png */
185 JKQTPRightTripod, /*!< \brief a tripod symbol, pointing to the right \image html symbols/symbol_right_tripod.png */
186 JKQTPAsterisc6, /*!< \brief an asterisc star with 6 arms \image html symbols/symbol_asterisc6.png */
187 JKQTPAsterisc8, /*!< \brief an asterisc star with 8 arms \image html symbols/symbol_asterisc8.png */
188 JKQTPPeace, /*!< \brief a peace symbol \image html symbols/symbol_peace.png */
189 JKQTPTarget, /*!< \brief a target symbol (circle with cross) \image html symbols/symbol_target.png */
190
191 JKQTPDownTriangle, /*!< \brief an unfilled triangle (tip at bottom) \image html symbols/symbol_down_triangle.png */
192 JKQTPFilledDownTriangle, /*!< \brief a filled triangle (tip at bottom) \image html symbols/symbol_filled_down_triangle.png */
193 JKQTPLeftTriangle, /*!< \brief an unfilled triangle (tip to the left) \image html symbols/symbol_left_triangle.png */
194 JKQTPFilledLeftTriangle, /*!< \brief a filled triangle (tip to the left) \image html symbols/symbol_filled_left_triangle.png */
195 JKQTPRightTriangle, /*!< \brief an unfilled triangle (tip to the right) \image html symbols/symbol_right_triangle.png */
196 JKQTPFilledRightTriangle, /*!< \brief a filled triangle (tip to the right) \image html symbols/symbol_filled_right_triangle.png */
197 JKQTPDownCurvedTriangle, /*!< \brief a curved triangle, pointing down \image html symbols/symbol_down_curved_triangle.png */
198 JKQTPFilledDownCurvedTriangle, /*!< \brief a filled curved triangle, pointing down \image html symbols/symbol_filled_down_curved_triangle.png */
199 JKQTPLeftCurvedTriangle, /*!< \brief a curved triangle, pointing to the left \image html symbols/symbol_left_curved_triangle.png */
200 JKQTPFilledLeftCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the left \image html symbols/symbol_filled_left_curved_triangle.png */
201 JKQTPRightCurvedTriangle, /*!< \brief a curved triangle, pointing to the right \image html symbols/symbol_right_curved_triangle.png */
202 JKQTPFilledRightCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the right \image html symbols/symbol_filled_right_curved_triangle.png */
203 JKQTPOctagon, /*!< \brief an unfilled octagon \image html symbols/symbol_octagon.png */
204 JKQTPFilledOctagon, /*!< \brief a filled octagon \image html symbols/symbol_filled_octagon.png */
205 JKQTPUpDownTriangle, /*!< \brief a overlay of an up and a down triangle symbol \image html symbols/symbol_updowntriangle.png */
206 JKQTPFilledUpDownTriangle, /*!< \brief a filled version of the overlay of an up and a down triangle \image html symbols/symbol_filled_updowntriangle.png */
207 JKQTPHorizontalHourglass, /*!< \brief a horizontal hour glass symbol \image html symbols/symbol_horizontal_hourglass.png */
208 JKQTPFilledHorizontalHourglass, /*!< \brief a filled horizontal hour glass symbol \image html symbols/symbol_filled_horizontal_hourglass.png */
209
210 JKQTPSantaClauseHouse, /*!< \brief a small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_santaclause.png */
211 JKQTPFilledSantaClauseHouse, /*!< \brief a filled small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_filled_santaclause.png */
212
213 JKQTPMale, /*!< \brief a male symbol \image html symbols/symbol_male.png */
214 JKQTPFemale, /*!< \brief a female symbol \image html symbols/symbol_female.png */
215
216 JKQTPSymbolCount, /*!< \brief can be used to iterate over all symbols using: <code>for (int i=0; i<static_cast<int>(JKQTPSymbolCount); i++) { JKQTPGraphSymbols s=static_cast<JKQTPGraphSymbols>(i); ... }</code> */
217 JKQTPMaxSymbolID=JKQTPSymbolCount-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++) { JKQTPGraphSymbols s=static_cast<JKQTPGraphSymbols>(i); ... }</code> */
218 JKQTPDefaultSymbol=JKQTPCross, /*!< \brief a default symbol used for plotting */
219
220 JKQTPCharacterSymbol=0x100, /*!< \brief draw a font-character as symbol with defined fill-brush (taken from symbol-color), you can use any character from a QFont by supplying \c JKQTPCharacterSymbol+QChar('').unicode() as JKQTPGraphSymbols
221 \image html symbols/symbol_char_at.png "generated by JKQTPCharacterSymbol+QChar('@').unicode()"
222 \image html symbols/symbol_char_club.png "generated by JKQTPCharacterSymbol+QChar(0x2663).unicode()" */
223 JKQTPFilledCharacterSymbol=JKQTPCharacterSymbol+0xFFFF+0xF, /*!< \brief draw a font-character as symbol with defined outline-pen and fill-brush, you can use any character from a QFont by supplying \c JKQTPFilledCharacterSymbol+QChar('').unicode() as JKQTPGraphSymbols
224 \image html symbols/symbol_filled_char_at.png "generated by JKQTPFilledCharacterSymbol+QChar('@').unicode()"
225 \image html symbols/symbol_filled_char_club.png "generated by JKQTPFilledCharacterSymbol+QChar(0x2663).unicode()"
226 */
227 JKQTPFirstCustomSymbol=JKQTPFilledCharacterSymbol+0xFFFF+0xF, /*!< \brief draw a completely custom symbol, defined by supplying a functor to JKQTPRegisterCustomGraphSymbol()
228 \image html symbols/symbol_custom.png "generated by <code>[](QPainter& p) { p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3); p.setBrush(Qt::NoBrush); p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3); p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3); };</code>" */
229};
230
231inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint8_t b) {
232 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
233}
234
235inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint16_t b) {
236 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
237}
238
239inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint32_t b) {
240 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
241}
242
243inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint64_t b) {
244 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
245}
246
247inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int8_t b) {
248 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
249}
250
251inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int16_t b) {
252 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
253}
254
255inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int32_t b) {
256 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
257}
258
259inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int64_t b) {
260 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
261}
262
263inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, const QChar& b) {
264 return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+static_cast<uint64_t>(b.unicode()));
265}
266
267
268/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!, <b>thread-safe</b>
269 * \ingroup jkqtptools_drawing
270 *
271 * The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program
272 *
273 * \see JKQTPCustomGraphSymbolFunctor for an example
274 */
276
277/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!, <b>thread-safe</b>
278 * \ingroup jkqtptools_drawing
279 *
280 * The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program
281 *
282 * \see JKQTPCustomGraphSymbolFunctor for an example
283 */
285
286
287/** \brief converts a JKQTPGraphSymbols variable into a identifier string
288 * \ingroup jkqtptools_drawing
289 */
291/** \brief converts a JKQTPGraphSymbols variable into a human-readable string
292 * \ingroup jkqtptools_drawing
293 */
295
296/** \brief converts a String into a JKQTPGraphSymbols
297 * \ingroup jkqtptools_drawing
298 */
300
301
302inline QDataStream& operator<<(QDataStream& str, JKQTPGraphSymbols s) {
303 str<<static_cast<quint64>(s);
304 return str;
305}
306
307
308inline QDataStream& operator>>(QDataStream& str, JKQTPGraphSymbols& s) {
309 str<<reinterpret_cast<quint64&>(s);
310 return str;
311}
312
313/*! \brief plot the specified symbol at pixel position x,y, <b>thread-safe</b>
314 \ingroup jkqtptools_drawing
315
316 \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
317 \param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
318 \param x x-coordinate of the symbol center
319 \param y y-coordinate of the symbol center
320 \param symbol type of the symbol to plot, see JKQTPGraphSymbols
321 \param size size (width/height) of the symbol around (\a x , \a y)
322 \param symbolLineWidth width of the lines used to draw the symbol
323 \param color color of the symbol lines
324 \param fillColor color of the symbol filling
325 \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
326
327 */
328template <class TPainter>
329inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont);
330
331/*! \brief plot the specified symbol at pixel position x,y, <b>thread-safe</b>
332 \ingroup jkqtptools_drawing
333
334 \param paintDevice the paint device to draw on
335 \param x x-coordinate of the symbol center
336 \param y y-coordinate of the symbol center
337 \param symbol type of the symbol to plot, see JKQTPGraphSymbols
338 \param size size (width/height) of the symbol around (\a x , \a y)
339 \param symbolLineWidth width of the lines used to draw the symbol
340 \param color color of the symbol lines
341 \param fillColor color of the symbol filling
342 \param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
343
344 */
345JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, const QFont &symbolFont);
346
347
348
349
350
351/** \brief symbols that can be used to plot a datapoint for a graph
352 * \ingroup jkqtptools_drawing
353 *
354 * \image html geo_arrow_tips.png
355 *
356 * Note that all arrows end at the designated line-end (here indicated by dashed grey lines), even circles and rectangle:
357 *
358 * \image html geo_arrow_tipsatlineend.png
359 *
360 *
361 * \see JKQTPPlotLineDecorator(), JKQTPPlotDecoratedLine(), JKQTPLineDecoratorStyle, JKQTPLineDecoratorStyleCalcDecoratorSize()
362 *
363 * \see \ref JKQTPlotterGeometricArrows and \ref JKQTPlotterGeometricGraphs for usage examples.
364 */
366 JKQTPNoDecorator=0, /*!< \brief no decorator, i.e. a simple line-end \image html linedecorators/none.png */
367 JKQTPArrow, /*!< \brief a simple arrow tip, unfilled \image html linedecorators/arrow.png */
368 JKQTPFilledArrow, /*!< \brief a nice filled arrow tip \image html linedecorators/filled_arrow.png */
369 JKQTPTriangleDecorator, /*!< \brief a triangular arrow tip \image html linedecorators/triangle.png */
370 JKQTPFilledTriangleDecorator, /*!< \brief a triangular filled arrow tip \image html linedecorators/filled_triangle.png */
371 JKQTPTriangleDecoratorAndBar, /*!< \brief a triangular arrow tip, with vertical bar \image html linedecorators/triangle_bar.png */
372 JKQTPFilledTriangleDecoratorAndBar, /*!< \brief a triangular filled arrow tip, with vertical bar \image html linedecorators/filled_triangle_bar.png */
373 JKQTPDoubleArrow, /*!< \brief a nice double-arrow tip \image html linedecorators/double_arrow.png*/
374 JKQTPFilledDoubleArrow, /*!< \brief a nice filled double-arrow tip \image html linedecorators/filled_double_arrow.png */
375 JKQTPCircleDecorator, /*!< \brief an open circle tip \image html linedecorators/circle.png */
376 JKQTPFilledCircleDecorator, /*!< \brief a filled circle tip \image html linedecorators/filled_circle.png */
377 JKQTPRectangleDecorator, /*!< \brief an open rectangle tip \image html linedecorators/rectangle.png */
378 JKQTPFilledRectangleDecorator, /*!< \brief a filled rectangle tip \image html linedecorators/filled_rectangle.png */
379 JKQTPArrowAndBar, /*!< \brief a simple arrow tip, unfilled, with vertical bar \image html linedecorators/arrow_bar.png */
380 JKQTPDoubleArrowAndBar, /*!< \brief a simple double-arrow tip, unfilled, with vertical bar \image html linedecorators/double_arrow_bar.png */
381 JKQTPBarDecorator, /*!< \brief a full vertical bar \image html linedecorators/bar.png */
382 JKQTPBracketDecorator, /*!< \brief a vertical bracket decorator \image html linedecorators/bracket.png */
383 JKQTPDiamondDecorator, /*!< \brief an open diamond tip \image html linedecorators/diamond.png */
384 JKQTPDiamondDecoratorAndBar, /*!< \brief an open diamond tip \image html linedecorators/diamond_bar.png */
385 JKQTPFilledDiamondDecorator, /*!< \brief a filled diamond tip \image html linedecorators/filled_diamond.png */
386 JKQTPFilledDiamondDecoratorAndBar, /*!< \brief a filled diamond tip \image html linedecorators/filled_diamond_bar.png */
387 JKQTPHalfBarDecorator, /*!< \brief a half vertical bar \image html linedecorators/half_bar.png */
388 JKQTPHarpoonDecorator, /*!< \brief an harpoon arrow \image html linedecorators/harpoon.png */
389 JKQTPHarpoonDecoratorAndBar, /*!< \brief an harpoon arrow, with vertical bar \image html linedecorators/harpoon_bar.png */
390 JKQTPSkewedBarDecorator, /*!< \brief a skewed vertical bar \image html linedecorators/skewed_bar.png */
391
392 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> */
393 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> */
394 JKQTPDefaultLineDecorator=JKQTPFilledArrow /*!< \brief a default symbol used for plotting */
396
397/** \brief converts a JKQTPLineDecoratorStyle variable into a identifier string
398 * \ingroup jkqtptools_drawing
399 */
401/** \brief converts a JKQTPLineDecoratorStyle variable into a human-readable string
402 * \ingroup jkqtptools_drawing
403 */
405
406/** \brief converts a String into a JKQTPLineDecoratorStyle
407 * \ingroup jkqtptools_drawing
408 */
410
411/*! \brief plot the specified symbol at pixel position x,y. Note that this function only draws the decorator, NOT the line pointing to it!
412 \ingroup jkqtptools_drawing
413
414 \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
415 \param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
416 \param x x-coordinate of the decorator tip
417 \param y y-coordinate of the decorator tip
418 \param angle_rad angle of the line pointing to (x,y), given in radians, 0rad points to the right, >0rad is a counter-clockwise rotation, as calculated by atan2() from dx, dy of a line!
419 \param style type of the decorator to plot, see JKQTPLineDecoratorStyle
420 \param size size of the decorator in pixels, the decorator fills at most the space \c x...x+size and \c y-size/2...y-size/2, but may be smaller (e.g. arrows are typically less high than the full \a size pixels ).
421 \param[out] line_start optional output parameter: when drawing the line let it end here, not necessarily at (x,y)
422
423 \see JKQTPPlotLineDecorator(), JKQTPPlotDecoratedLine(), JKQTPLineDecoratorStyle, JKQTPLineDecoratorStyleCalcDecoratorSize()
424 */
425template <class TPainter>
426inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double angle_rad, JKQTPLineDecoratorStyle style, double size, QPointF* line_start=nullptr);
427
428/*! \brief plot a line with the given decorators \a style1 and a style2 at the start- and end-point repsectively, using the painter's current pen
429 \ingroup jkqtptools_drawing
430
431 \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
432 \param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
433 \param l line to draw
434 \param style1 type of the first decorator to plot, see JKQTPLineDecoratorStyle
435 \param size1 size of the first decorator
436 \param style2 type of the second decorator to plot, see JKQTPLineDecoratorStyle
437 \param size2 size of the second decorator
438
439 \note a decorator fills at most the space \c x...x+size and \c y-size/2...y-size/2 (where \c size is \a size1 or \a size2), but may be smaller (e.g. arrows are typically less high than the full \c size pixels ).
440
441 \see JKQTPPlotLineDecorator(), JKQTPPlotDecoratedLine(), JKQTPLineDecoratorStyle, JKQTPLineDecoratorStyleCalcDecoratorSize()
442 */
443template <class TPainter>
444inline void JKQTPPlotDecoratedLine(TPainter& painter, const QLineF& l, JKQTPLineDecoratorStyle style1, double size1, JKQTPLineDecoratorStyle style2, double size2);
445
446/*! \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
447 \ingroup jkqtptools_drawing
448
449 \see JKQTPPlotLineDecorator(), JKQTPPlotDecoratedLine(), JKQTPLineDecoratorStyle, JKQTPLineDecoratorStyleCalcDecoratorSize()
450*/
451JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor);
452
453
454
455
456/*! \brief clips the given line (\a x1 , \a y1 ) -- (\a x2 , \a y2 ) to the given rectangle \a xmin .. \a xmax and \a ymin ... \a ymax
457 \ingroup jkqtptools_drawing
458
459 \return the clipped line in \a x1 , \a y1 , \a x2 , \a y2 and \c true if the line is still to be drawn or \c false else
460
461 This function implements the algorithm descripbed in https://www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
462 i.e. in Pseudocode
463 \verbatim
464 // x1 , y1 , x2 , y2 , xmin , ymax , xmax , ymin //
465 if not ( x1<xmin and x2<xmin ) and not ( x1>xmax and x2>xmax ) then
466 if not ( y1<ymin and y2<ymin ) and not ( y1>ymax and y2>ymax ) then
467 x[1]= x1
468 y[1]= y1
469 x[2]= x2
470 y[2]= y2
471 i =1
472 repeat
473 if x[i] < xmin then
474 x[i] = xmin
475 y[i] = ( ( y2-y1 ) / ( x2-x1 ) ) * ( xmin-x1)+y1
476 elseif x[i] > xmax then
477 x[i] = xmax
478 y[i] = ( ( y2-y1 ) / ( x2-x1 ) ) * ( xmax-x1)+y1
479 endif
480 if y[i] < ymin then
481 y[i] = ymin
482 x[i] = ( ( x2-x1 ) / ( y2-y1 ) ) * ( ymin-y1)+x1
483 elseif y[i] > ymax then
484 y[i] = ymax
485 x[i] = ( ( x2-x1 ) / ( y2-y1 ) ) * ( ymax-y1)+x1
486 endif
487 i = i + 1
488 until i >2
489 if not ( x [1 ] < xmin and x [2 ] < xmin ) and not ( x [1 ] >xmax and x [2 ] >xmax ) then
490 drawLine ( x[1] , y[1] , x[2] , y[2] )
491 endif
492 endif
493 endif
494 \endverbatim
495*/
496inline bool JKQTPClipLine(double& x1 , double& y1 , double& x2 , double& y2 , double xmin , double xmax , double ymin, double ymax) {
497 if (! ( x1<xmin && x2<xmin ) && !( x1>xmax && x2>xmax )) {
498 if ( !( y1<ymin && y2<ymin ) && !( y1>ymax && y2>ymax ) ) {
499 double x[2]= {x1,x2};
500 double y[2]= {y1,y2};
501 for (int i=0; i<2; i++) {
502 if (x[i] < xmin) {
503 x[i] = xmin;
504 y[i] = ( ( y2-y1 ) / ( x2-x1 ) ) * ( xmin-x1)+y1;
505 } else if (x[i] > xmax) {
506 x[i] = xmax;
507 y[i] = ( ( y2-y1 ) / ( x2-x1 ) ) * ( xmax-x1)+y1;
508 }
509 if (y[i] < ymin) {
510 y[i] = ymin;
511 x[i] = ( ( x2-x1 ) / ( y2-y1 ) ) * ( ymin-y1)+x1;
512 } else if (y[i] > ymax) {
513 y[i] = ymax;
514 x[i] = ( ( x2-x1 ) / ( y2-y1 ) ) * ( ymax-y1)+x1;
515 }
516 }
517 if (! ( x[0] < xmin && x[1]< xmin ) && !( x[0] >xmax && x[1] >xmax )) {
518 x1=x[0];
519 y1=y[0];
520 x2=x[1];
521 y2=y[1];
522 return true;
523 }
524 }
525 }
526 return false;
527}
528
529/*! \brief clips the given line \a line to the given rectangle rectangle \a xmin .. \a xmax and \a ymin ... \a ymax
530 \ingroup jkqtptools_drawing
531
532 \return the clipped line or a line with 0-length, i.e. QLineF()
533
534 This function implements the algorithm descripbed in https://www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
535
536*/
537inline QLineF JKQTPClipLine(const QLineF& line, double xmin , double xmax , double ymin, double ymax) {
538 double x1=line.x1();
539 double y1=line.y1();
540 double x2=line.x2();
541 double y2=line.y2();
542 if (JKQTPClipLine(x1,y1,x2,y2,xmin,xmax,ymin,ymax)) {
543 return QLineF(x1,y1,x2,y2);
544 } else {
545 return QLineF();
546 }
547}
548
549/*! \brief clips the given line \a line to the given rectangle \a clipRect
550 \ingroup jkqtptools_drawing
551
552 \param line line to be clipped
553 \param clipRect rectangle to clip to
554 \return the clipped line or a line with 0-length, i.e. QLineF()
555
556 This function implements the algorithm descripbed in https://www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
557
558*/
559inline QLineF JKQTPClipLine(const QLineF& line, const QRectF& clipRect) {
560 const double xmin=qMin(clipRect.left(), clipRect.right());
561 const double xmax=qMax(clipRect.left(), clipRect.right());
562 const double ymin=qMin(clipRect.top(), clipRect.bottom());
563 const double ymax=qMax(clipRect.top(), clipRect.bottom());
564
565 double x1=line.x1();
566 double y1=line.y1();
567 double x2=line.x2();
568 double y2=line.y2();
569 if (JKQTPClipLine(x1,y1,x2,y2,xmin,xmax,ymin,ymax)) {
570 return QLineF(x1,y1,x2,y2);
571 } else {
572 return QLineF();
573 }
574}
575
576/*! \brief clips the given list of poly-lines \a polylines_in to the given rectangle \a clipRect
577 \ingroup jkqtptools_drawing
578
579 \param polylines_in list of poly-lines to be clipped
580 \param clipRect rectangle to clip to
581 \return a list of poly-lines representing the clipped lines. Note that some lines may be split further so the number of poly-lines in the output may actually be larger than the number of polylines in the input!
582*/
583JKQTCOMMON_LIB_EXPORT QList<QPolygonF> JKQTPClipPolyLines(const QList<QPolygonF> & polylines_in, const QRectF& clipRect);
584/*! \brief clips the given poly-line \a polyline_in to the given rectangle \a clipRect
585 \ingroup jkqtptools_drawing
586
587 \param polyline_in poly-line to be clipped
588 \param clipRect rectangle to clip to
589 \return a list of poly-lines representing the clipped line.
590*/
591JKQTCOMMON_LIB_EXPORT QList<QPolygonF> JKQTPClipPolyLine(const QPolygonF & polyline_in, const QRectF& clipRect);
592
593/*! \brief tries to reduce the complexity of the given list of poly-lines \a lines_in, but keeping the appearance as if all lines were drawn
594 \ingroup jkqtptools_drawing
595
596 \param lines_in list of poly-lines to be simplified
597 \param maxDeltaXY a group has to be either less wide or less high than this, typically equals the linewidth of the poly-line
598 \return a simplified version of lines_in
599*/
600JKQTCOMMON_LIB_EXPORT QList<QPolygonF> JKQTPSimplifyPolyLines(const QList<QPolygonF>& lines_in, double maxDeltaXY=1.0);
601
602/*! \brief tries to reduce the complexity of the given poly-line \a lines_in, but keeping the appearance as if all lines were drawn
603 \ingroup jkqtptools_drawing
604
605 \param lines_in poly-line to be simplified
606 \param maxDeltaXY a group has to be either less wide or less high than this, typically equals the linewidth of the poly-line
607 \return a simplified version of lines_in
608*/
609JKQTCOMMON_LIB_EXPORT QPolygonF JKQTPSimplifyPolyLines(const QPolygonF& lines_in, double maxDeltaXY=1.0);
610
611/*! \brief draw a tooltip, using the current brush and pen of the provided painter
612 \ingroup jkqtptools_drawing
613
614 \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
615 \param painter QPainter-like object to use for painting
616 \param x x-coordinate of position the tooltip points to
617 \param y y-coordinate of position the tooltip points to
618 \param rect rectangle of the main tooltip area
619
620 \image html tooltiptool_example.png
621*/
622template <class TPainter>
623inline void JKQTPDrawTooltip(TPainter& painter, double x, double y, const QRectF& rect);
624
625
626
627
628
629/*! \brief return the consecutive ccordinates of the tips of a N-tipped star on a circle of radius 1.
630 Inner tips are on a irle of radius \a inner_radius.
631 \ingroup jkqtptools_drawing
632 */
633template <int N>
634inline std::array<QPointF, N*2> JKQTPGetStarCoordinates(double inner_radius=0.5) {
635 std::array<QPointF, N*2> star_coords;
636 const double angle=360.0/double(N)/180.0*JKQTPSTATISTICS_PI;
637 for (int i=0; i<N; i++) {
638 const double a=(static_cast<double>(i)+0.5)*angle;
639 star_coords[i*2]=QPointF(sin(a),cos(a));
640 star_coords[i*2+1]=QPointF(inner_radius*sin(a+angle/2.0),inner_radius*cos(a+angle/2.0));
641 }
642 return star_coords;
643}
644
645/** \brief internal datastructure used in JKQTPPlotSymbol() to precalculate certain data only once per runtime
646 * \ingroup jkqtptools_drawing
647 * \internal
648*/
651 QPainterPath paths;
652 QPainterPath filledpaths;
653 QVector<QLineF> lines;
654 QPolygonF polygons;
655 QPolygonF filledpolygons;
657};
658
659
660template <class TPainter>
661inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double symbolSize, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont) {
662 if (symbol==JKQTPNoSymbol) return;
663 painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
664 QPen p=painter.pen();
665 p.setColor(color);
666 p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, symbolLineWidth));
667 p.setStyle(Qt::SolidLine);
668 p.setCapStyle(Qt::FlatCap);
669 QPen pDescaled=p;
670 pDescaled.setWidthF(pDescaled.widthF()/symbolSize);
671 QFont fDescaled=symbolFont;
672 fDescaled.setPointSizeF(fDescaled.pointSizeF()/symbolSize);
673 const QBrush b=QBrush(fillColor, Qt::SolidPattern);
674
675
676 static std::vector<JKQTPSymbolPathsInternnal> all_paths = []() {
677 // this functor is called the the static variable symbolData is initialized, but only once per runtimme (guaranteed by C++)
678 std::vector<JKQTPSymbolPathsInternnal> paths;
679 paths.resize(JKQTPSymbolCount);
680
681 // calculate star cordinates as static values
682 const double s45=fabs(cos(45.0/180.0*JKQTPSTATISTICS_PI));
683 const auto star5cords=JKQTPGetStarCoordinates<5>(0.5);
684 const auto star6cords=JKQTPGetStarCoordinates<6>(0.5);
685 const auto star8cords=JKQTPGetStarCoordinates<8>(0.5);
686
687 paths[JKQTPCross].paths.moveTo(-0.5,-0.5);
688 paths[JKQTPCross].paths.lineTo(0.5,0.5);
689 paths[JKQTPCross].paths.moveTo(-0.5,+0.5);
690 paths[JKQTPCross].paths.lineTo(+0.5,-0.5);
691 paths[JKQTPPlus].paths.moveTo(-0.5,0);
692 paths[JKQTPPlus].paths.lineTo(0.5,0);
693 paths[JKQTPPlus].paths.moveTo(0,+0.5);
694 paths[JKQTPPlus].paths.lineTo(0,-0.5);
695 paths[JKQTPCircle].paths.addEllipse(QPointF(0,0), 0.5, 0.5);
696 paths[JKQTPFilledCircle].filledpaths=paths[JKQTPCircle].paths;
697 paths[JKQTPCircleCross].paths.addEllipse(QPointF(0,0), 0.5, 0.5);
698 paths[JKQTPCircleCross].paths.moveTo(-0.5*s45,-0.5*s45);
699 paths[JKQTPCircleCross].paths.lineTo(0.5*s45,0.5*s45);
700 paths[JKQTPCircleCross].paths.moveTo(-0.5*s45,+0.5*s45);
701 paths[JKQTPCircleCross].paths.lineTo(+0.5*s45,-0.5*s45);
702 paths[JKQTPCirclePlus].paths.addEllipse(QPointF(0,0), 0.5, 0.5);
703 paths[JKQTPCirclePlus].paths.moveTo(-0.5,0);
704 paths[JKQTPCirclePlus].paths.lineTo(0.5,0);
705 paths[JKQTPCirclePlus].paths.moveTo(0,+0.5);
706 paths[JKQTPCirclePlus].paths.lineTo(0,-0.5);
707 paths[JKQTPCirclePeace].paths.addEllipse(QPointF(0,0), 0.5, 0.5);
708 paths[JKQTPCirclePeace].paths.moveTo(0,-0.5);
709 paths[JKQTPCirclePeace].paths.lineTo(0, 0.5);
710 paths[JKQTPCirclePeace].paths.moveTo(0,0);
711 paths[JKQTPCirclePeace].paths.lineTo(0.5*s45,0.5*s45);
712 paths[JKQTPCirclePeace].paths.moveTo(0,0);
713 paths[JKQTPCirclePeace].paths.lineTo(-0.5*s45,0.5*s45);
714 paths[JKQTPPeace].paths.moveTo(0,-0.5);
715 paths[JKQTPPeace].paths.lineTo(0, 0.5);
716 paths[JKQTPPeace].paths.moveTo(0,0);
717 paths[JKQTPPeace].paths.lineTo(0.5*s45,0.5*s45);
718 paths[JKQTPPeace].paths.moveTo(0,0);
719 paths[JKQTPPeace].paths.lineTo(-0.5*s45,0.5*s45);
720 paths[JKQTPTarget].paths.addEllipse(QPointF(0,0), 0.33333, 0.33333);
721 paths[JKQTPTarget].paths.moveTo(QPointF(0,-0.5));
722 paths[JKQTPTarget].paths.lineTo(QPointF(0,0.5));
723 paths[JKQTPTarget].paths.moveTo(QPointF(-0.5,0));
724 paths[JKQTPTarget].paths.lineTo(QPointF(0.5,0));
725 paths[JKQTPFemale].paths.addEllipse(-0.25,-0.5,0.5,0.5);
726 paths[JKQTPFemale].paths.moveTo(0,0);
727 paths[JKQTPFemale].paths.lineTo(0,0.5);
728 paths[JKQTPFemale].paths.moveTo(-0.5/3.0,0.5/2.0);
729 paths[JKQTPFemale].paths.lineTo(0.5/3.0,0.5/2.0);
730 paths[JKQTPMale].paths.addEllipse(QRectF(-0.5/2.0, -0.5/2.0, 0.5, 0.5));
731 paths[JKQTPMale].paths.moveTo(QPointF(+0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI),-0.5/2.0*cos(45.0/180.0*JKQTPSTATISTICS_PI)));
732 paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5));
733 paths[JKQTPMale].paths.moveTo(QPointF(+0.5-0.5/2.0,-0.5));
734 paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5));
735 paths[JKQTPMale].paths.lineTo(QPointF(+0.5,-0.5+0.5/2.0));
736 paths[JKQTPRect].paths.addRect(-0.5,-0.5, 1,1);
737 paths[JKQTPFilledRect].filledpaths=paths[JKQTPRect].paths;
738 paths[JKQTPRectCross].paths.addRect(-0.5,-0.5, 1,1);
739 paths[JKQTPRectCross].paths.moveTo(-0.5,-0.5);
740 paths[JKQTPRectCross].paths.lineTo(0.5,0.5);
741 paths[JKQTPRectCross].paths.moveTo(-0.5,+0.5);
742 paths[JKQTPRectCross].paths.lineTo(+0.5,-0.5);
743 paths[JKQTPRectPlus].paths.addRect(-0.5,-0.5, 1,1);
744 paths[JKQTPRectPlus].paths.moveTo(-0.5,0);
745 paths[JKQTPRectPlus].paths.lineTo(0.5,0);
746 paths[JKQTPRectPlus].paths.moveTo(0,+0.5);
747 paths[JKQTPRectPlus].paths.lineTo(0,-0.5);
748 paths[JKQTPCurvedTriangle].paths.moveTo(0,0-0.5);
749 paths[JKQTPCurvedTriangle].paths.quadTo(0-1.0/10.0,0+1.0/4.0, 0-0.5,0+0.5);
750 paths[JKQTPCurvedTriangle].paths.quadTo(0,0+1.0/4.0, 0+0.5,0+0.5);
751 paths[JKQTPCurvedTriangle].paths.quadTo(0+1.0/10.0,0+1.0/4.0, 0,0-0.5);
752 paths[JKQTPFilledCurvedTriangle].filledpaths=paths[JKQTPCurvedTriangle].paths;
753
754 paths[JKQTPDownCurvedTriangle].paths=paths[JKQTPCurvedTriangle].paths;
755 paths[JKQTPDownCurvedTriangle].pathsrotation=180.0;
756 paths[JKQTPFilledDownCurvedTriangle].filledpaths=paths[JKQTPDownCurvedTriangle].paths;
757 paths[JKQTPFilledDownCurvedTriangle].pathsrotation=180.0;
758
759 paths[JKQTPLeftCurvedTriangle].paths=paths[JKQTPCurvedTriangle].paths;
760 paths[JKQTPLeftCurvedTriangle].pathsrotation=-90.0;
761 paths[JKQTPFilledLeftCurvedTriangle].filledpaths=paths[JKQTPLeftCurvedTriangle].paths;
762 paths[JKQTPFilledLeftCurvedTriangle].pathsrotation=-90.0;
763
764 paths[JKQTPRightCurvedTriangle].paths=paths[JKQTPCurvedTriangle].paths;
765 paths[JKQTPRightCurvedTriangle].pathsrotation=90.0;
766 paths[JKQTPFilledRightCurvedTriangle].filledpaths=paths[JKQTPRightCurvedTriangle].paths;
767 paths[JKQTPFilledRightCurvedTriangle].pathsrotation=90.0;
768
769 {
770 QPolygonF poly;
771 poly<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0+0.5, 0.0)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0-0.5, 0.0);
772 poly<<poly[0];
773 paths[JKQTPDiamondPlus].paths.addPolygon(poly);
774 paths[JKQTPDiamondPlus].paths.moveTo(poly[0]);
775 paths[JKQTPDiamondPlus].paths.lineTo(poly[2]);
776 paths[JKQTPDiamondPlus].paths.moveTo(poly[1]);
777 paths[JKQTPDiamondPlus].paths.lineTo(poly[3]);
778 }
779 {
780 QPolygonF poly;
781 poly<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0+0.5, 0.0)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0-0.5, 0.0);
782 poly<<poly[0];
783 paths[JKQTPDiamondCross].paths.addPolygon(poly);
784 paths[JKQTPDiamondCross].paths.moveTo((poly[0]+poly[1])/2.0);
785 paths[JKQTPDiamondCross].paths.lineTo((poly[2]+poly[3])/2.0);
786 paths[JKQTPDiamondCross].paths.moveTo((poly[1]+poly[2])/2.0);
787 paths[JKQTPDiamondCross].paths.lineTo((poly[3]+poly[0])/2.0);
788 }
789
790
791 for (size_t i=0; i<star8cords.size(); i+=2) {
792 paths[JKQTPAsterisc8].paths.moveTo(star8cords[i].x()*0.5, star8cords[i].y()*0.5);
793 paths[JKQTPAsterisc8].paths.lineTo(0,0);
794 }
795 for (size_t i=0; i<star6cords.size(); i+=2) {
796 paths[JKQTPAsterisc6].paths.moveTo(star6cords[i].x()*0.5, star6cords[i].y()*0.5);
797 paths[JKQTPAsterisc6].paths.lineTo(0,0);
798 }
799 for (size_t i=0; i<star5cords.size(); i+=2) {
800 paths[JKQTPAsterisc].paths.moveTo(star5cords[i].x()*0.5, star5cords[i].y()*0.5);
801 paths[JKQTPAsterisc].paths.lineTo(0,0);
802 }
803
804 paths[JKQTPRectTriangle].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0+0.5);
805 paths[JKQTPRectDownTriangle].polygons<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-0.5);
806 paths[JKQTPRectLeftTriangle].polygons<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0+0.5);
807 paths[JKQTPRectRightTriangle].polygons<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0)<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0+0.5);
808 paths[JKQTPTriangle].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0, 0.0-0.5);
809 paths[JKQTPFilledTriangle].filledpolygons=paths[JKQTPTriangle].polygons;
810 paths[JKQTPDownTriangle].polygons<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0, 0.0+0.5);
811 paths[JKQTPFilledDownTriangle].filledpolygons=paths[JKQTPDownTriangle].polygons;
812 paths[JKQTPLeftTriangle].polygons<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0)<<QPointF(0.0+0.5, 0.0-0.5);
813 paths[JKQTPFilledLeftTriangle].filledpolygons=paths[JKQTPLeftTriangle].polygons;
814 paths[JKQTPRightTriangle].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0)<<QPointF(0.0-0.5, 0.0-0.5);
815 paths[JKQTPFilledRightTriangle].filledpolygons=paths[JKQTPRightTriangle].polygons;
816 for (size_t i=0; i<star5cords.size(); i++) {
817 paths[JKQTPstar].polygons<<QPointF(0.0+star5cords[i].x()*0.5, 0.0+star5cords[i].y()*0.5);
818 paths[JKQTPFilledStar].filledpolygons<<QPointF(0.0+star5cords[i].x()*0.5, 0.0+star5cords[i].y()*0.5);
819 if (i%2==0) {
820 paths[JKQTPPentagon].polygons<<QPointF(0.0+star5cords[i].x()*0.5, 0.0+star5cords[i].y()*0.5);
821 paths[JKQTPFilledPentagon].filledpolygons<<QPointF(0.0+star5cords[i].x()*0.5, 0.0+star5cords[i].y()*0.5);
822 }
823 }
824 for (size_t i=0; i<star6cords.size(); i+=2) {
825 paths[JKQTPHexagon].polygons<<QPointF(0.0+star6cords[i].x()*0.5, 0.0+star6cords[i].y()*0.5);
826 paths[JKQTPFilledHexagon].filledpolygons<<QPointF(0.0+star6cords[i].x()*0.5, 0.0+star6cords[i].y()*0.5);
827 }
828 for (size_t i=0; i<star8cords.size(); i+=2) {
829 paths[JKQTPOctagon].polygons<<QPointF(0.0+star8cords[i].x()*0.5, 0.0+star8cords[i].y()*0.5);
830 paths[JKQTPFilledOctagon].filledpolygons<<QPointF(0.0+star8cords[i].x()*0.5, 0.0+star8cords[i].y()*0.5);
831 }
832 paths[JKQTPDiamond].polygons<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0+0.5, 0.0)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0-0.5, 0.0);
833 paths[JKQTPFilledDiamond].filledpolygons=paths[JKQTPDiamond].polygons;
834 paths[JKQTPHourglass].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0-0.5);
835 paths[JKQTPFilledHourglass].filledpolygons=paths[JKQTPHourglass].polygons;
836 paths[JKQTPHorizontalHourglass].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-0.5);
837 paths[JKQTPFilledHorizontalHourglass].filledpolygons=paths[JKQTPHorizontalHourglass].polygons;
838 paths[JKQTPSantaClauseHouse].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-1.0/6.0)<<QPointF(0.0-0.5, 0.0-1.0/6.0)<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0+0.5, 0.0-1.0/6.0)<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0-0.5, 0.0-1.0/6.0)<<QPointF(0.0+0.5, 0.0+0.5);
839 paths[JKQTPFilledSantaClauseHouse].filledpolygons=paths[JKQTPSantaClauseHouse].polygons;
840 paths[JKQTPUpDownTriangle].polygons<<QPointF(0.0-0.5, 0.0+0.5)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0+0.5, 0.0-0.5)<<QPointF(0.0-0.5, 0.0-0.5)<<QPointF(0.0, 0.0+0.5)<<QPointF(0.0+0.5, 0.0+0.5)<<QPointF(0.0, 0.0-0.5)<<QPointF(0.0-0.5, 0.0+0.5);
841 paths[JKQTPFilledUpDownTriangle].filledpolygons=paths[JKQTPUpDownTriangle].polygons;
842
843
844 paths[JKQTPTripod].lines<<QLineF(0.0, 0.0-0.5, 0.0, 0.0)
845 <<QLineF(0.0, 0.0, 0.0-s45, 0.0+s45)
846 <<QLineF(0.0, 0.0, 0.0+s45, 0.0+s45);
847
848 paths[JKQTPDownTripod].lines<<QLineF(0.0, 0.0+0.5, 0.0, 0.0)
849 <<QLineF(0.0, 0.0, 0.0-s45, 0.0-s45)
850 <<QLineF(0.0, 0.0, 0.0+s45, 0.0-s45);
851
852 paths[JKQTPLeftTripod].lines<<QLineF(0.0-0.5, 0.0, 0.0, 0.0)
853 <<QLineF(0.0, 0.0, 0.0+s45, 0.0-s45)
854 <<QLineF(0.0, 0.0, 0.0+s45, 0.0+s45);
855
856 paths[JKQTPRightTripod].lines<<QLineF(0.0+0.5, 0.0, 0.0, 0.0)
857 <<QLineF(0.0, 0.0, 0.0-s45, 0.0-s45)
858 <<QLineF(0.0, 0.0, 0.0-s45, 0.0+s45);
859
860 return paths;
861 }();
862
863 painter.setBrush(QColor(Qt::transparent));
864 painter.setPen(p);
865 switch(symbol) {
866 case JKQTPDot:
867 painter.drawPoint(QPointF(x,y));
868 break;
869
870 case JKQTPCross:
871 case JKQTPPlus:
872 case JKQTPCircle:
873 case JKQTPCircleCross:
874 case JKQTPCirclePlus:
875 case JKQTPCirclePeace:
876 case JKQTPPeace:
877 case JKQTPFemale:
878 case JKQTPMale:
879 case JKQTPTarget:
880 case JKQTPRect:
881 case JKQTPRectCross:
882 case JKQTPRectPlus:
887 case JKQTPAsterisc:
888 case JKQTPAsterisc6:
889 case JKQTPAsterisc8:
890 case JKQTPDiamondPlus:
892 painter.translate(QPointF(x,y));
893 painter.scale(symbolSize,symbolSize);
894 painter.setBrush(QColor(Qt::transparent));
895 painter.setPen(pDescaled);
896 if (all_paths[symbol].pathsrotation!=0.0) painter.rotate(all_paths[symbol].pathsrotation);
897 painter.drawPath(all_paths[symbol].paths);
898 break;
899
900
901
903 case JKQTPFilledRect:
908 painter.translate(QPointF(x,y));
909 painter.scale(symbolSize,symbolSize);
910 painter.setBrush(b);
911 painter.setPen(pDescaled);
912 if (all_paths[symbol].pathsrotation!=0.0) painter.rotate(all_paths[symbol].pathsrotation);
913 painter.drawPath(all_paths[symbol].filledpaths);
914
915 break;
916
917
918
923 case JKQTPTriangle:
927 case JKQTPstar:
928 case JKQTPPentagon:
929 case JKQTPHexagon:
930 case JKQTPOctagon:
933 case JKQTPHourglass:
935 case JKQTPDiamond:
936 painter.translate(QPointF(x,y));
937 painter.scale(symbolSize,symbolSize);
938 painter.setBrush(QColor(Qt::transparent));
939 painter.setPen(pDescaled);
940 if (all_paths[symbol].pathsrotation!=0.0) painter.rotate(all_paths[symbol].pathsrotation);
941 painter.drawConvexPolygon(all_paths[symbol].polygons);
942 break;
943
944
945
950 case JKQTPFilledStar:
959 painter.translate(QPointF(x,y));
960 painter.scale(symbolSize,symbolSize);
961 painter.setBrush(b);
962 painter.setPen(pDescaled);
963 if (all_paths[symbol].pathsrotation!=0.0) painter.rotate(all_paths[symbol].pathsrotation);
964 painter.drawConvexPolygon(all_paths[symbol].filledpolygons);
965 break;
966
967
968
969 case JKQTPTripod:
970 case JKQTPDownTripod:
971 case JKQTPLeftTripod:
972 case JKQTPRightTripod:
973 painter.translate(QPointF(x,y));
974 painter.scale(symbolSize,symbolSize);
975 painter.setBrush(QColor(Qt::transparent));
976 painter.setPen(pDescaled);
977 if (all_paths[symbol].pathsrotation!=0.0) painter.rotate(all_paths[symbol].pathsrotation);
978 painter.drawLines(all_paths[symbol].lines);
979 break;
980
981
982
983 case JKQTPNoSymbol:
984 case JKQTPSymbolCount:
988 break;
989 }
990 if (symbol>=JKQTPCharacterSymbol && symbol<=JKQTPCharacterSymbol+0xFFFF) {
991 symbolFont.setStyleStrategy(QFont::PreferDefault);
992 const QChar ch(static_cast<uint16_t>(symbol-JKQTPCharacterSymbol));
993 const QFontMetricsF fm(symbolFont);
994 const QRectF tbr=fm.tightBoundingRect(ch);
995 const double scale=symbolSize/qMax(tbr.width(), tbr.height());
996 painter.translate(QPointF(x,y));
997 //painter.setPen(QColor("yellow"));
998 //painter.drawEllipse(QPointF(0,0),symbolSize/2.0,symbolSize/2.0);
999 painter.scale(scale,scale);
1000 //painter.setPen(QColor("green"));
1001 //painter.drawRect(tbr);
1002 //painter.drawEllipse(QPointF(0,0),2,2);
1003 painter.translate(-tbr.center());//QPointF(-tbr.width()/2.0,-tbr.height()/2.0)+QPointF(tbr.x(),tbr.y()));
1004 //painter.setPen(QColor("red"));
1005 //painter.drawRect(tbr);
1006 //painter.drawEllipse(QPointF(0,0),2,2);
1007 painter.setBrush(color);
1008 painter.setPen(Qt::NoPen);
1009 QPainterPath path;
1010 path.addText(0,0,symbolFont, ch),
1011 painter.drawPath(path);
1012 }
1013 if (symbol>=JKQTPFilledCharacterSymbol && symbol<=JKQTPFilledCharacterSymbol+0xFFFF) {
1014 symbolFont.setStyleStrategy(QFont::PreferDefault);
1015 const QChar ch(static_cast<uint16_t>(symbol-JKQTPFilledCharacterSymbol));
1016 const QFontMetricsF fm(symbolFont);
1017 const QRectF tbr=fm.tightBoundingRect(ch);
1018 const double scale=symbolSize/qMax(tbr.width(), tbr.height());
1019 painter.setPen(p);
1020 painter.translate(QPointF(x,y));
1021 painter.scale(scale,scale);
1022 painter.translate(-tbr.center());//QPointF(-tbr.width()/2.0,-tbr.height()/2.0)+QPointF(tbr.x(),tbr.y()));
1023 painter.setBrush(b);
1024 QPainterPath path;
1025 path.addText(0,0,symbolFont, ch),
1026 painter.drawPath(path);
1027 }
1028 if (symbol>=JKQTPFirstCustomSymbol) {
1030 const int idx(static_cast<int>(symbol-JKQTPFirstCustomSymbol));
1031 if (idx>=0 && idx<JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->size()) {
1032 painter.setPen(p);
1033 painter.translate(QPointF(x,y));
1034 painter.scale(symbolSize,symbolSize);
1035 painter.setBrush(b);
1036 painter.setPen(pDescaled);
1037 const auto functor=JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore->at(idx);
1038 functor(painter);
1039 }
1040 }
1041}
1042
1043template <class TPainter>
1044inline void JKQTPDrawTooltip(TPainter& painter, double x, double y, const QRectF& rect)
1045{
1046 QPolygonF poly;
1047 if (y<rect.top()) {
1048 poly<<rect.topLeft()<<QPointF(rect.left()+rect.width()/3, rect.top())<<QPointF(x,y)<<QPointF(rect.right()-rect.width()/3, rect.top())<< rect.topRight()<<rect.bottomRight()<<rect.bottomLeft()<<rect.topLeft();
1049 painter.drawPolygon(poly);
1050 } else if (y>rect.bottom()) {
1051 poly<<rect.topLeft()<<rect.topRight()<<rect.bottomRight()<<QPointF(rect.right()-rect.width()/3, rect.bottom())<<QPointF(x,y)<<QPointF(rect.left()+rect.width()/3, rect.bottom())<< rect.bottomLeft()<<rect.topLeft();
1052 painter.drawPolygon(poly);
1053 } else if (x<rect.left()) {
1054 poly<<QPointF(x,y)<<rect.topLeft()<<rect.topRight()<<rect.bottomRight()<<rect.bottomLeft()<<QPointF(rect.left(), rect.top()+rect.height()/2)<<QPointF(x,y);
1055 painter.drawPolygon(poly);
1056 } else if (x>rect.left()) {
1057 poly<<rect.topLeft()<<rect.topRight()<<QPointF(x,y)<<QPointF(rect.right(), rect.top()+rect.height()/2)<<rect.bottomRight()<<rect.bottomLeft()<<rect.topLeft();
1058 painter.drawPolygon(poly);
1059 } else {
1060 painter.drawRect(rect);
1061 }
1062}
1063
1064template <class TPainter>
1065inline void JKQTPPlotDecoratedLine(TPainter& painter, const QLineF& l, JKQTPLineDecoratorStyle style1, double size1, JKQTPLineDecoratorStyle style2, double size2) {
1066 const double angle1=atan2(l.p2().y()-l.p1().y(), l.p2().x()-l.p1().x());
1067 const double angle2=atan2(l.p1().y()-l.p2().y(), l.p1().x()-l.p2().x());
1068 QPointF lx1=l.p1(), lx2=l.p2();
1069 JKQTPPlotLineDecorator(painter, l.p1().x(), l.p1().y(), angle1, style1, size1, &lx1);
1070 JKQTPPlotLineDecorator(painter, l.p2().x(), l.p2().y(), angle2, style2, size2, &lx2);
1071 // draw corrected line
1072 painter.drawLine(QLineF(lx1, lx2));
1073
1074}
1075
1076
1077template <class TPainter>
1078inline void JKQTPPlotLineDecorator(TPainter& painter, double x, double y, double angle_rad, JKQTPLineDecoratorStyle style, double size, QPointF* line_start) {
1079 if (line_start) *line_start=QPointF(x,y);
1080 static double default_theta_open_tip=60.0/2.0 /180.0*JKQTPSTATISTICS_PI;
1081 static double tan__default_theta_open_tip=tan(default_theta_open_tip);
1082 static double default_theta_closed_tip=50.0/2.0 /180.0*JKQTPSTATISTICS_PI;
1083 static double tan__default_theta_closed_tip=tan(default_theta_closed_tip);
1084 QPen pinit=painter.pen();
1085 pinit.setCapStyle(Qt::FlatCap);
1086 pinit.setJoinStyle(Qt::RoundJoin);
1087 QPen p0=pinit;
1088 p0.setWidthF(0);
1089 {
1090 painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
1091 painter.translate(x,y);
1092 painter.rotate(angle_rad/JKQTPSTATISTICS_PI*180.0);
1093 painter.setPen(p0);
1094
1095 switch(style) {
1096 case JKQTPArrow:
1097 case JKQTPArrowAndBar: {
1098 const QPointF poly[3] = {
1099 QPointF(size, -tan__default_theta_open_tip*size),
1100 QPointF(0,0),
1101 QPointF(size, tan__default_theta_open_tip*size)
1102 };
1103 painter.setPen(pinit);
1104 if (style==JKQTPArrowAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
1105 painter.drawPolyline(poly, 3);
1106 } break;
1109 painter.setPen(pinit);
1110 if (style==JKQTPHarpoonDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
1111 painter.drawLine(QPointF(0,0), QPointF(size, tan__default_theta_open_tip*size));
1112 } break;
1113 case JKQTPDoubleArrow:
1115 const QPointF poly[3] = {
1116 QPointF(size, -tan__default_theta_open_tip*size),
1117 QPointF(0,0),
1118 QPointF(size, tan__default_theta_open_tip*size)
1119 };
1120 painter.setPen(pinit);
1121 if (style==JKQTPDoubleArrowAndBar) painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
1122 painter.drawPolyline(poly, 3);
1123 painter.translate(4.0*pinit.widthF(),0);
1124 painter.drawPolyline(poly, 3);
1125 if (line_start) *line_start=QPointF(x,y)+QPointF(4.0*pinit.widthF()*cos(angle_rad),4.0*pinit.widthF()*sin(angle_rad));
1126 } break;
1127 case JKQTPFilledArrow:
1129 const QPointF poly[4] = {
1130 QPointF(0,0),
1131 QPointF(size, tan__default_theta_closed_tip*size),
1132 QPointF(0.75*size,0),
1133 QPointF(size, -tan__default_theta_closed_tip*size)
1134 };
1135 painter.drawPolygon(poly, 4);
1136 if (style==JKQTPFilledDoubleArrow) {
1137 painter.translate(0.5*size, 0);
1138 painter.drawPolygon(poly, 4);
1139 if (line_start) *line_start=QPointF(x,y)+QPointF(1.25*size*cos(angle_rad),1.25*size*sin(angle_rad));
1140 } else {
1141 if (line_start) *line_start=QPointF(x,y)+QPointF(0.75*size*cos(angle_rad),0.75*size*sin(angle_rad));
1142 }
1143 } break;
1144
1147 const QPointF poly[3] = {
1148 QPointF(size, -tan__default_theta_closed_tip*size),
1149 QPointF(0,0),
1150 QPointF(size, tan__default_theta_closed_tip*size)
1151 };
1152 painter.setBrush(Qt::NoBrush);
1153 painter.setPen(pinit);
1154 painter.drawConvexPolygon(poly, 3);
1155 if (style==JKQTPTriangleDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
1156 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1157 } break;
1158
1161 const QPointF poly[3] = {
1162 QPointF(size, -tan__default_theta_closed_tip*size),
1163 QPointF(0,0),
1164 QPointF(size, tan__default_theta_closed_tip*size)
1165 };
1166 painter.setPen(p0);
1167 painter.drawConvexPolygon(poly, 3);
1169 painter.setPen(pinit);
1170 painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
1171 }
1172 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1173 } break;
1174
1175
1178 const QPointF poly[4] = {
1179 QPointF(0,0),
1180 QPointF(size/2.0, -tan__default_theta_closed_tip*size),
1181 QPointF(size,0),
1182 QPointF(size/2.0, tan__default_theta_closed_tip*size)
1183 };
1184 painter.setBrush(Qt::NoBrush);
1185 painter.setPen(pinit);
1186 painter.drawConvexPolygon(poly, 4);
1187 if (style==JKQTPDiamondDecoratorAndBar) painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
1188 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1189 } break;
1190
1193 const QPointF poly[4] = {
1194 QPointF(0,0),
1195 QPointF(size/2.0, -tan__default_theta_closed_tip*size),
1196 QPointF(size,0),
1197 QPointF(size/2.0, tan__default_theta_closed_tip*size)
1198 };
1199 painter.setPen(p0);
1200 painter.drawConvexPolygon(poly, 4);
1202 painter.setPen(pinit);
1203 painter.drawLine(QPointF(0,-tan__default_theta_closed_tip*size), QPointF(0,tan__default_theta_closed_tip*size));
1204 }
1205 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1206 } break;
1207
1210 if (style==JKQTPCircleDecorator) {
1211 painter.setBrush(Qt::NoBrush);
1212 painter.setPen(pinit);
1213 } else {
1214 painter.setPen(p0);
1215 }
1216 painter.drawEllipse(QRectF(0,-size/2.0,size,size));
1217 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1218 } break;
1219
1222 if (style==JKQTPRectangleDecorator) {
1223 painter.setBrush(Qt::NoBrush);
1224 painter.setPen(pinit);
1225 } else {
1226 painter.setPen(p0);
1227 }
1228 painter.drawRect(QRectF(0,-size/2.0,size,size));
1229 if (line_start) *line_start=QPointF(x,y)+QPointF(size*cos(angle_rad),size*sin(angle_rad));
1230 } break;
1231
1232 case JKQTPBarDecorator: {
1233 painter.setPen(pinit);
1234 painter.drawLine(QPointF(0,-tan__default_theta_open_tip*size), QPointF(0,tan__default_theta_open_tip*size));
1235 } break;
1236
1237 case JKQTPHalfBarDecorator: {
1238 painter.setPen(pinit);
1239 painter.drawLine(QPointF(0,0), QPointF(0,tan__default_theta_open_tip*size));
1240 } break;
1241
1243 painter.setPen(pinit);
1244 painter.drawLine(QPointF(0.25*size,-tan__default_theta_open_tip*size), QPointF(-0.25*size,tan__default_theta_open_tip*size));
1245 } break;
1246
1247 case JKQTPBracketDecorator: {
1248 const QPointF poly[4] = {
1249 QPointF(-size*0.2,-tan__default_theta_open_tip*size),
1250 QPointF(0,-tan__default_theta_open_tip*size),
1251 QPointF(0,tan__default_theta_open_tip*size),
1252 QPointF(-size*0.2, tan__default_theta_open_tip*size)
1253 };
1254 painter.setPen(pinit);
1255 painter.drawPolyline(poly, 4);
1256 } break;
1258 case JKQTPNoDecorator:
1259 break;
1260 }
1261
1262 }
1263}
1264
1265
1266#endif // JKQTPDRAWINGTOOLS_H_INCLUDED
this class extends the QPainter
Definition jkqtpenhancedpainter.h:33
template class that wraps any datatype and combines it with a mutex, exposes the lock()/unlock() inte...
Definition jkqtpconcurrencytools.h:40
JKQTPFinalAct< F > JKQTPFinally(const F &f) noexcept
C++11 finally construct (executes a callable-object at the end of a scope)
Definition jkqtpcodestructuring.h:93
JKQTCOMMON_LIB_EXPORT QList< QPolygonF > JKQTPClipPolyLine(const QPolygonF &polyline_in, const QRectF &clipRect)
clips the given poly-line polyline_in to the given rectangle clipRect
JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos)
converts a JKQTPGraphSymbols variable into a human-readable string
JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor)
calculates the tail decorator size from the line width line_width, using decoratorSizeFactor and a no...
JKQTCOMMON_LIB_EXPORT QList< QPolygonF > JKQTPClipPolyLines(const QList< QPolygonF > &polylines_in, const QRectF &clipRect)
clips the given list of poly-lines polylines_in to the given rectangle clipRect
void JKQTPPlotSymbol(TPainter &painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont)
plot the specified symbol at pixel position x,y, thread-safe
Definition jkqtpdrawingtools.h:661
std::function< void(QPainter &p)> JKQTPCustomGraphSymbolFunctor
functor used to draw a custom JKQTPGraphSymbols
Definition jkqtpdrawingtools.h:76
static JKQTCOMMON_LIB_EXPORT JKQTPSynchronized< QVector< JKQTPCustomGraphSymbolFunctor > > JKQTPCustomGraphSymbolStore
stores all custom JKQTPGraphSymbols registered using JKQTPRegisterCustomGraphSymbol
Definition jkqtpdrawingtools.h:119
JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos)
converts a JKQTPGraphSymbols variable into a identifier string
void JKQTPPlotLineDecorator(TPainter &painter, double x, double y, double angle_rad, JKQTPLineDecoratorStyle style, double size, QPointF *line_start=nullptr)
plot the specified symbol at pixel position x,y. Note that this function only draws the decorator,...
Definition jkqtpdrawingtools.h:1078
JKQTCOMMON_LIB_EXPORT QList< QPolygonF > JKQTPSimplifyPolyLines(const QList< QPolygonF > &lines_in, double maxDeltaXY=1.0)
tries to reduce the complexity of the given list of poly-lines lines_in, but keeping the appearance a...
bool JKQTPClipLine(double &x1, double &y1, double &x2, double &y2, double xmin, double xmax, double ymin, double ymax)
clips the given line (x1 , y1 ) – (x2 , y2 ) to the given rectangle xmin .. xmax and ymin ....
Definition jkqtpdrawingtools.h:496
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString &pos)
converts a String into a JKQTPGraphSymbols
JKQTCOMMON_LIB_EXPORT void JKQTPReplaceCurrentColor(QColor &col, const QColor &currentColor)
check whether col equals JKQTPlotterDrawingTools::CurrentColorPlaceholder (or one of its variants) an...
void JKQTPPlotDecoratedLine(TPainter &painter, const QLineF &l, JKQTPLineDecoratorStyle style1, double size1, JKQTPLineDecoratorStyle style2, double size2)
plot a line with the given decorators style1 and a style2 at the start- and end-point repsectively,...
Definition jkqtpdrawingtools.h:1065
std::array< QPointF, N *2 > JKQTPGetStarCoordinates(double inner_radius=0.5)
return the consecutive ccordinates of the tips of a N-tipped star on a circle of radius 1....
Definition jkqtpdrawingtools.h:634
JKQTCOMMON_LIB_EXPORT QString JKQTPLineDecoratorStyle2NameString(JKQTPLineDecoratorStyle pos)
converts a JKQTPLineDecoratorStyle variable into a human-readable string
JKQTPLineDecoratorStyle
symbols that can be used to plot a datapoint for a graph
Definition jkqtpdrawingtools.h:365
JKQTPGraphSymbols
symbols that can be used to plot a datapoint for a graph
Definition jkqtpdrawingtools.h:143
JKQTCOMMON_LIB_EXPORT JKQTPLineDecoratorStyle String2JKQTPLineDecoratorStyle(const QString &pos)
converts a String into a JKQTPLineDecoratorStyle
JKQTCOMMON_LIB_EXPORT QString JKQTPLineDecoratorStyle2String(JKQTPLineDecoratorStyle pos)
converts a JKQTPLineDecoratorStyle variable into a identifier string
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor &&)
register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to acce...
void JKQTPDrawTooltip(TPainter &painter, double x, double y, const QRectF &rect)
draw a tooltip, using the current brush and pen of the provided painter
Definition jkqtpdrawingtools.h:1044
@ JKQTPFilledDiamondDecoratorAndBar
a filled diamond tip
Definition jkqtpdrawingtools.h:386
@ JKQTPDiamondDecorator
an open diamond tip
Definition jkqtpdrawingtools.h:383
@ JKQTPHarpoonDecorator
an harpoon arrow
Definition jkqtpdrawingtools.h:388
@ JKQTPTriangleDecoratorAndBar
a triangular arrow tip, with vertical bar
Definition jkqtpdrawingtools.h:371
@ JKQTPDoubleArrow
a nice double-arrow tip
Definition jkqtpdrawingtools.h:373
@ JKQTPCircleDecorator
an open circle tip
Definition jkqtpdrawingtools.h:375
@ JKQTPArrow
a simple arrow tip, unfilled
Definition jkqtpdrawingtools.h:367
@ JKQTPFilledCircleDecorator
a filled circle tip
Definition jkqtpdrawingtools.h:376
@ JKQTPArrowAndBar
a simple arrow tip, unfilled, with vertical bar
Definition jkqtpdrawingtools.h:379
@ JKQTPMaxLineDecoratorID
points to the last available symbol, can be used to iterate over all symbols: for (int i=0; i<=static...
Definition jkqtpdrawingtools.h:393
@ JKQTPBracketDecorator
a vertical bracket decorator
Definition jkqtpdrawingtools.h:382
@ JKQTPNoDecorator
no decorator, i.e. a simple line-end
Definition jkqtpdrawingtools.h:366
@ JKQTPBarDecorator
a full vertical bar
Definition jkqtpdrawingtools.h:381
@ JKQTPDefaultLineDecorator
a default symbol used for plotting
Definition jkqtpdrawingtools.h:394
@ JKQTPDoubleArrowAndBar
a simple double-arrow tip, unfilled, with vertical bar
Definition jkqtpdrawingtools.h:380
@ JKQTPFilledDiamondDecorator
a filled diamond tip
Definition jkqtpdrawingtools.h:385
@ JKQTPDiamondDecoratorAndBar
an open diamond tip
Definition jkqtpdrawingtools.h:384
@ JKQTPHalfBarDecorator
a half vertical bar
Definition jkqtpdrawingtools.h:387
@ JKQTPFilledTriangleDecorator
a triangular filled arrow tip
Definition jkqtpdrawingtools.h:370
@ JKQTPFilledTriangleDecoratorAndBar
a triangular filled arrow tip, with vertical bar
Definition jkqtpdrawingtools.h:372
@ JKQTPFilledArrow
a nice filled arrow tip
Definition jkqtpdrawingtools.h:368
@ JKQTPRectangleDecorator
an open rectangle tip
Definition jkqtpdrawingtools.h:377
@ JKQTPSkewedBarDecorator
a skewed vertical bar
Definition jkqtpdrawingtools.h:390
@ JKQTPHarpoonDecoratorAndBar
an harpoon arrow, with vertical bar
Definition jkqtpdrawingtools.h:389
@ JKQTPTriangleDecorator
a triangular arrow tip
Definition jkqtpdrawingtools.h:369
@ JKQTPLineDecoratorCount
can be used to iterate over all symbols using: for (int i=0; i<static_cast<int>(JKQTPLineDecoratorCou...
Definition jkqtpdrawingtools.h:392
@ JKQTPFilledRectangleDecorator
a filled rectangle tip
Definition jkqtpdrawingtools.h:378
@ JKQTPFilledDoubleArrow
a nice filled double-arrow tip
Definition jkqtpdrawingtools.h:374
@ JKQTPRectCross
a square symbol with a cross inside
Definition jkqtpdrawingtools.h:168
@ JKQTPDownCurvedTriangle
a curved triangle, pointing down
Definition jkqtpdrawingtools.h:197
@ JKQTPFemale
a female symbol
Definition jkqtpdrawingtools.h:214
@ JKQTPAsterisc
an asterisc star with 5 arms
Definition jkqtpdrawingtools.h:160
@ JKQTPCurvedTriangle
a curved triangle
Definition jkqtpdrawingtools.h:163
@ JKQTPPentagon
an unfilled pentagon
Definition jkqtpdrawingtools.h:158
@ JKQTPAsterisc6
an asterisc star with 6 arms
Definition jkqtpdrawingtools.h:186
@ JKQTPFilledCurvedTriangle
a filled curved triangle
Definition jkqtpdrawingtools.h:164
@ JKQTPFilledHexagon
a filled hexagon
Definition jkqtpdrawingtools.h:166
@ JKQTPUpDownTriangle
a overlay of an up and a down triangle symbol
Definition jkqtpdrawingtools.h:205
@ JKQTPRectTriangle
a square symbol with a triangle inside
Definition jkqtpdrawingtools.h:170
@ JKQTPAsterisc8
an asterisc star with 8 arms
Definition jkqtpdrawingtools.h:187
@ JKQTPFilledDownCurvedTriangle
a filled curved triangle, pointing down
Definition jkqtpdrawingtools.h:198
@ JKQTPDownTriangle
an unfilled triangle (tip at bottom)
Definition jkqtpdrawingtools.h:191
@ JKQTPFilledRightTriangle
a filled triangle (tip to the right)
Definition jkqtpdrawingtools.h:196
@ JKQTPRectLeftTriangle
a square symbol with a triangle (tip to the left) inside
Definition jkqtpdrawingtools.h:172
@ JKQTPFilledHorizontalHourglass
a filled horizontal hour glass symbol
Definition jkqtpdrawingtools.h:208
@ JKQTPRightTriangle
an unfilled triangle (tip to the right)
Definition jkqtpdrawingtools.h:195
@ JKQTPCharacterSymbol
draw a font-character as symbol with defined fill-brush (taken from symbol-color),...
Definition jkqtpdrawingtools.h:220
@ JKQTPDefaultSymbol
a default symbol used for plotting
Definition jkqtpdrawingtools.h:218
@ JKQTPNoSymbol
plots no symbol at all (usefull together with error bars)
Definition jkqtpdrawingtools.h:144
@ JKQTPHexagon
an unfilled hexagon
Definition jkqtpdrawingtools.h:165
@ JKQTPFilledUpDownTriangle
a filled version of the overlay of an up and a down triangle
Definition jkqtpdrawingtools.h:206
@ JKQTPstar
an unfilled diamond
Definition jkqtpdrawingtools.h:156
@ JKQTPLeftTriangle
an unfilled triangle (tip to the left)
Definition jkqtpdrawingtools.h:193
@ JKQTPFilledRightCurvedTriangle
a filled curved triangle, pointing to the right
Definition jkqtpdrawingtools.h:202
@ JKQTPFilledTriangle
a filled triangle (tip at top)
Definition jkqtpdrawingtools.h:153
@ JKQTPSantaClauseHouse
a small house symbol ("Das is das haus vom Nicolaus")
Definition jkqtpdrawingtools.h:210
@ JKQTPSymbolCount
can be used to iterate over all symbols using: for (int i=0; i<static_cast<int>(JKQTPSymbolCount); i+...
Definition jkqtpdrawingtools.h:216
@ JKQTPDot
a small dot
Definition jkqtpdrawingtools.h:145
@ JKQTPCircleCross
a circle symbol with a cross inside
Definition jkqtpdrawingtools.h:175
@ JKQTPMale
a male symbol
Definition jkqtpdrawingtools.h:213
@ JKQTPFilledStar
a filled diamond
Definition jkqtpdrawingtools.h:157
@ JKQTPCross
a X cross
Definition jkqtpdrawingtools.h:146
@ JKQTPRightCurvedTriangle
a curved triangle, pointing to the right
Definition jkqtpdrawingtools.h:201
@ JKQTPHorizontalHourglass
a horizontal hour glass symbol
Definition jkqtpdrawingtools.h:207
@ JKQTPLeftCurvedTriangle
a curved triangle, pointing to the left
Definition jkqtpdrawingtools.h:199
@ JKQTPFilledRect
a filled rectangle
Definition jkqtpdrawingtools.h:151
@ JKQTPDownTripod
a tripod symbol, pointing down
Definition jkqtpdrawingtools.h:183
@ JKQTPFilledOctagon
a filled octagon
Definition jkqtpdrawingtools.h:204
@ JKQTPFilledHourglass
a filled hour glass symbol
Definition jkqtpdrawingtools.h:162
@ JKQTPCirclePlus
a circle symbol with a plus inside
Definition jkqtpdrawingtools.h:176
@ JKQTPFilledDownTriangle
a filled triangle (tip at bottom)
Definition jkqtpdrawingtools.h:192
@ JKQTPDiamondCross
a diamond symbol with a cross inside
Definition jkqtpdrawingtools.h:180
@ JKQTPLeftTripod
a tripod symbol, pointing to the left
Definition jkqtpdrawingtools.h:184
@ JKQTPTriangle
an unfilled triangle (tip at top)
Definition jkqtpdrawingtools.h:152
@ JKQTPDiamond
an unfilled diamond
Definition jkqtpdrawingtools.h:154
@ JKQTPRectPlus
a square symbol with a plus inside
Definition jkqtpdrawingtools.h:169
@ JKQTPCircle
an unfilled circle
Definition jkqtpdrawingtools.h:148
@ JKQTPFilledPentagon
a filled pentagon
Definition jkqtpdrawingtools.h:159
@ JKQTPFilledSantaClauseHouse
a filled small house symbol ("Das is das haus vom Nicolaus")
Definition jkqtpdrawingtools.h:211
@ JKQTPFilledDiamond
a filled diamond
Definition jkqtpdrawingtools.h:155
@ JKQTPRectDownTriangle
a square symbol with a triangle (tip to the bottom) inside
Definition jkqtpdrawingtools.h:171
@ JKQTPHourglass
an hour glass symbol
Definition jkqtpdrawingtools.h:161
@ JKQTPRect
an unfilled rectangle
Definition jkqtpdrawingtools.h:150
@ JKQTPCirclePeace
a circled peace symbol
Definition jkqtpdrawingtools.h:177
@ JKQTPOctagon
an unfilled octagon
Definition jkqtpdrawingtools.h:203
@ JKQTPFilledCircle
a filled circle
Definition jkqtpdrawingtools.h:149
@ JKQTPFilledCharacterSymbol
draw a font-character as symbol with defined outline-pen and fill-brush, you can use any character fr...
Definition jkqtpdrawingtools.h:223
@ JKQTPPlus
a + cross
Definition jkqtpdrawingtools.h:147
@ JKQTPDiamondPlus
a diamond symbol with a plus inside
Definition jkqtpdrawingtools.h:179
@ JKQTPPeace
a peace symbol
Definition jkqtpdrawingtools.h:188
@ JKQTPRectRightTriangle
a square symbol with a triangle (tip to the right) inside
Definition jkqtpdrawingtools.h:173
@ JKQTPTarget
a target symbol (circle with cross)
Definition jkqtpdrawingtools.h:189
@ JKQTPRightTripod
a tripod symbol, pointing to the right
Definition jkqtpdrawingtools.h:185
@ JKQTPTripod
a tripod symbol
Definition jkqtpdrawingtools.h:182
@ JKQTPMaxSymbolID
points to the last available symbol, can be used to iterate over all symbols: for (int i=0; i<=static...
Definition jkqtpdrawingtools.h:217
@ JKQTPFilledLeftCurvedTriangle
a filled curved triangle, pointing to the left
Definition jkqtpdrawingtools.h:200
@ JKQTPFirstCustomSymbol
draw a completely custom symbol, defined by supplying a functor to JKQTPRegisterCustomGraphSymbol()
Definition jkqtpdrawingtools.h:227
@ JKQTPFilledLeftTriangle
a filled triangle (tip to the left)
Definition jkqtpdrawingtools.h:194
#define JKQTCOMMON_LIB_EXPORT
Definition jkqtcommon_imexport.h:87
#define JKQTPSTATISTICS_PI
Definition jkqtpmathtools.h:52
internal datastructure used in JKQTPPlotSymbol() to precalculate certain data only once per runtime
Definition jkqtpdrawingtools.h:649
QPainterPath filledpaths
Definition jkqtpdrawingtools.h:652
QVector< QLineF > lines
Definition jkqtpdrawingtools.h:653
QPolygonF polygons
Definition jkqtpdrawingtools.h:654
JKQTPSymbolPathsInternnal()
Definition jkqtpdrawingtools.h:650
qreal pathsrotation
Definition jkqtpdrawingtools.h:656
QPainterPath paths
Definition jkqtpdrawingtools.h:651
QPolygonF filledpolygons
Definition jkqtpdrawingtools.h:655
tool class with static values used by JKQTPlotter/JKQTBasePlotter
Definition jkqtpdrawingtools.h:81
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder_Trans50
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:101
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder_Trans90
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:111
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder_Trans75
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:106
JKQTPSynchronized< QVector< JKQTPCustomGraphSymbolFunctor > >::WriteLocker SymbolsWriteLocker
Definition jkqtpdrawingtools.h:121
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:86
JKQTPSynchronized< QVector< JKQTPCustomGraphSymbolFunctor > >::ReadLocker SymbolsReadLocker
Definition jkqtpdrawingtools.h:120
static JKQTCOMMON_LIB_EXPORT const double ABS_MIN_LINEWIDTH
smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
Definition jkqtpdrawingtools.h:114
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder_Trans10
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:91
static JKQTCOMMON_LIB_EXPORT const QColor CurrentColorPlaceholder_Trans25
a special placeholder that can be used to indicate that a color should be replaced by the "current co...
Definition jkqtpdrawingtools.h:96