2019-05-30 04:40:02 +08:00
/*
2022-07-19 19:40:43 +08:00
Copyright ( c ) 2008 - 2022 Jan W . Krieger ( < jan @ jkrieger . de > )
2019-05-30 04:40:02 +08:00
This software is free software : you can redistribute it and / or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation , either version 2.1 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef JKQTPDRAWINGTOOLS_H_INCLUDED
# define JKQTPDRAWINGTOOLS_H_INCLUDED
2019-06-22 20:21:32 +08:00
# include "jkqtcommon/jkqtcommon_imexport.h"
2019-05-30 04:40:02 +08:00
# include <QPaintDevice>
# include <QPainter>
# include <QPolygonF>
# include <QPolygon>
# include <QRectF>
# include <QRect>
# include <QLineF>
# include <QLine>
# include <QPainterPath>
# include <QColor>
# include <QVector>
# include <vector>
- improved: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)
- improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)
- new: all geometric objects can either be drawn as graphic element (i.e. lines are straight line, even on non-linear axes), or as mathematical curve (i.e. on non-linear axes, lines become the appropriate curve representing the linear function, connecting the given start/end-points). The only exceptions are ellipses (and the derived arcs,pies,chords), which are always drawn as mathematical curves
2020-09-04 05:08:52 +08:00
# include <forward_list>
2019-05-30 04:40:02 +08:00
# include <cmath>
- improved: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)
- improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)
- new: all geometric objects can either be drawn as graphic element (i.e. lines are straight line, even on non-linear axes), or as mathematical curve (i.e. on non-linear axes, lines become the appropriate curve representing the linear function, connecting the given start/end-points). The only exceptions are ellipses (and the derived arcs,pies,chords), which are always drawn as mathematical curves
2020-09-04 05:08:52 +08:00
# include <utility>
2020-08-22 00:31:58 +08:00
# include <QDebug>
2019-05-30 04:40:02 +08:00
# include "jkqtcommon/jkqtpmathtools.h"
# include "jkqtcommon/jkqtpcodestructuring.h"
class JKQTPEnhancedPainter ; // forward
/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter
\ ingroup jkqtptools_drawing
*/
2019-06-22 20:21:32 +08:00
struct JKQTPlotterDrawingTools {
2019-05-30 04:40:02 +08:00
/** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
*/
2019-06-22 20:21:32 +08:00
static JKQTCOMMON_LIB_EXPORT const double ABS_MIN_LINEWIDTH ;
2019-05-30 04:40:02 +08:00
} ;
/** \brief symbols that can be used to plot a datapoint for a graph
* \ ingroup jkqtptools_drawing
*/
enum JKQTPGraphSymbols {
JKQTPNoSymbol = 0 , /*!< \brief plots no symbol at all (usefull together with error bars) */
JKQTPDot , /*!< \brief a small dot \image html symbols/symbol_dot.png */
JKQTPCross , /*!< \brief a X cross \image html symbols/symbol_cross.png */
JKQTPPlus , /*!< \brief a + cross \image html symbols/symbol_plus.png */
JKQTPCircle , /*!< \brief an unfilled circle \image html symbols/symbol_circle.png */
JKQTPFilledCircle , /*!< \brief a filled circle \image html symbols/symbol_filled_circle.png */
JKQTPRect , /*!< \brief an unfilled rectangle \image html symbols/symbol_rect.png */
JKQTPFilledRect , /*!< \brief a filled rectangle \image html symbols/symbol_filled_rect.png */
JKQTPTriangle , /*!< \brief an unfilled triangle (tip at top) \image html symbols/symbol_triangle.png */
JKQTPFilledTriangle , /*!< \brief a filled triangle (tip at top) \image html symbols/symbol_filled_triangle.png */
JKQTPDiamond , /*!< \brief an unfilled diamond \image html symbols/symbol_diamond.png */
JKQTPFilledDiamond , /*!< \brief a filled diamond \image html symbols/symbol_filled_diamond.png */
JKQTPstar , /*!< \brief an unfilled diamond \image html symbols/symbol_star.png */
JKQTPFilledStar , /*!< \brief a filled diamond \image html symbols/symbol_filled_star.png */
JKQTPPentagon , /*!< \brief an unfilled pentagon \image html symbols/symbol_pentagon.png */
JKQTPFilledPentagon , /*!< \brief a filled pentagon \image html symbols/symbol_filled_pentagon.png */
JKQTPAsterisc , /*!< \brief an asterisc star with 5 arms \image html symbols/symbol_asterisc.png */
JKQTPHourglass , /*!< \brief an hour glass symbol \image html symbols/symbol_hourglass.png */
JKQTPFilledHourglass , /*!< \brief a filled hour glass symbol \image html symbols/symbol_filled_hourglass.png */
JKQTPCurvedTriangle , /*!< \brief a curved triangle\image html symbols/symbol_curved_triangle.png */
JKQTPFilledCurvedTriangle , /*!< \brief a filled curved triangle\image html symbols/symbol_filled_curved_triangle.png */
JKQTPHexagon , /*!< \brief an unfilled hexagon \image html symbols/symbol_hexagon.png */
JKQTPFilledHexagon , /*!< \brief a filled hexagon \image html symbols/symbol_filled_hexagon.png */
JKQTPRectCross , /*!< \brief a square symbol with a cross inside \image html symbols/symbol_rect_cross.png */
JKQTPRectPlus , /*!< \brief a square symbol with a plus inside \image html symbols/symbol_rect_plus.png */
JKQTPRectTriangle , /*!< \brief a square symbol with a triangle inside \image html symbols/symbol_rect_triangle.png */
JKQTPRectDownTriangle , /*!< \brief a square symbol with a triangle (tip to the bottom) inside \image html symbols/symbol_rect_downtriangle.png */
JKQTPRectLeftTriangle , /*!< \brief a square symbol with a triangle (tip to the left) inside \image html symbols/symbol_rect_lefttriangle.png */
JKQTPRectRightTriangle , /*!< \brief a square symbol with a triangle (tip to the right) inside \image html symbols/symbol_rect_righttriangle.png */
JKQTPCircleCross , /*!< \brief a circle symbol with a cross inside \image html symbols/symbol_circle_cross.png */
JKQTPCirclePlus , /*!< \brief a circle symbol with a plus inside \image html symbols/symbol_circle_plus.png */
JKQTPCirclePeace , /*!< \brief a circled peace symbol \image html symbols/symbol_circle_peace.png */
JKQTPDiamondPlus , /*!< \brief a diamond symbol with a plus inside \image html symbols/symbol_diamond_plus.png */
JKQTPDiamondCross , /*!< \brief a diamond symbol with a cross inside \image html symbols/symbol_diamond_cross.png */
JKQTPTripod , /*!< \brief a tripod symbol \image html symbols/symbol_tripod.png */
JKQTPDownTripod , /*!< \brief a tripod symbol, pointing down \image html symbols/symbol_down_tripod.png */
JKQTPLeftTripod , /*!< \brief a tripod symbol, pointing to the left \image html symbols/symbol_left_tripod.png */
JKQTPRightTripod , /*!< \brief a tripod symbol, pointing to the right \image html symbols/symbol_right_tripod.png */
JKQTPAsterisc6 , /*!< \brief an asterisc star with 6 arms \image html symbols/symbol_asterisc6.png */
JKQTPAsterisc8 , /*!< \brief an asterisc star with 8 arms \image html symbols/symbol_asterisc8.png */
JKQTPPeace , /*!< \brief a peace symbol \image html symbols/symbol_peace.png */
JKQTPTarget , /*!< \brief a target symbol (circle with cross) \image html symbols/symbol_target.png */
JKQTPDownTriangle , /*!< \brief an unfilled triangle (tip at bottom) \image html symbols/symbol_down_triangle.png */
JKQTPFilledDownTriangle , /*!< \brief a filled triangle (tip at bottom) \image html symbols/symbol_filled_down_triangle.png */
JKQTPLeftTriangle , /*!< \brief an unfilled triangle (tip to the left) \image html symbols/symbol_left_triangle.png */
JKQTPFilledLeftTriangle , /*!< \brief a filled triangle (tip to the left) \image html symbols/symbol_filled_left_triangle.png */
JKQTPRightTriangle , /*!< \brief an unfilled triangle (tip to the right) \image html symbols/symbol_right_triangle.png */
JKQTPFilledRightTriangle , /*!< \brief a filled triangle (tip to the right) \image html symbols/symbol_filled_right_triangle.png */
JKQTPDownCurvedTriangle , /*!< \brief a curved triangle, pointing down \image html symbols/symbol_down_curved_triangle.png */
JKQTPFilledDownCurvedTriangle , /*!< \brief a filled curved triangle, pointing down \image html symbols/symbol_filled_down_curved_triangle.png */
JKQTPLeftCurvedTriangle , /*!< \brief a curved triangle, pointing to the left \image html symbols/symbol_left_curved_triangle.png */
JKQTPFilledLeftCurvedTriangle , /*!< \brief a filled curved triangle, pointing to the left \image html symbols/symbol_filled_left_curved_triangle.png */
JKQTPRightCurvedTriangle , /*!< \brief a curved triangle, pointing to the right \image html symbols/symbol_right_curved_triangle.png */
JKQTPFilledRightCurvedTriangle , /*!< \brief a filled curved triangle, pointing to the right \image html symbols/symbol_filled_right_curved_triangle.png */
JKQTPOctagon , /*!< \brief an unfilled octagon \image html symbols/symbol_octagon.png */
JKQTPFilledOctagon , /*!< \brief a filled octagon \image html symbols/symbol_filled_octagon.png */
JKQTPUpDownTriangle , /*!< \brief a overlay of an up and a down triangle symbol \image html symbols/symbol_updowntriangle.png */
JKQTPFilledUpDownTriangle , /*!< \brief a filled version of the overlay of an up and a down triangle \image html symbols/symbol_filled_updowntriangle.png */
JKQTPHorizontalHourglass , /*!< \brief a horizontal hour glass symbol \image html symbols/symbol_horizontal_hourglass.png */
JKQTPFilledHorizontalHourglass , /*!< \brief a filled horizontal hour glass symbol \image html symbols/symbol_filled_horizontal_hourglass.png */
JKQTPSantaClauseHouse , /*!< \brief a small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_santaclause.png */
JKQTPFilledSantaClauseHouse , /*!< \brief a filled small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_filled_santaclause.png */
JKQTPMale , /*!< \brief a male symbol \image html symbols/symbol_male.png */
JKQTPFemale , /*!< \brief a female symbol \image html symbols/symbol_female.png */
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> */
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> */
JKQTPDefaultSymbol = JKQTPCross , /*!< \brief a default symbol used for plotting */
} ;
/** \brief converts a JKQTPGraphSymbols variable into a identifier string
* \ ingroup jkqtptools_drawing
*/
2019-06-22 20:21:32 +08:00
JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2String ( JKQTPGraphSymbols pos ) ;
2019-05-30 04:40:02 +08:00
/** \brief converts a JKQTPGraphSymbols variable into a human-readable string
* \ ingroup jkqtptools_drawing
*/
2019-06-22 20:21:32 +08:00
JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2NameString ( JKQTPGraphSymbols pos ) ;
2019-05-30 04:40:02 +08:00
/** \brief converts a String into a JKQTPGraphSymbols
* \ ingroup jkqtptools_drawing
*/
2019-06-22 20:21:32 +08:00
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols ( const QString & pos ) ;
2019-05-30 04:40:02 +08:00
2020-08-22 00:31:58 +08:00
/** \brief symbols that can be used to plot a datapoint for a graph
* \ ingroup jkqtptools_drawing
2020-08-23 19:13:53 +08:00
*
* \ 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
2020-08-22 00:31:58 +08:00
*/
enum JKQTPLineDecoratorStyle {
JKQTPNoDecorator = 0 , /*!< \brief no decorator, i.e. a simple line-end */
JKQTPArrow , /*!< \brief a simple arrow tip, unfilled \image html JKQTPArrow.png*/
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 */
2020-08-23 19:13:53 +08:00
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 */
2020-08-22 00:31:58 +08:00
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 */
2020-08-23 19:13:53 +08:00
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 */
2020-08-22 00:31:58 +08:00
JKQTPBracketDecorator , /*!< \brief a vertical bracket decorator \image html JKQTPBracketDecorator.png */
2020-08-23 19:13:53 +08:00
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>(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> */
2020-08-22 00:31:58 +08:00
JKQTPDefaultLineDecorator = JKQTPFilledArrow /*!< \brief a default symbol used for plotting */
} ;
/** \brief converts a JKQTPLineDecoratorStyle variable into a identifier string
* \ ingroup jkqtptools_drawing
*/
JKQTCOMMON_LIB_EXPORT QString JKQTPLineDecoratorStyle2String ( JKQTPLineDecoratorStyle pos ) ;
/** \brief converts a JKQTPLineDecoratorStyle variable into a human-readable string
* \ ingroup jkqtptools_drawing
*/
JKQTCOMMON_LIB_EXPORT QString JKQTPLineDecoratorStyle2NameString ( JKQTPLineDecoratorStyle pos ) ;
/** \brief converts a String into a JKQTPLineDecoratorStyle
* \ ingroup jkqtptools_drawing
*/
JKQTCOMMON_LIB_EXPORT JKQTPLineDecoratorStyle String2JKQTPLineDecoratorStyle ( const QString & pos ) ;
/*! \brief plot the specified symbol at pixel position x,y. Note that this function only draws the decorator, NOT the line pointing to it!
\ ingroup jkqtptools_drawing
\ tparam TPainter Type of \ a painter : A class like JKQTPEnhancedPainter or < a href = " http://doc.qt.io/qt-5/qpainter.html " > QPainter < / a >
\ param painter the < a href = " http://doc.qt.io/qt-5/qpainter.html " > QPainter < / a > to draw to
\ param x x - coordinate of the decorator tip
\ param y y - coordinate of the decorator tip
\ param angle_rad angle of the line pointing to ( x , y ) , given in radians , 0 rad points to the right , > 0 rad is a counter - clockwise rotation , as calculated by atan2 ( ) from dx , dy of a line !
\ param style type of the decorator to plot , see JKQTPLineDecoratorStyle
\ param size size of the decorator
\ param [ out ] line_start optional output parameter : when drawing the line let it end here , not necessarily at ( x , y )
*/
template < class TPainter >
inline void JKQTPPlotLineDecorator ( TPainter & painter , double x , double y , double angle_rad , JKQTPLineDecoratorStyle style , double size , QPointF * line_start = nullptr ) ;
2020-08-23 19:13:53 +08:00
/** \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 */
- improved: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)
- improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)
- new: all geometric objects can either be drawn as graphic element (i.e. lines are straight line, even on non-linear axes), or as mathematical curve (i.e. on non-linear axes, lines become the appropriate curve representing the linear function, connecting the given start/end-points). The only exceptions are ellipses (and the derived arcs,pies,chords), which are always drawn as mathematical curves
2020-09-04 05:08:52 +08:00
JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize ( double line_width , double decoratorSizeFactor ) ;
2019-05-30 04:40:02 +08:00
/*! \brief plot the specified symbol at pixel position x,y
\ ingroup jkqtptools_drawing
\ tparam TPainter Type of \ a painter : A class like JKQTPEnhancedPainter or < a href = " http://doc.qt.io/qt-5/qpainter.html " > QPainter < / a >
\ param painter the < a href = " http://doc.qt.io/qt-5/qpainter.html " > QPainter < / a > to draw to
\ param x x - coordinate of the symbol center
\ param y y - coordinate of the symbol center
\ param symbol type of the symbol to plot , see JKQTPGraphSymbols
\ param size size ( width / height ) of the symbol around ( \ a x , \ a y )
\ param symbolLineWidth width of the lines used to draw the symbol
\ param color color of the symbol lines
\ param fillColor color of the symbol filling
*/
template < class TPainter >
inline void JKQTPPlotSymbol ( TPainter & painter , double x , double y , JKQTPGraphSymbols symbol , double size , double symbolLineWidth , QColor color , QColor fillColor ) ;
/*! \brief plot the specified symbol at pixel position x,y
\ ingroup jkqtptools_drawing
\ param paintDevice the paint device to draw on
\ param x x - coordinate of the symbol center
\ param y y - coordinate of the symbol center
\ param symbol type of the symbol to plot , see JKQTPGraphSymbols
\ param size size ( width / height ) of the symbol around ( \ a x , \ a y )
\ param symbolLineWidth width of the lines used to draw the symbol
\ param color color of the symbol lines
\ param fillColor color of the symbol filling
*/
2019-06-22 20:21:32 +08:00
JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol ( QPaintDevice & paintDevice , double x , double y , JKQTPGraphSymbols symbol , double size , double symbolLineWidth , QColor color , QColor fillColor ) ;
2019-05-30 04:40:02 +08:00
2022-08-25 21:17:50 +08:00
/*! \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
\ ingroup jkqtptools_drawing
\ 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
This function implements the algorithm descripbed in https : //www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
i . e . in Pseudocode
\ verbatim
// x1 , y1 , x2 , y2 , xmin , ymax , xmax , ymin //
if not ( x1 < xmin and x2 < xmin ) and not ( x1 > xmax and x2 > xmax ) then
if not ( y1 < ymin and y2 < ymin ) and not ( y1 > ymax and y2 > ymax ) then
x [ 1 ] = x1
y [ 1 ] = y1
x [ 2 ] = x2
y [ 2 ] = y2
i = 1
repeat
if x [ i ] < xmin then
x [ i ] = xmin
y [ i ] = ( ( y2 - y1 ) / ( x2 - x1 ) ) * ( xmin - x1 ) + y1
elseif x [ i ] > xmax then
x [ i ] = xmax
y [ i ] = ( ( y2 - y1 ) / ( x2 - x1 ) ) * ( xmax - x1 ) + y1
endif
if y [ i ] < ymin then
y [ i ] = ymin
x [ i ] = ( ( x2 - x1 ) / ( y2 - y1 ) ) * ( ymin - y1 ) + x1
elseif y [ i ] > ymax then
y [ i ] = ymax
x [ i ] = ( ( x2 - x1 ) / ( y2 - y1 ) ) * ( ymax - y1 ) + x1
endif
i = i + 1
until i > 2
if not ( x [ 1 ] < xmin and x [ 2 ] < xmin ) and not ( x [ 1 ] > xmax and x [ 2 ] > xmax ) then
drawLine ( x [ 1 ] , y [ 1 ] , x [ 2 ] , y [ 2 ] )
endif
endif
endif
\ endverbatim
*/
inline bool JKQTPClipLine ( double & x1 , double & y1 , double & x2 , double & y2 , double xmin , double xmax , double ymin , double ymax ) {
if ( ! ( x1 < xmin & & x2 < xmin ) & & ! ( x1 > xmax & & x2 > xmax ) ) {
if ( ! ( y1 < ymin & & y2 < ymin ) & & ! ( y1 > ymax & & y2 > ymax ) ) {
double x [ 2 ] = { x1 , x2 } ;
double y [ 2 ] = { y1 , y2 } ;
for ( int i = 0 ; i < 2 ; i + + ) {
if ( x [ i ] < xmin ) {
x [ i ] = xmin ;
y [ i ] = ( ( y2 - y1 ) / ( x2 - x1 ) ) * ( xmin - x1 ) + y1 ;
} else if ( x [ i ] > xmax ) {
x [ i ] = xmax ;
y [ i ] = ( ( y2 - y1 ) / ( x2 - x1 ) ) * ( xmax - x1 ) + y1 ;
}
if ( y [ i ] < ymin ) {
y [ i ] = ymin ;
x [ i ] = ( ( x2 - x1 ) / ( y2 - y1 ) ) * ( ymin - y1 ) + x1 ;
} else if ( y [ i ] > ymax ) {
y [ i ] = ymax ;
x [ i ] = ( ( x2 - x1 ) / ( y2 - y1 ) ) * ( ymax - y1 ) + x1 ;
}
}
if ( ! ( x [ 0 ] < xmin & & x [ 1 ] < xmin ) & & ! ( x [ 0 ] > xmax & & x [ 1 ] > xmax ) ) {
x1 = x [ 0 ] ;
y1 = y [ 0 ] ;
x2 = x [ 1 ] ;
y2 = y [ 1 ] ;
return true ;
}
}
}
return false ;
}
/*! \brief clips the given line \a line to the given rectangle rectangle \a xmin .. \a xmax and \a ymin ... \a ymax
\ ingroup jkqtptools_drawing
\ return the clipped line or a line with 0 - length , i . e . QLineF ( )
This function implements the algorithm descripbed in https : //www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
*/
inline QLineF JKQTPClipLine ( const QLineF & line , double xmin , double xmax , double ymin , double ymax ) {
double x1 = line . x1 ( ) ;
double y1 = line . y1 ( ) ;
double x2 = line . x2 ( ) ;
double y2 = line . y2 ( ) ;
if ( JKQTPClipLine ( x1 , y1 , x2 , y2 , xmin , xmax , ymin , ymax ) ) {
return QLineF ( x1 , y1 , x2 , y2 ) ;
} else {
return QLineF ( ) ;
}
}
/*! \brief clips the given line \a line to the given rectangle \a clipRect
\ ingroup jkqtptools_drawing
\ param line line to be clipped
\ param clipRect rectangle to clip to
\ return the clipped line or a line with 0 - length , i . e . QLineF ( )
This function implements the algorithm descripbed in https : //www.researchgate.net/publication/335018076_Another_Simple_but_Faster_Method_for_2D_Line_Clipping
*/
inline QLineF JKQTPClipLine ( const QLineF & line , const QRectF & clipRect ) {
const double xmin = qMin ( clipRect . left ( ) , clipRect . right ( ) ) ;
const double xmax = qMax ( clipRect . left ( ) , clipRect . right ( ) ) ;
const double ymin = qMin ( clipRect . top ( ) , clipRect . bottom ( ) ) ;
const double ymax = qMax ( clipRect . top ( ) , clipRect . bottom ( ) ) ;
double x1 = line . x1 ( ) ;
double y1 = line . y1 ( ) ;
double x2 = line . x2 ( ) ;
double y2 = line . y2 ( ) ;
if ( JKQTPClipLine ( x1 , y1 , x2 , y2 , xmin , xmax , ymin , ymax ) ) {
return QLineF ( x1 , y1 , x2 , y2 ) ;
} else {
return QLineF ( ) ;
}
}
/*! \brief clips the given list of poly-lines \a polylines_in to the given rectangle \a clipRect
\ ingroup jkqtptools_drawing
\ param polylines_in list of poly - lines to be clipped
\ param clipRect rectangle to clip to
\ 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 !
*/
2022-08-25 23:46:57 +08:00
JKQTCOMMON_LIB_EXPORT QList < QPolygonF > JKQTPClipPolyLines ( const QList < QPolygonF > & polylines_in , const QRectF & clipRect ) ;
2022-08-25 21:17:50 +08:00
/*! \brief clips the given poly-line \a polyline_in to the given rectangle \a clipRect
\ ingroup jkqtptools_drawing
\ param polyline_in poly - line to be clipped
\ param clipRect rectangle to clip to
\ return a list of poly - lines representing the clipped line .
*/
2022-08-25 23:46:57 +08:00
JKQTCOMMON_LIB_EXPORT QList < QPolygonF > JKQTPClipPolyLine ( const QPolygonF & polyline_in , const QRectF & clipRect ) ;
2022-08-25 21:17:50 +08:00
2022-08-26 04:32:34 +08:00
/*! \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
\ ingroup jkqtptools_drawing
\ param lines_in list of poly - lines to be simplified
\ param maxDeltaXY a group has to be either less wide or less high than this , typically equals the linewidth of the poly - line
\ return a simplified version of lines_in
*/
JKQTCOMMON_LIB_EXPORT QList < QPolygonF > JKQTPSimplifyPolyLines ( const QList < QPolygonF > & lines_in , double maxDeltaXY = 1.0 ) ;
2022-08-25 21:17:50 +08:00
/*! \brief tries to reduce the complexity of the given poly-line \a lines_in, but keeping the appearance as if all lines were drawn
\ ingroup jkqtptools_drawing
\ param lines_in poly - line to be simplified
\ param maxDeltaXY a group has to be either less wide or less high than this , typically equals the linewidth of the poly - line
\ return a simplified version of lines_in
*/
2022-08-25 23:46:57 +08:00
JKQTCOMMON_LIB_EXPORT QPolygonF JKQTPSimplifyPolyLines ( const QPolygonF & lines_in , double maxDeltaXY = 1.0 ) ;
2022-08-25 21:17:50 +08:00
2019-05-30 04:40:02 +08:00
/*! \brief draw a tooltip, using the current brush and pen of the provided painter
\ ingroup jkqtptools_drawing
\ tparam TPainter Type of \ a painter : A class like JKQTPEnhancedPainter or < a href = " http://doc.qt.io/qt-5/qpainter.html " > QPainter < / a >
\ param painter QPainter - like object to use for painting
\ param x x - coordinate of position the tooltip points to
\ param y y - coordinate of position the tooltip points to
\ param rect rectangle of the main tooltip area
2020-08-23 19:30:20 +08:00
\ image html tooltiptool_example . png
2019-05-30 04:40:02 +08:00
*/
template < class TPainter >
inline void JKQTPDrawTooltip ( TPainter & painter , double x , double y , const QRectF & rect ) ;
template < class TPainter >
inline void JKQTPPlotSymbol ( TPainter & painter , double x , double y , JKQTPGraphSymbols symbol , double symbolSize , double symbolLineWidth , QColor color , QColor fillColor ) {
2022-08-25 21:17:50 +08:00
if ( symbol = = JKQTPNoSymbol ) return ;
2019-05-30 04:40:02 +08:00
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
QPen p = painter . pen ( ) ;
p . setColor ( color ) ;
p . setWidthF ( qMax ( JKQTPlotterDrawingTools : : ABS_MIN_LINEWIDTH , symbolLineWidth ) ) ;
p . setStyle ( Qt : : SolidLine ) ;
p . setCapStyle ( Qt : : FlatCap ) ;
painter . setPen ( p ) ;
QBrush b = painter . brush ( ) ;
b . setColor ( fillColor ) ;
b . setStyle ( Qt : : SolidPattern ) ;
const double w = symbolSize ;
const double w2 = w / 2.0 ;
2019-11-24 17:42:44 +08:00
const double w45 = fabs ( w * cos ( 45.0 / 180.0 * JKQTPSTATISTICS_PI ) ) ;
2019-05-30 04:40:02 +08:00
const double w3 = w / 3.0 ;
// calculate star cordinates as static values
static int star5_items = 0 ;
static double star5cordsx [ 10 ] ;
static double star5cordsy [ 10 ] ;
if ( star5_items = = 0 ) {
star5_items = 5 ;
2019-11-24 17:42:44 +08:00
double angle = 360.0 / double ( star5_items ) / 180.0 * JKQTPSTATISTICS_PI ;
2019-05-30 04:40:02 +08:00
for ( int i = 0 ; i < star5_items ; i + + ) {
double a = ( static_cast < double > ( i ) + 0.5 ) * angle ;
star5cordsx [ i * 2 ] = sin ( a ) ;
star5cordsx [ i * 2 + 1 ] = 0.5 * sin ( a + angle / 2.0 ) ;
star5cordsy [ i * 2 ] = cos ( a ) ;
star5cordsy [ i * 2 + 1 ] = 0.5 * cos ( a + angle / 2.0 ) ;
}
}
static int star6_items = 0 ;
static double star6cordsx [ 12 ] ;
static double star6cordsy [ 12 ] ;
if ( star6_items = = 0 ) {
star6_items = 6 ;
2019-11-24 17:42:44 +08:00
double angle = 360.0 / double ( star6_items ) / 180.0 * JKQTPSTATISTICS_PI ;
2019-05-30 04:40:02 +08:00
for ( int i = 0 ; i < star6_items ; i + + ) {
double a = ( static_cast < double > ( i ) + 0.5 ) * angle ;
star6cordsx [ i * 2 ] = sin ( a ) ;
star6cordsx [ i * 2 + 1 ] = 0.5 * sin ( a + angle / 2.0 ) ;
star6cordsy [ i * 2 ] = cos ( a ) ;
star6cordsy [ i * 2 + 1 ] = 0.5 * cos ( a + angle / 2.0 ) ;
}
}
static int star8_items = 0 ;
static double star8cordsx [ 16 ] ;
static double star8cordsy [ 16 ] ;
if ( star8_items = = 0 ) {
star8_items = 8 ;
2019-11-24 17:42:44 +08:00
double angle = 360.0 / double ( star8_items ) / 180.0 * JKQTPSTATISTICS_PI ;
2019-05-30 04:40:02 +08:00
for ( int i = 0 ; i < star8_items ; i + + ) {
double a = ( static_cast < double > ( i ) + 0.5 ) * angle ;
star8cordsx [ i * 2 ] = sin ( a ) ;
star8cordsx [ i * 2 + 1 ] = 0.5 * sin ( a + angle / 2.0 ) ;
star8cordsy [ i * 2 ] = cos ( a ) ;
star8cordsy [ i * 2 + 1 ] = 0.5 * cos ( a + angle / 2.0 ) ;
}
}
switch ( symbol ) {
case JKQTPDot :
painter . drawPoint ( QPointF ( x , y ) ) ;
break ;
case JKQTPCross : {
QPainterPath path ;
path . moveTo ( x - w2 , y - w2 ) ;
path . lineTo ( x + w2 , y + w2 ) ;
path . moveTo ( x - w2 , y + w2 ) ;
path . lineTo ( x + w2 , y - w2 ) ;
painter . drawPath ( path ) ;
}
break ;
case JKQTPPlus : {
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y + w2 ) ;
lines < < QLineF ( x - w2 , y , x + w2 , y ) ;
painter . drawLines ( lines ) ;
}
break ;
case JKQTPCircle : {
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawEllipse ( rectangle ) ;
}
break ;
case JKQTPCircleCross : {
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawEllipse ( rectangle ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x - w45 / 2.0 , y - w45 / 2.0 , x + w45 / 2.0 , y + w45 / 2.0 ) ;
lines < < QLineF ( x - w45 / 2.0 , y + w45 / 2.0 , x + w45 / 2.0 , y - w45 / 2.0 ) ;
painter . drawLines ( lines ) ;
}
break ;
case JKQTPCirclePlus : {
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawEllipse ( rectangle ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y + w2 ) ;
lines < < QLineF ( x - w2 , y , x + w2 , y ) ;
painter . drawLines ( lines ) ;
}
break ;
case JKQTPCirclePeace : {
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawEllipse ( rectangle ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y + w2 ) ;
lines < < QLineF ( x , y , x + w45 / 2.0 , y + w45 / 2.0 ) ;
lines < < QLineF ( x , y , x - w45 / 2.0 , y + w45 / 2.0 ) ;
painter . drawLines ( lines ) ;
}
break ;
case JKQTPPeace : {
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y + w2 ) ;
lines < < QLineF ( x , y , x + w45 / 2.0 , y + w45 / 2.0 ) ;
lines < < QLineF ( x , y , x - w45 / 2.0 , y + w45 / 2.0 ) ;
painter . drawLines ( lines ) ;
}
break ;
case JKQTPTarget : {
QPainterPath path ;
QRectF rectangle3 ( x - w3 , y - w3 , 2.0 * w3 , 2.0 * w3 ) ;
path . addEllipse ( rectangle3 ) ;
path . moveTo ( QPointF ( x , y - w2 ) ) ;
path . lineTo ( QPointF ( x , y + w2 ) ) ;
path . moveTo ( QPointF ( x - w2 , y ) ) ;
path . lineTo ( QPointF ( x + w2 , y ) ) ;
painter . drawPath ( path ) ;
}
break ;
case JKQTPFemale : {
QPainterPath path ;
QRectF rectangle3 ( x - w2 / 2.0 , y - w2 , w2 , w2 ) ;
path . addEllipse ( rectangle3 ) ;
path . moveTo ( QPointF ( x , y ) ) ;
path . lineTo ( QPointF ( x , y + w2 ) ) ;
path . moveTo ( QPointF ( x - w2 / 3.0 , y + w2 / 2.0 ) ) ;
path . lineTo ( QPointF ( x + w2 / 3.0 , y + w2 / 2.0 ) ) ;
painter . drawPath ( path ) ;
}
break ;
case JKQTPMale : {
QPainterPath path ;
QRectF rectangle3 ( x - w2 / 2.0 , y - w2 / 2.0 , w2 , w2 ) ;
path . addEllipse ( rectangle3 ) ;
2019-11-24 17:42:44 +08:00
path . moveTo ( QPointF ( x + w2 / 2.0 * cos ( 45.0 / 180.0 * JKQTPSTATISTICS_PI ) , y - w2 / 2.0 * cos ( 45.0 / 180.0 * JKQTPSTATISTICS_PI ) ) ) ;
2019-05-30 04:40:02 +08:00
path . lineTo ( QPointF ( x + w2 , y - w2 ) ) ;
path . moveTo ( QPointF ( x + w2 - w2 / 2.0 , y - w2 ) ) ;
path . lineTo ( QPointF ( x + w2 , y - w2 ) ) ;
path . lineTo ( QPointF ( x + w2 , y - w2 + w2 / 2.0 ) ) ;
painter . drawPath ( path ) ;
}
break ;
case JKQTPFilledCircle : {
painter . setBrush ( b ) ;
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawEllipse ( rectangle ) ;
}
break ;
case JKQTPRect : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawRect ( rectangle ) ;
}
break ;
case JKQTPRectCross : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPainterPath path ;
path . moveTo ( x - w2 , y - w2 ) ;
path . lineTo ( x + w2 , y + w2 ) ;
path . moveTo ( x - w2 , y + w2 ) ;
path . lineTo ( x + w2 , y - w2 ) ;
painter . drawPath ( path ) ;
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawRect ( rectangle ) ;
}
break ;
case JKQTPFilledCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . setBrush ( b ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPFilledDownCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( 180 ) ;
painter . setBrush ( b ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPDownCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( 180 ) ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPFilledLeftCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( - 90 ) ;
painter . setBrush ( b ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPLeftCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( - 90 ) ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPFilledRightCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( 90 ) ;
painter . setBrush ( b ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPRightCurvedTriangle : {
painter . save ( ) ;
painter . translate ( x , y ) ;
painter . rotate ( 90 ) ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPainterPath path ;
path . moveTo ( 0 , 0 - w2 ) ;
path . quadTo ( 0 - w / 10.0 , 0 + w / 4.0 , 0 - w2 , 0 + w2 ) ;
path . quadTo ( 0 , 0 + w / 4.0 , 0 + w2 , 0 + w2 ) ;
path . quadTo ( 0 + w / 10.0 , 0 + w / 4.0 , 0 , 0 - w2 ) ;
painter . drawPath ( path ) ;
painter . restore ( ) ;
}
break ;
case JKQTPRectTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x + w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
}
break ;
case JKQTPRectDownTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x , y + w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
}
break ;
case JKQTPRectLeftTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x - w2 , y ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x + w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
}
break ;
case JKQTPRectRightTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x - w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
}
break ;
case JKQTPRectPlus : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y + w2 ) ;
lines < < QLineF ( x - w2 , y , x + w2 , y ) ;
painter . drawLines ( lines ) ;
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawRect ( rectangle ) ;
}
break ;
case JKQTPFilledRect : {
painter . setBrush ( b ) ;
QRectF rectangle ( x - w2 , y - w2 , w , w ) ;
painter . drawRect ( rectangle ) ;
}
break ;
case JKQTPTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledTriangle : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPDownTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledDownTriangle : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPLeftTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledLeftTriangle : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPRightTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x - w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledRightTriangle : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x - w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPTripod : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x , y - w2 , x , y )
< < QLineF ( x , y , x - w45 , y + w45 )
< < QLineF ( x , y , x + w45 , y + w45 ) ;
painter . drawLines ( lines ) ;
} break ;
case JKQTPDownTripod : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x , y + w2 , x , y )
< < QLineF ( x , y , x - w45 , y - w45 )
< < QLineF ( x , y , x + w45 , y - w45 ) ;
painter . drawLines ( lines ) ;
} break ;
case JKQTPLeftTripod : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x - w2 , y , x , y )
< < QLineF ( x , y , x + w45 , y - w45 )
< < QLineF ( x , y , x + w45 , y + w45 ) ;
painter . drawLines ( lines ) ;
} break ;
case JKQTPRightTripod : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QVector < QLineF > lines ;
lines < < QLineF ( x + w2 , y , x , y )
< < QLineF ( x , y , x - w45 , y - w45 )
< < QLineF ( x , y , x - w45 , y + w45 ) ;
painter . drawLines ( lines ) ;
} break ;
case JKQTPUpDownTriangle : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x , y + w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x , y - w2 ) < < QPointF ( x - w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledUpDownTriangle : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x , y + w2 ) < < QPointF ( x + w2 , y - w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x , y - w2 ) < < QPointF ( x - w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPSantaClauseHouse : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w / 6.0 ) < < QPointF ( x - w2 , y - w / 6.0 ) < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y - w / 6.0 ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w / 6.0 ) < < QPointF ( x + w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledSantaClauseHouse : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w / 6.0 ) < < QPointF ( x - w2 , y - w / 6.0 ) < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y - w / 6.0 ) < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w / 6.0 ) < < QPointF ( x + w2 , y + w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPHourglass : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPHorizontalHourglass : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledHourglass : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledHorizontalHourglass : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x - w2 , y + w2 ) < < QPointF ( x - w2 , y - w2 ) < < QPointF ( x + w2 , y + w2 ) < < QPointF ( x + w2 , y - w2 ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPDiamond : {
QPolygonF poly ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
poly < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x , y + w2 ) < < QPointF ( x - w2 , y ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPDiamondPlus : {
QPolygonF poly ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
poly < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x , y + w2 ) < < QPointF ( x - w2 , y ) ;
painter . drawConvexPolygon ( poly ) ;
painter . drawLine ( poly [ 0 ] , poly [ 2 ] ) ;
painter . drawLine ( poly [ 1 ] , poly [ 3 ] ) ;
} break ;
case JKQTPDiamondCross : {
QPolygonF poly ;
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
poly < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x , y + w2 ) < < QPointF ( x - w2 , y ) ;
painter . drawConvexPolygon ( poly ) ;
painter . drawLine ( ( poly [ 0 ] + poly [ 1 ] ) / 2.0 , ( poly [ 2 ] + poly [ 3 ] ) / 2.0 ) ;
painter . drawLine ( ( poly [ 1 ] + poly [ 2 ] ) / 2.0 , ( poly [ 3 ] + poly [ 0 ] ) / 2.0 ) ;
} break ;
case JKQTPFilledDiamond : {
painter . setBrush ( b ) ;
QPolygonF poly ;
poly < < QPointF ( x , y - w2 ) < < QPointF ( x + w2 , y ) < < QPointF ( x , y + w2 ) < < QPointF ( x - w2 , y ) ;
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPstar : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star5_items * 2 ; i + + ) {
poly < < QPointF ( x + star5cordsx [ i ] * w2 , y + star5cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledStar : {
painter . setBrush ( b ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star5_items * 2 ; i + + ) {
poly < < QPointF ( x + star5cordsx [ i ] * w2 , y + star5cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPPentagon : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star5_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star5cordsx [ i ] * w2 , y + star5cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPHexagon : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star6_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star6cordsx [ i ] * w2 , y + star6cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPOctagon : {
painter . setBrush ( QColor ( Qt : : transparent ) ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star8_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star8cordsx [ i ] * w2 , y + star8cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPAsterisc : {
QPainterPath path ;
for ( int i = 0 ; i < star5_items * 2 ; i + = 2 ) {
path . moveTo ( x + star5cordsx [ i ] * w2 , y + star5cordsy [ i ] * w2 ) ;
path . lineTo ( x , y ) ;
}
painter . drawPath ( path ) ;
} break ;
case JKQTPAsterisc6 : {
QPainterPath path ;
for ( int i = 0 ; i < star6_items * 2 ; i + = 2 ) {
path . moveTo ( x + star6cordsx [ i ] * w2 , y + star6cordsy [ i ] * w2 ) ;
path . lineTo ( x , y ) ;
}
painter . drawPath ( path ) ;
} break ;
case JKQTPAsterisc8 : {
QPainterPath path ;
for ( int i = 0 ; i < star8_items * 2 ; i + = 2 ) {
path . moveTo ( x + star8cordsx [ i ] * w2 , y + star8cordsy [ i ] * w2 ) ;
path . lineTo ( x , y ) ;
}
painter . drawPath ( path ) ;
} break ;
case JKQTPFilledPentagon : {
painter . setBrush ( b ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star5_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star5cordsx [ i ] * w2 , y + star5cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledHexagon : {
painter . setBrush ( b ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star6_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star6cordsx [ i ] * w2 , y + star6cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
case JKQTPFilledOctagon : {
painter . setBrush ( b ) ;
QPolygonF poly ;
for ( int i = 0 ; i < star8_items * 2 ; i + = 2 ) {
poly < < QPointF ( x + star8cordsx [ i ] * w2 , y + star8cordsy [ i ] * w2 ) ;
}
painter . drawConvexPolygon ( poly ) ;
} break ;
default : break ;
}
}
template < class TPainter >
inline void JKQTPDrawTooltip ( TPainter & painter , double x , double y , const QRectF & rect )
{
QPolygonF poly ;
if ( y < rect . top ( ) ) {
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 ( ) ;
painter . drawPolygon ( poly ) ;
} else if ( y > rect . bottom ( ) ) {
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 ( ) ;
painter . drawPolygon ( poly ) ;
} else if ( x < rect . left ( ) ) {
poly < < QPointF ( x , y ) < < rect . topLeft ( ) < < rect . topRight ( ) < < rect . bottomRight ( ) < < rect . bottomLeft ( ) < < QPointF ( rect . left ( ) , rect . top ( ) + rect . height ( ) / 2 ) < < QPointF ( x , y ) ;
painter . drawPolygon ( poly ) ;
} else if ( x > rect . left ( ) ) {
poly < < rect . topLeft ( ) < < rect . topRight ( ) < < QPointF ( x , y ) < < QPointF ( rect . right ( ) , rect . top ( ) + rect . height ( ) / 2 ) < < rect . bottomRight ( ) < < rect . bottomLeft ( ) < < rect . topLeft ( ) ;
painter . drawPolygon ( poly ) ;
} else {
painter . drawRect ( rect ) ;
}
}
2020-08-22 00:31:58 +08:00
template < class TPainter >
inline void JKQTPPlotLineDecorator ( TPainter & painter , double x , double y , double angle_rad , JKQTPLineDecoratorStyle style , double size , QPointF * line_start ) {
if ( line_start ) * line_start = QPointF ( x , y ) ;
static double default_theta_open_tip = 60.0 / 2.0 / 180.0 * JKQTPSTATISTICS_PI ;
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 ) ;
2020-08-23 19:13:53 +08:00
QPen pinit = painter . pen ( ) ;
pinit . setCapStyle ( Qt : : FlatCap ) ;
pinit . setJoinStyle ( Qt : : RoundJoin ) ;
2020-08-22 00:31:58 +08:00
QPen p0 = pinit ;
p0 . setWidthF ( 0 ) ;
{
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . translate ( x , y ) ;
painter . rotate ( angle_rad / JKQTPSTATISTICS_PI * 180.0 ) ;
painter . setPen ( p0 ) ;
switch ( style ) {
case JKQTPArrow :
2020-08-23 19:13:53 +08:00
case JKQTPArrowAndBar : {
2020-08-22 00:31:58 +08:00
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 ) ;
2020-08-23 19:13:53 +08:00
if ( style = = JKQTPArrowAndBar ) painter . drawLine ( QPointF ( 0 , - tan__default_theta_open_tip * size ) , QPointF ( 0 , tan__default_theta_open_tip * size ) ) ;
2020-08-22 00:31:58 +08:00
painter . drawPolyline ( poly , 3 ) ;
} break ;
2020-08-23 19:13:53 +08:00
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 ;
2020-08-22 00:31:58 +08:00
case JKQTPDoubleArrow :
2020-08-23 19:13:53 +08:00
case JKQTPDoubleArrowAndBar : {
2020-08-22 00:31:58 +08:00
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 ) ;
2020-08-23 19:13:53 +08:00
if ( style = = JKQTPDoubleArrowAndBar ) painter . drawLine ( QPointF ( 0 , - tan__default_theta_open_tip * size ) , QPointF ( 0 , tan__default_theta_open_tip * size ) ) ;
2020-08-22 00:31:58 +08:00
painter . drawPolyline ( poly , 3 ) ;
painter . translate ( 4.0 * pinit . widthF ( ) , 0 ) ;
painter . drawPolyline ( poly , 3 ) ;
if ( line_start ) * line_start = QPointF ( x , y ) + QPointF ( 4.0 * pinit . widthF ( ) * cos ( angle_rad ) , 4.0 * pinit . widthF ( ) * sin ( angle_rad ) ) ;
} break ;
case JKQTPFilledArrow :
case JKQTPFilledDoubleArrow : {
const QPointF poly [ 4 ] = {
QPointF ( 0 , 0 ) ,
QPointF ( size , tan__default_theta_closed_tip * size ) ,
QPointF ( 0.75 * size , 0 ) ,
QPointF ( size , - tan__default_theta_closed_tip * size )
} ;
painter . drawPolygon ( poly , 4 ) ;
if ( style = = JKQTPFilledDoubleArrow ) {
2020-08-23 19:13:53 +08:00
painter . translate ( 0.5 * size , 0 ) ;
2020-08-22 00:31:58 +08:00
painter . drawPolygon ( poly , 4 ) ;
2020-08-23 19:13:53 +08:00
if ( line_start ) * line_start = QPointF ( x , y ) + QPointF ( 1.25 * size * cos ( angle_rad ) , 1.25 * size * sin ( angle_rad ) ) ;
2020-08-22 00:31:58 +08:00
} 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 :
2020-08-23 19:13:53 +08:00
case JKQTPTriangleDecoratorAndBar : {
2020-08-22 00:31:58 +08:00
const QPointF poly [ 3 ] = {
QPointF ( size , - tan__default_theta_closed_tip * size ) ,
QPointF ( 0 , 0 ) ,
QPointF ( size , tan__default_theta_closed_tip * size )
} ;
painter . setBrush ( Qt : : NoBrush ) ;
painter . setPen ( pinit ) ;
painter . drawConvexPolygon ( poly , 3 ) ;
2020-08-23 19:13:53 +08:00
if ( style = = JKQTPTriangleDecoratorAndBar ) painter . drawLine ( QPointF ( 0 , - tan__default_theta_closed_tip * size ) , QPointF ( 0 , tan__default_theta_closed_tip * size ) ) ;
2020-08-22 00:31:58 +08:00
if ( line_start ) * line_start = QPointF ( x , y ) + QPointF ( size * cos ( angle_rad ) , size * sin ( angle_rad ) ) ;
} break ;
case JKQTPFilledTriangleDecorator :
2020-08-23 19:13:53 +08:00
case JKQTPFilledTriangleDecoratorAndBar : {
2020-08-22 00:31:58 +08:00
const QPointF poly [ 3 ] = {
QPointF ( size , - tan__default_theta_closed_tip * size ) ,
QPointF ( 0 , 0 ) ,
QPointF ( size , tan__default_theta_closed_tip * size )
} ;
painter . setPen ( p0 ) ;
painter . drawConvexPolygon ( poly , 3 ) ;
2020-08-23 19:13:53 +08:00
if ( style = = JKQTPFilledTriangleDecoratorAndBar ) {
2020-08-22 00:31:58 +08:00
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 ;
2020-08-23 19:13:53 +08:00
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 ;
2020-08-22 00:31:58 +08:00
2020-08-23 19:13:53 +08:00
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 ;
2020-08-22 00:31:58 +08:00
case JKQTPCircleDecorator :
case JKQTPFilledCircleDecorator : {
if ( style = = JKQTPCircleDecorator ) {
painter . setBrush ( Qt : : NoBrush ) ;
painter . setPen ( pinit ) ;
} else {
painter . setPen ( p0 ) ;
}
2020-08-23 19:13:53 +08:00
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 ) ) ;
2020-08-22 00:31:58 +08:00
} break ;
case JKQTPRectangleDecorator :
case JKQTPFilledRectangleDecorator : {
if ( style = = JKQTPRectangleDecorator ) {
painter . setBrush ( Qt : : NoBrush ) ;
painter . setPen ( pinit ) ;
} else {
painter . setPen ( p0 ) ;
}
2020-08-23 19:13:53 +08:00
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 ) ) ;
2020-08-22 00:31:58 +08:00
} break ;
2020-08-23 19:13:53 +08:00
case JKQTPBarDecorator : {
2020-08-22 00:31:58 +08:00
painter . setPen ( pinit ) ;
painter . drawLine ( QPointF ( 0 , - tan__default_theta_open_tip * size ) , QPointF ( 0 , tan__default_theta_open_tip * size ) ) ;
} break ;
2020-08-23 19:13:53 +08:00
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 ;
2020-08-22 00:31:58 +08:00
case JKQTPBracketDecorator : {
const QPointF poly [ 4 ] = {
QPointF ( - size * 0.2 , - tan__default_theta_open_tip * size ) ,
QPointF ( 0 , - tan__default_theta_open_tip * size ) ,
QPointF ( 0 , tan__default_theta_open_tip * size ) ,
QPointF ( - size * 0.2 , tan__default_theta_open_tip * size )
} ;
painter . setPen ( pinit ) ;
painter . drawPolyline ( poly , 4 ) ;
} break ;
2020-08-22 00:40:30 +08:00
case JKQTPLineDecoratorCount :
case JKQTPNoDecorator :
break ;
2020-08-22 00:31:58 +08:00
}
}
}
2019-05-30 04:40:02 +08:00
# endif // JKQTPDRAWINGTOOLS_H_INCLUDED