2020-08-26 16:36:07 +08:00
/*
2024-02-06 21:50:49 +08:00
Copyright ( c ) 2008 - 2024 Jan W . Krieger ( < jan @ jkrieger . de > )
2020-08-26 16:36:07 +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 ( LGPL ) as published by
the Free Software Foundation , either version 2.1 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Lesser General Public License ( LGPL ) for more details .
You should have received a copy of the GNU Lesser General Public License ( LGPL )
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "jkqtplotter/graphs/jkqtpgeolines.h"
# include "jkqtplotter/jkqtpbaseplotter.h"
# include "jkqtplotter/jkqtplotter.h"
- 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 "jkqtcommon/jkqtpgeometrytools.h"
2020-08-26 16:36:07 +08:00
# include <stdlib.h>
# include <QDebug>
# include <QApplication>
# define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
- 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
JKQTPGeoLine : : JKQTPGeoLine ( JKQTBasePlotter * parent , double x1_ , double y1_ , double x2_ , double y2_ ) :
JKQTPGeoBaseDecoratedLine ( parent ) , x1 ( x1_ ) , y1 ( y1_ ) , x2 ( x2_ ) , y2 ( y2_ )
2020-08-26 16:36:07 +08:00
{
setHeadDecoratorStyle ( JKQTPNoDecorator ) ;
setTailDecoratorStyle ( JKQTPNoDecorator ) ;
}
JKQTPGeoLine : : JKQTPGeoLine ( JKQTPlotter * parent , double x1 , double y1 , double x2 , double y2 ) :
JKQTPGeoLine ( parent - > getPlotter ( ) , x1 , y1 , x2 , y2 )
{
}
- 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
JKQTPGeoLine : : JKQTPGeoLine ( JKQTBasePlotter * parent , const QPointF & p1 , const QPointF & p2 ) :
JKQTPGeoLine ( parent , p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) )
{
}
JKQTPGeoLine : : JKQTPGeoLine ( JKQTPlotter * parent , const QPointF & p1 , const QPointF & p2 ) :
JKQTPGeoLine ( parent , p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) )
{
}
JKQTPGeoLine : : JKQTPGeoLine ( JKQTBasePlotter * parent , const QLineF & line ) :
JKQTPGeoLine ( parent , line . x1 ( ) , line . y1 ( ) , line . x2 ( ) , line . y2 ( ) )
{
}
JKQTPGeoLine : : JKQTPGeoLine ( JKQTPlotter * parent , const QLineF & line ) :
JKQTPGeoLine ( parent , line . x1 ( ) , line . y1 ( ) , line . x2 ( ) , line . y2 ( ) )
{
}
2020-08-26 16:36:07 +08:00
bool JKQTPGeoLine : : getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) {
minx = qMin ( x1 , x2 ) ;
maxx = qMax ( x1 , x2 ) ;
smallestGreaterZero = 0 ;
double xvsgz ;
xvsgz = x1 ; SmallestGreaterZeroCompare_xvsgz ( ) ;
xvsgz = x2 ; SmallestGreaterZeroCompare_xvsgz ( ) ;
return true ;
}
bool JKQTPGeoLine : : getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) {
miny = qMin ( y1 , y2 ) ;
maxy = qMax ( y1 , y2 ) ;
smallestGreaterZero = 0 ;
double xvsgz ;
xvsgz = y1 ; SmallestGreaterZeroCompare_xvsgz ( ) ;
xvsgz = y2 ; SmallestGreaterZeroCompare_xvsgz ( ) ;
return true ;
}
void JKQTPGeoLine : : draw ( JKQTPEnhancedPainter & painter ) {
clearHitTestData ( ) ;
reserveHitTestData ( 2 ) ;
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . setPen ( getLinePen ( painter , parent ) ) ;
painter . setBrush ( getLineColor ( ) ) ;
QPointF xx1 ( transformX ( x1 ) , transformY ( y1 ) ) ;
QPointF xx2 ( transformX ( x2 ) , transformY ( y2 ) ) ;
if ( QLineF ( xx1 , xx2 ) . length ( ) > 0 ) {
- 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
2023-03-23 20:55:18 +08:00
if ( ( getDrawMode ( ) = = DrawAsGraphicElement ) | | ( getXAxis ( ) - > isLinearAxis ( ) & & getYAxis ( ) - > isLinearAxis ( ) ) ) {
- 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
// for linear axes, we can simply draw a line
const double angle1 = atan2 ( xx2 . y ( ) - xx1 . y ( ) , xx2 . x ( ) - xx1 . x ( ) ) ;
const double angle2 = atan2 ( xx1 . y ( ) - xx2 . y ( ) , xx1 . x ( ) - xx2 . x ( ) ) ;
QPointF lx1 = xx1 , lx2 = xx2 ;
JKQTPPlotLineDecorator ( painter , xx1 . x ( ) , xx1 . y ( ) , angle1 , getTailDecoratorStyle ( ) , calcTailDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) , & lx1 ) ;
JKQTPPlotLineDecorator ( painter , xx2 . x ( ) , xx2 . y ( ) , angle2 , getHeadDecoratorStyle ( ) , calcHeadDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) , & lx2 ) ;
// draw corrected line
painter . drawLine ( QLineF ( lx1 , lx2 ) ) ;
} else {
QLineF line ( QPointF ( x1 , y1 ) , QPointF ( x2 , y2 ) ) ;
2023-03-23 20:55:18 +08:00
const double xmin = getXAxis ( ) - > getMin ( ) ;
const double xmax = getXAxis ( ) - > getMax ( ) ;
const double ymin = getYAxis ( ) - > getMin ( ) ;
const double ymax = getYAxis ( ) - > getMax ( ) ;
- 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
const QRectF bbox ( QPointF ( xmin , ymin ) , QPointF ( xmax , ymax ) ) ;
bool drawHead = bbox . contains ( line . p2 ( ) ) ;
bool drawTail = bbox . contains ( line . p1 ( ) ) ;
if ( JKQTPClipLine ( line , bbox ) ) {
// for non-linear axes, a line might not be drawn as a line, so we need to segment the line (i.e. linear function in coordinate space)
// and transform each node to draw the corresponding non-linear curve in pixel-space!
2020-09-21 19:15:57 +08:00
auto fTransform = std : : bind ( [ ] ( const JKQTPGeometricPlotElement * plot , const QPointF & p ) { return plot - > transform ( p ) ; } , this , std : : placeholders : : _1 ) ;
- 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
QVector < QPointF > points = JKQTPSplitLineIntoPoints ( line , fTransform ) ;
points = JKQTPSimplyfyLineSegemnts ( points ) ;
if ( points . size ( ) > 1 ) {
xx1 = points [ 0 ] ;
QPointF xx1p = points [ 1 ] ;
xx2 = points [ points . size ( ) - 1 ] ;
QPointF xx2p = points [ points . size ( ) - 2 ] ;
//QPointF lx1=xx1, lx2=xx2;
const double angle1 = atan2 ( xx1p . y ( ) - xx1 . y ( ) , xx1p . x ( ) - xx1 . x ( ) ) ;
const double angle2 = atan2 ( xx2p . y ( ) - xx2 . y ( ) , xx2p . x ( ) - xx2 . x ( ) ) ;
if ( drawTail ) JKQTPPlotLineDecorator ( painter , xx1 . x ( ) , xx1 . y ( ) , angle1 , getTailDecoratorStyle ( ) , calcTailDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ; //, &lx1);
if ( drawHead ) JKQTPPlotLineDecorator ( painter , xx2 . x ( ) , xx2 . y ( ) , angle2 , getHeadDecoratorStyle ( ) , calcHeadDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ; //, &lx2);
//points[0]=lx1;
//points[points.size()-1]=lx2;
2022-08-31 04:24:24 +08:00
painter . drawPolylineFast ( points . data ( ) , points . size ( ) ) ;
- 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
}
}
}
2020-08-26 16:36:07 +08:00
addHitTestData ( x1 , y1 ) ;
addHitTestData ( x2 , y2 ) ;
}
}
void JKQTPGeoLine : : setX1 ( double __value )
{
this - > x1 = __value ;
}
double JKQTPGeoLine : : getX1 ( ) const
{
return this - > x1 ;
}
void JKQTPGeoLine : : setY1 ( double __value )
{
this - > y1 = __value ;
}
double JKQTPGeoLine : : getY1 ( ) const
{
return this - > y1 ;
}
void JKQTPGeoLine : : setX2 ( double __value )
{
this - > x2 = __value ;
}
double JKQTPGeoLine : : getX2 ( ) const
{
return this - > x2 ;
}
void JKQTPGeoLine : : setY2 ( double __value )
{
this - > y2 = __value ;
}
double JKQTPGeoLine : : getY2 ( ) const
{
return this - > y2 ;
}
- 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
QPointF JKQTPGeoLine : : getP1 ( ) const
{
return QPointF ( x1 , y1 ) ;
}
void JKQTPGeoLine : : setP1 ( const QPointF & p )
{
x1 = p . x ( ) ;
y1 = p . y ( ) ;
}
QPointF JKQTPGeoLine : : getP2 ( ) const
{
return QPointF ( x2 , y2 ) ;
}
void JKQTPGeoLine : : setP2 ( const QPointF & p )
{
x2 = p . x ( ) ;
y2 = p . y ( ) ;
}
QLineF JKQTPGeoLine : : getLine ( ) const
{
return QLineF ( getP1 ( ) , getP2 ( ) ) ;
}
void JKQTPGeoLine : : setLine ( const QLineF & line )
{
x1 = line . p1 ( ) . x ( ) ;
x2 = line . p2 ( ) . x ( ) ;
y1 = line . p1 ( ) . y ( ) ;
y2 = line . p2 ( ) . y ( ) ;
}
2020-08-26 16:36:07 +08:00
2020-09-26 21:58:58 +08:00
JKQTPGeoArrow : : JKQTPGeoArrow ( JKQTBasePlotter * parent , double x1 , double y1 , double x2 , double y2 , JKQTPLineDecoratorStyle headStyle , JKQTPLineDecoratorStyle tailStyle ) :
JKQTPGeoLine ( parent , x1 , y1 , x2 , y2 )
2020-08-26 16:36:07 +08:00
{
setHeadDecoratorStyle ( headStyle ) ;
setTailDecoratorStyle ( tailStyle ) ;
}
2020-09-26 21:58:58 +08:00
JKQTPGeoArrow : : JKQTPGeoArrow ( JKQTPlotter * parent , double x1 , double y1 , double x2 , double y2 , JKQTPLineDecoratorStyle headStyle , JKQTPLineDecoratorStyle tailStyle ) :
JKQTPGeoArrow ( parent - > getPlotter ( ) , x1 , y1 , x2 , y2 , headStyle , tailStyle )
2020-08-26 16:36:07 +08:00
{
}
2023-07-22 01:32:47 +08:00
JKQTPGeoArrow : : JKQTPGeoArrow ( JKQTBasePlotter * parent , const QPointF & p1 , const QPointF & p2 , JKQTPLineDecoratorStyle headStyle , JKQTPLineDecoratorStyle tailStyle ) :
JKQTPGeoArrow ( parent , p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) , headStyle , tailStyle )
{
}
JKQTPGeoArrow : : JKQTPGeoArrow ( JKQTPlotter * parent , const QPointF & p1 , const QPointF & p2 , JKQTPLineDecoratorStyle headStyle , JKQTPLineDecoratorStyle tailStyle ) :
JKQTPGeoArrow ( parent - > getPlotter ( ) , p1 . x ( ) , p1 . y ( ) , p2 . x ( ) , p2 . y ( ) , headStyle , tailStyle )
{
}
2020-08-26 16:36:07 +08:00
2020-09-26 21:58:58 +08:00
JKQTPGeoInfiniteLine : : JKQTPGeoInfiniteLine ( JKQTBasePlotter * parent , double x , double y , double dx , double dy ) :
JKQTPGeoBaseDecoratedHeadLine ( parent )
2020-08-26 16:36:07 +08:00
{
this - > x = x ;
this - > y = y ;
this - > dx = dx ;
this - > dy = dy ;
this - > two_sided = false ;
}
2020-09-26 21:58:58 +08:00
JKQTPGeoInfiniteLine : : JKQTPGeoInfiniteLine ( JKQTPlotter * parent , double x , double y , double dx , double dy ) :
JKQTPGeoInfiniteLine ( parent - > getPlotter ( ) , x , y , dx , dy )
2020-08-26 16:36:07 +08:00
{
}
bool JKQTPGeoInfiniteLine : : getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) {
minx = x ;
maxx = x ;
smallestGreaterZero = 0 ;
if ( x > 10.0 * DBL_MIN ) smallestGreaterZero = x ;
return true ;
}
bool JKQTPGeoInfiniteLine : : getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) {
miny = y ;
maxy = y ;
smallestGreaterZero = 0 ;
if ( y > 10.0 * DBL_MIN ) smallestGreaterZero = y ;
return true ;
}
void JKQTPGeoInfiniteLine : : draw ( JKQTPEnhancedPainter & painter ) {
clearHitTestData ( ) ;
reserveHitTestData ( 2 ) ;
2023-03-23 20:55:18 +08:00
double xmin = getXAxis ( ) - > getMin ( ) ;
double xmax = getXAxis ( ) - > getMax ( ) ;
double ymin = getYAxis ( ) - > getMin ( ) ;
double ymax = getYAxis ( ) - > getMax ( ) ;
2020-08-26 16:36:07 +08:00
QRectF bbox ( QPointF ( xmin , ymin ) , QPointF ( xmax , ymax ) ) ;
bool doDraw = false ;
double x2 = x , y2 = y ;
double x1 = x , y1 = y ;
// normalize lengh of direction
double dl = sqrt ( dx * dx + dy * dy ) ;
dx = dx / dl ;
dy = dy / dl ;
// first catch cases where we are parallel to one coordinate axis
if ( dy = = 0 ) {
doDraw = ( ( y > = ymin ) & & ( y < = ymax ) ) ;
x1 = xmin ;
x2 = xmax ;
if ( ! two_sided ) {
if ( ( dx > 0 ) & & ( x > xmin ) ) {
x1 = x ;
} else if ( ( dx < 0 ) & & ( x < xmax ) ) {
x2 = x ;
}
}
} else if ( dx = = 0 ) {
doDraw = ( ( x > = xmin ) & & ( x < = xmax ) ) ;
y1 = ymin ;
y2 = ymax ;
if ( ! two_sided ) {
if ( ( dy > 0 ) & & ( y > ymin ) ) {
y1 = y ;
} else if ( ( dy < 0 ) & & ( y < ymax ) ) {
y2 = y ;
}
}
} else {
// first we find intersection points of line and y=ymin, as well as y=ymax
double tymin = ( ymin - y ) / dy ;
double xymin = x + tymin * dx ;
double tymax = ( ymax - y ) / dy ;
double xymax = x + tymax * dx ;
double t1 = 0 , t2 = 0 ;
if ( ( xymin > xmin ) & & ( xymin < xmax ) ) {
// (xymin,ymin) is on the rectangle circumference => use it
t1 = tymin ;
if ( two_sided ) {
doDraw = true ;
} else if ( t1 > 0 ) {
doDraw = true ;
} else {
t1 = 0 ;
}
} else if ( xymin < xmin ) {
//(xymin,ymin) is on the left, next to the rectangle, so we have to intersect with x=xmin
t1 = ( xmin - x ) / dx ;
if ( two_sided ) {
doDraw = true ;
} else if ( t1 > 0 ) {
doDraw = true ;
} else {
t1 = 0 ;
}
} else if ( xymin > xmax ) {
//(xymin,ymin) is on the right, next to the rectangle, so we have to intersect with x=xmax
t1 = ( xmax - x ) / dx ;
if ( two_sided ) {
doDraw = true ;
} else if ( t1 > 0 ) {
doDraw = true ;
} else {
t1 = 0 ;
}
}
if ( ( xymax > xmin ) & & ( xymax < xmax ) ) {
// (xymax,ymin) is on the rectangle circumference => use it
t2 = tymax ;
if ( two_sided ) {
doDraw = true ;
} else if ( t2 > 0 ) {
doDraw = true ;
} else {
t2 = 0 ;
}
} else if ( xymax < xmin ) {
//(xymax,ymax) is on the left, next to the rectangle, so we have to intersect with x=xmin
t2 = ( xmin - x ) / dx ;
if ( two_sided ) {
doDraw = true ;
} else if ( t2 > 0 ) {
doDraw = true ;
} else {
t2 = 0 ;
}
} else if ( xymax > xmax ) {
//(xymax,ymax) is on the right, next to the rectangle, so we have to intersect with x=xmax
t2 = ( xmax - x ) / dx ;
if ( two_sided ) {
doDraw = true ;
} else if ( t2 > 0 ) {
doDraw = true ;
} else {
t2 = 0 ;
}
}
x1 = x + t1 * dx ;
y1 = y + t1 * dy ;
x2 = x + t2 * dx ;
y2 = y + t2 * dy ;
}
if ( doDraw ) {
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . setPen ( getLinePen ( painter , parent ) ) ;
- 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
QLineF line ( QPointF ( transformX ( x1 ) , transformY ( y1 ) ) , QPointF ( transformX ( x2 ) , transformY ( y2 ) ) ) ;
if ( line . length ( ) > 0 ) {
QPointF xx1 ;
2022-07-22 04:17:37 +08:00
double angle1 = 0 ;
2023-03-23 20:55:18 +08:00
if ( ( getDrawMode ( ) = = DrawAsGraphicElement ) | | ( getXAxis ( ) - > isLinearAxis ( ) & & getYAxis ( ) - > isLinearAxis ( ) ) ) {
- 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
painter . drawLine ( line ) ;
xx1 = QPointF ( transformX ( x ) , transformY ( y ) ) ;
angle1 = atan2 ( line . dy ( ) , line . dx ( ) ) ;
} else {
// for non-linear axes, a line might not be drawn as a line, so we need to segment the line (i.e. linear function in coordinate space)
// and transform each node to draw the corresponding non-linear curve in pixel-space!
2020-09-21 19:15:57 +08:00
auto fTransform = std : : bind ( [ ] ( const JKQTPGeometricPlotElement * plot , const QPointF & p ) { return plot - > transform ( p ) ; } , this , std : : placeholders : : _1 ) ;
- 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
QVector < QPointF > points = JKQTPSplitLineIntoPoints ( QLineF ( x1 , y1 , x2 , y2 ) , fTransform ) ;
points = JKQTPSimplyfyLineSegemnts ( points ) ;
if ( points . size ( ) > 1 ) {
xx1 = points [ 0 ] ;
const QPointF xx1p = points [ 1 ] ;
angle1 = atan2 ( xx1p . y ( ) - xx1 . y ( ) , xx1p . x ( ) - xx1 . x ( ) ) ;
2022-08-31 04:24:24 +08:00
painter . drawPolylineFast ( points . data ( ) , points . size ( ) ) ;
- 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
}
}
2020-08-26 16:36:07 +08:00
- 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
// draw line-end decorator
2020-08-26 16:36:07 +08:00
if ( two_sided = = false & & x > = xmin & & x < = xmax & & y > = ymin & & y < = ymax ) {
2020-08-26 17:00:25 +08:00
painter . save ( ) ; auto __finalpainttwosided = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
2020-08-26 16:36:07 +08:00
painter . setPen ( getLinePen ( painter , parent ) ) ;
painter . setBrush ( getLineColor ( ) ) ;
JKQTPPlotLineDecorator ( painter , xx1 . x ( ) , xx1 . y ( ) , angle1 , getHeadDecoratorStyle ( ) , calcHeadDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ;
}
- 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
addHitTestData ( x , y , formatHitTestDefaultLabel ( x , y ) +
2024-02-14 20:57:16 +08:00
QString ( " , \\ ensuremath{ \\ mathrm{ \\ mathbf{d}}y/ \\ mathrm{ \\ mathbf{d}}x \\ ;= \\ ;%1/%2 \\ ;= \\ ;%3 \\ ;= \\ ;%4 \\ degree} " ) . arg ( yFloatToString ( dy ) ) . arg ( xFloatToString ( dx ) ) . arg ( jkqtp_floattolatexqstr ( dy / dx , 3 ) ) . arg ( jkqtp_floattolatexqstr ( atan2 ( dy , dx ) , 1 ) ) ) ;
- 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
addHitTestData ( x1 , y1 ) ;
addHitTestData ( x2 , y2 ) ;
2020-08-26 16:36:07 +08:00
}
}
}
void JKQTPGeoInfiniteLine : : setX ( double __value )
{
this - > x = __value ;
}
double JKQTPGeoInfiniteLine : : getX ( ) const
{
return this - > x ;
}
void JKQTPGeoInfiniteLine : : setY ( double __value )
{
this - > y = __value ;
}
double JKQTPGeoInfiniteLine : : getY ( ) const
{
return this - > y ;
}
void JKQTPGeoInfiniteLine : : setDx ( double __value )
{
this - > dx = __value ;
}
double JKQTPGeoInfiniteLine : : getDx ( ) const
{
return this - > dx ;
}
void JKQTPGeoInfiniteLine : : setDy ( double __value )
{
this - > dy = __value ;
}
double JKQTPGeoInfiniteLine : : getDy ( ) const
{
return this - > dy ;
}
void JKQTPGeoInfiniteLine : : setTwoSided ( bool __value )
{
this - > two_sided = __value ;
}
bool JKQTPGeoInfiniteLine : : getTwoSided ( ) const
{
return this - > two_sided ;
}
- 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
QPointF JKQTPGeoInfiniteLine : : getP ( ) const
{
return QPointF ( x , y ) ;
}
void JKQTPGeoInfiniteLine : : setP ( const QPointF & p )
{
x = p . x ( ) ;
y = p . y ( ) ;
}
2020-08-26 16:36:07 +08:00
2020-09-26 21:58:58 +08:00
JKQTPGeoPolyLines : : JKQTPGeoPolyLines ( JKQTBasePlotter * parent , const QVector < QPointF > & points ) :
JKQTPGeoBaseDecoratedLine ( parent )
2020-08-26 16:36:07 +08:00
{
this - > points = points ;
2024-02-14 06:49:23 +08:00
setHeadDecoratorStyle ( JKQTPNoDecorator ) ;
setTailDecoratorStyle ( JKQTPNoDecorator ) ;
2020-08-26 16:36:07 +08:00
}
2020-09-26 21:58:58 +08:00
JKQTPGeoPolyLines : : JKQTPGeoPolyLines ( JKQTPlotter * parent , const QVector < QPointF > & points ) :
JKQTPGeoPolyLines ( parent - > getPlotter ( ) , points )
2020-08-26 16:36:07 +08:00
{
}
2020-09-26 21:58:58 +08:00
JKQTPGeoPolyLines : : JKQTPGeoPolyLines ( JKQTBasePlotter * parent ) :
JKQTPGeoBaseDecoratedLine ( parent )
2020-08-26 16:36:07 +08:00
{
}
2020-09-26 21:58:58 +08:00
JKQTPGeoPolyLines : : JKQTPGeoPolyLines ( JKQTPlotter * parent ) :
JKQTPGeoPolyLines ( parent - > getPlotter ( ) )
2020-08-26 16:36:07 +08:00
{
}
bool JKQTPGeoPolyLines : : getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) {
minx = 0 ;
maxx = 0 ;
smallestGreaterZero = 0 ;
if ( points . size ( ) > 0 ) {
minx = points [ 0 ] . x ( ) ;
maxx = points [ 0 ] . x ( ) ;
for ( int i = 1 ; i < points . size ( ) ; i + + ) {
double x = points [ i ] . x ( ) ;
if ( x > maxx ) maxx = x ;
if ( x < minx ) minx = x ;
double xvsgz ;
xvsgz = x ; SmallestGreaterZeroCompare_xvsgz ( ) ;
}
return true ;
}
return false ;
//qDebug()<<"getXMinMax"<<minx<<maxx;
}
bool JKQTPGeoPolyLines : : getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) {
miny = 0 ;
maxy = 0 ;
smallestGreaterZero = 0 ;
if ( points . size ( ) > 0 ) {
miny = points [ 0 ] . y ( ) ;
maxy = points [ 0 ] . y ( ) ;
for ( int i = 1 ; i < points . size ( ) ; i + + ) {
double y = points [ i ] . y ( ) ;
if ( y > maxy ) maxy = y ;
if ( y < miny ) miny = y ;
double xvsgz ;
xvsgz = y ; SmallestGreaterZeroCompare_xvsgz ( ) ;
}
return true ;
}
return false ;
//qDebug()<<"getYMinMax"<<miny<<maxy;
}
void JKQTPGeoPolyLines : : draw ( JKQTPEnhancedPainter & painter ) {
clearHitTestData ( ) ;
if ( points . size ( ) > = 2 ) {
reserveHitTestData ( points . size ( ) ) ;
2024-02-14 20:57:16 +08:00
double angle1 = 0 , angle2 = 0 ;
- 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
QPointF xx1 , xx2 ;
bool doDrawDecorator = false ;
2020-08-26 16:36:07 +08:00
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . setPen ( getLinePen ( painter , parent ) ) ;
painter . setBrush ( getLineColor ( ) ) ;
2023-03-23 20:55:18 +08:00
if ( ( getDrawMode ( ) = = DrawAsGraphicElement ) | | ( getXAxis ( ) - > isLinearAxis ( ) & & getYAxis ( ) - > isLinearAxis ( ) ) ) {
- 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
QVector < QPointF > path = transform ( points ) ;
angle1 = atan2 ( path [ 1 ] . y ( ) - path [ 0 ] . y ( ) , path [ 1 ] . x ( ) - path [ 0 ] . x ( ) ) ;
angle2 = atan2 ( path [ path . size ( ) - 2 ] . y ( ) - path [ path . size ( ) - 1 ] . y ( ) , path [ path . size ( ) - 2 ] . x ( ) - path [ path . size ( ) - 1 ] . x ( ) ) ;
xx1 = path [ 0 ] ;
xx2 = path [ path . size ( ) - 1 ] ;
// draw corrected line
2022-08-31 04:24:24 +08:00
painter . drawPolylineFast ( path . data ( ) , path . size ( ) ) ;
- 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
doDrawDecorator = true ;
} else {
// for non-linear axes, a line might not be drawn as a line, so we need to segment the line (i.e. linear function in coordinate space)
// and transform each node to draw the corresponding non-linear curve in pixel-space!
2020-09-21 19:15:57 +08:00
auto fTransform = std : : bind ( [ ] ( const JKQTPGeometricPlotElement * plot , const QPointF & p ) { return plot - > transform ( p ) ; } , this , std : : placeholders : : _1 ) ;
- 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
QVector < QPointF > points_poly = JKQTPSplitPolylineIntoPoints ( points , fTransform ) ;
points_poly = JKQTPSimplyfyLineSegemnts ( points_poly ) ;
if ( points_poly . size ( ) > 1 ) {
xx1 = points_poly [ 0 ] ;
const QPointF xx1p = points_poly [ 1 ] ;
angle1 = atan2 ( xx1p . y ( ) - xx1 . y ( ) , xx1p . x ( ) - xx1 . x ( ) ) ;
xx2 = points_poly [ points_poly . size ( ) - 1 ] ;
const QPointF xx2p = points_poly [ points_poly . size ( ) - 2 ] ;
angle2 = atan2 ( xx2p . y ( ) - xx2 . y ( ) , xx2p . x ( ) - xx2 . x ( ) ) ;
2022-08-31 04:24:24 +08:00
painter . drawPolylineFast ( points_poly . data ( ) , points_poly . size ( ) ) ;
- 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
doDrawDecorator = true ;
}
}
2020-08-26 16:36:07 +08:00
// potentially draw line-end decorators/arrows
- 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
if ( doDrawDecorator ) {
JKQTPPlotLineDecorator ( painter , xx1 . x ( ) , xx1 . y ( ) , angle1 , getTailDecoratorStyle ( ) , calcTailDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ;
JKQTPPlotLineDecorator ( painter , xx2 . x ( ) , xx2 . y ( ) , angle2 , getHeadDecoratorStyle ( ) , calcHeadDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ;
}
2020-08-26 16:36:07 +08:00
for ( const auto & p : points ) {
addHitTestData ( p . x ( ) , p . y ( ) ) ;
}
}
}
void JKQTPGeoPolyLines : : setPoints ( const QVector < QPointF > & __value )
{
this - > points = __value ;
}
QVector < QPointF > JKQTPGeoPolyLines : : getPoints ( ) const
{
return this - > points ;
}
void JKQTPGeoPolyLines : : appendPoint ( const QPointF & p ) {
points . append ( p ) ;
}
void JKQTPGeoPolyLines : : appendPoint ( const double x , const double y ) {
points . append ( QPointF ( x , y ) ) ;
}
- 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
int JKQTPGeoPolyLines : : getPointCount ( ) const
{
return points . size ( ) ;
}
const QPointF & JKQTPGeoPolyLines : : getPoint ( int i ) const
{
return points [ i ] ;
}
QPointF & JKQTPGeoPolyLines : : getPoint ( int i )
{
return points [ i ] ;
}
void JKQTPGeoPolyLines : : setPoint ( int i , const QPointF & point )
{
points [ i ] = point ;
}
void JKQTPGeoPolyLines : : removePoint ( int i )
{
points . remove ( i ) ;
}
QVector < QPointF > : : iterator JKQTPGeoPolyLines : : pointsBegin ( )
{
return points . begin ( ) ;
}
QVector < QPointF > : : iterator JKQTPGeoPolyLines : : pointsEnd ( )
{
return points . end ( ) ;
}
QVector < QPointF > : : const_iterator JKQTPGeoPolyLines : : pointsCBegin ( ) const
{
return points . cbegin ( ) ;
}
QVector < QPointF > : : const_iterator JKQTPGeoPolyLines : : pointsCEnd ( ) const
{
return points . cend ( ) ;
}
2020-08-26 16:36:07 +08:00
2020-09-26 21:58:58 +08:00
JKQTPGeoArc : : JKQTPGeoArc ( JKQTBasePlotter * parent , double x , double y , double width , double height , double angleStart , double angleStop ) :
JKQTPGeoBaseLine ( parent )
2020-08-26 16:36:07 +08:00
{
this - > angleStart = angleStart ;
this - > angleStop = angleStop ;
this - > x = x ;
this - > y = y ;
this - > width = width ;
this - > height = height ;
this - > angle = 0 ;
}
2020-09-26 21:58:58 +08:00
JKQTPGeoArc : : JKQTPGeoArc ( JKQTPlotter * parent , double x , double y , double width , double height , double angleStart , double angleStop ) :
JKQTPGeoArc ( parent - > getPlotter ( ) , x , y , width , height , angleStart , angleStop )
2020-08-26 16:36:07 +08:00
{
}
void JKQTPGeoArc : : draw ( JKQTPEnhancedPainter & painter ) {
2020-09-21 19:15:57 +08:00
auto fTransform = std : : bind ( [ ] ( const JKQTPGeometricPlotElement * plot , const QPointF & p ) { return plot - > transform ( p ) ; } , this , std : : placeholders : : _1 ) ;
- 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
const QPolygonF rect = JKQTPSplitEllipseIntoPoints ( fTransform , x , y , width / 2.0 , height / 2.0 , angleStart , angleStop , angle ) ;
2020-08-26 16:36:07 +08:00
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . setPen ( getLinePen ( painter , parent ) ) ;
2022-08-31 04:24:24 +08:00
painter . drawPolylineFast ( rect ) ;
2020-08-26 16:36:07 +08:00
}
void JKQTPGeoArc : : setAngleStart ( double __value )
{
this - > angleStart = __value ;
}
double JKQTPGeoArc : : getAngleStart ( ) const
{
return this - > angleStart ;
}
void JKQTPGeoArc : : setAngleStop ( double __value )
{
this - > angleStop = __value ;
}
double JKQTPGeoArc : : getAngleStop ( ) const
{
return this - > angleStop ;
}
void JKQTPGeoArc : : setX ( double __value )
{
this - > x = __value ;
}
double JKQTPGeoArc : : getX ( ) const
{
return this - > x ;
}
void JKQTPGeoArc : : setY ( double __value )
{
this - > y = __value ;
}
double JKQTPGeoArc : : getY ( ) const
{
return this - > y ;
}
- 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
QPointF JKQTPGeoArc : : getCenter ( ) const
{
return QPointF ( x , y ) ;
}
void JKQTPGeoArc : : setCenter ( const QPointF & center )
{
x = center . x ( ) ;
y = center . y ( ) ;
}
2020-08-26 16:36:07 +08:00
void JKQTPGeoArc : : setWidth ( double __value )
{
this - > width = __value ;
}
double JKQTPGeoArc : : getWidth ( ) const
{
return this - > width ;
}
void JKQTPGeoArc : : setHeight ( double __value )
{
this - > height = __value ;
}
double JKQTPGeoArc : : getHeight ( ) const
{
return this - > height ;
}
- 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
QSizeF JKQTPGeoArc : : getSize ( ) const
{
return QSizeF ( width , height ) ;
}
void JKQTPGeoArc : : setSize ( const QSizeF & size )
{
width = size . width ( ) ;
height = size . height ( ) ;
}
2020-08-26 16:36:07 +08:00
void JKQTPGeoArc : : setAngle ( double __value )
{
this - > angle = __value ;
}
double JKQTPGeoArc : : getAngle ( ) const
{
return this - > angle ;
}
bool JKQTPGeoArc : : getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) {
QPolygonF rect ;
- 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
rect = QPolygonF ( JKQTPSplitEllipseIntoPoints ( x , y , width / 2.0 , height / 2.0 , angleStart , angleStop , angle , 180 ) ) ;
2020-08-26 16:36:07 +08:00
minx = rect . boundingRect ( ) . left ( ) ;
maxx = rect . boundingRect ( ) . right ( ) ;
if ( minx > maxx ) std : : swap ( minx , maxx ) ;
smallestGreaterZero = 0 ;
double xvsgz ;
xvsgz = minx ; SmallestGreaterZeroCompare_xvsgz ( ) ;
xvsgz = maxx ; SmallestGreaterZeroCompare_xvsgz ( ) ;
return true ;
}
bool JKQTPGeoArc : : getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) {
QPolygonF rect ;
- 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
rect = QPolygonF ( JKQTPSplitEllipseIntoPoints ( x , y , width / 2.0 , height / 2.0 , angleStart , angleStop , angle , 180 ) ) ;
2020-08-26 16:36:07 +08:00
miny = rect . boundingRect ( ) . bottom ( ) ;
maxy = rect . boundingRect ( ) . top ( ) ;
if ( miny > maxy ) std : : swap ( miny , maxy ) ;
smallestGreaterZero = 0 ;
double xvsgz ;
xvsgz = miny ; SmallestGreaterZeroCompare_xvsgz ( ) ;
xvsgz = maxy ; SmallestGreaterZeroCompare_xvsgz ( ) ;
return true ;
}
2024-02-14 06:49:23 +08:00
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTBasePlotter * parent , const QPointF & start , const QPointF & control1 , const QPointF & end ) :
JKQTPGeoBaseDecoratedLine ( parent )
{
setQuad ( start , control1 , end ) ;
setHeadDecoratorStyle ( JKQTPNoDecorator ) ;
setTailDecoratorStyle ( JKQTPNoDecorator ) ;
}
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTPlotter * parent , const QPointF & start , const QPointF & control1 , const QPointF & end ) :
JKQTPGeoBezierCurve ( parent - > getPlotter ( ) , start , control1 , end )
{
}
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTBasePlotter * parent , const QPointF & start , const QPointF & control1 , const QPointF & control2 , const QPointF & end ) :
JKQTPGeoBaseDecoratedLine ( parent )
{
setCubic ( start , control1 , control2 , end ) ;
setHeadDecoratorStyle ( JKQTPNoDecorator ) ;
setTailDecoratorStyle ( JKQTPNoDecorator ) ;
}
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTPlotter * parent , const QPointF & start , const QPointF & control1 , const QPointF & control2 , const QPointF & end ) :
JKQTPGeoBezierCurve ( parent - > getPlotter ( ) , start , control1 , control2 , end )
{
}
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTBasePlotter * parent ) :
JKQTPGeoBaseDecoratedLine ( parent )
{
setHeadDecoratorStyle ( JKQTPNoDecorator ) ;
setTailDecoratorStyle ( JKQTPNoDecorator ) ;
}
JKQTPGeoBezierCurve : : JKQTPGeoBezierCurve ( JKQTPlotter * parent ) :
JKQTPGeoBezierCurve ( parent - > getPlotter ( ) )
{
}
bool JKQTPGeoBezierCurve : : getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) {
minx = 0 ;
maxx = 0 ;
smallestGreaterZero = 0 ;
if ( points . size ( ) > 0 ) {
minx = points [ 0 ] . x ( ) ;
maxx = points [ 0 ] . x ( ) ;
for ( int i = 1 ; i < points . size ( ) ; i + + ) {
double x = points [ i ] . x ( ) ;
if ( x > maxx ) maxx = x ;
if ( x < minx ) minx = x ;
double xvsgz ;
xvsgz = x ; SmallestGreaterZeroCompare_xvsgz ( ) ;
}
return true ;
}
return false ;
//qDebug()<<"getXMinMax"<<minx<<maxx;
}
bool JKQTPGeoBezierCurve : : getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) {
miny = 0 ;
maxy = 0 ;
smallestGreaterZero = 0 ;
if ( points . size ( ) > 0 ) {
miny = points [ 0 ] . y ( ) ;
maxy = points [ 0 ] . y ( ) ;
for ( int i = 1 ; i < points . size ( ) ; i + + ) {
double y = points [ i ] . y ( ) ;
if ( y > maxy ) maxy = y ;
if ( y < miny ) miny = y ;
double xvsgz ;
xvsgz = y ; SmallestGreaterZeroCompare_xvsgz ( ) ;
}
return true ;
}
return false ;
//qDebug()<<"getYMinMax"<<miny<<maxy;
}
void JKQTPGeoBezierCurve : : draw ( JKQTPEnhancedPainter & painter ) {
clearHitTestData ( ) ;
if ( points . size ( ) > = 2 ) {
reserveHitTestData ( points . size ( ) ) ;
2024-02-14 20:57:16 +08:00
double angle1 = 0 , angle2 = 0 ;
2024-02-14 06:49:23 +08:00
QPointF xx1 , xx2 ;
bool doDrawDecorator = false ;
painter . save ( ) ; auto __finalpaint = JKQTPFinally ( [ & painter ] ( ) { painter . restore ( ) ; } ) ;
painter . setPen ( getLinePen ( painter , parent ) ) ;
painter . setBrush ( Qt : : NoBrush ) ;
if ( ( points . size ( ) < = 4 ) & & ( ( getDrawMode ( ) = = DrawAsGraphicElement ) | | ( getXAxis ( ) - > isLinearAxis ( ) & & getYAxis ( ) - > isLinearAxis ( ) ) ) ) {
const QVector < QPointF > path = transform ( points ) ;
angle1 = atan2 ( path [ 1 ] . y ( ) - path [ 0 ] . y ( ) , path [ 1 ] . x ( ) - path [ 0 ] . x ( ) ) ;
angle2 = atan2 ( path [ path . size ( ) - 2 ] . y ( ) - path [ path . size ( ) - 1 ] . y ( ) , path [ path . size ( ) - 2 ] . x ( ) - path [ path . size ( ) - 1 ] . x ( ) ) ;
xx1 = path [ 0 ] ;
xx2 = path [ path . size ( ) - 1 ] ;
QPainterPath ppath ;
if ( path . size ( ) > 0 ) ppath . moveTo ( path [ 0 ] ) ;
if ( path . size ( ) = = 2 ) ppath . lineTo ( path [ 1 ] ) ;
else if ( path . size ( ) = = 3 ) ppath . quadTo ( path [ 1 ] , path [ 2 ] ) ;
else if ( path . size ( ) = = 4 ) ppath . cubicTo ( path [ 1 ] , path [ 2 ] , path [ 3 ] ) ;
// draw corrected line
if ( path . size ( ) > 0 ) {
painter . drawPath ( ppath ) ;
doDrawDecorator = true ;
}
} else {
if ( points . size ( ) > 1 ) {
std : : function < QPointF ( double ) > plotfunc ;
const auto B2_0 = jkqtp_makeBernstein < double > ( 2 , 0 ) ;
const auto B2_1 = jkqtp_makeBernstein < double > ( 2 , 1 ) ;
const auto B2_2 = jkqtp_makeBernstein < double > ( 2 , 2 ) ;
const auto B3_0 = jkqtp_makeBernstein < double > ( 3 , 0 ) ;
const auto B3_1 = jkqtp_makeBernstein < double > ( 3 , 1 ) ;
const auto B3_2 = jkqtp_makeBernstein < double > ( 3 , 2 ) ;
const auto B3_3 = jkqtp_makeBernstein < double > ( 3 , 3 ) ;
const auto B4_0 = jkqtp_makeBernstein < double > ( 4 , 0 ) ;
const auto B4_1 = jkqtp_makeBernstein < double > ( 4 , 1 ) ;
const auto B4_2 = jkqtp_makeBernstein < double > ( 4 , 2 ) ;
const auto B4_3 = jkqtp_makeBernstein < double > ( 4 , 3 ) ;
const auto B4_4 = jkqtp_makeBernstein < double > ( 4 , 4 ) ;
2024-02-14 20:57:16 +08:00
QVector < QPointF > pointsT = points ;
if ( getDrawMode ( ) = = DrawAsMathematicalCurve ) {
if ( points . size ( ) = = 2 ) plotfunc = [ & ] ( double t ) - > QPointF { return points [ 0 ] + t * ( points [ 1 ] - points [ 0 ] ) ; } ;
else if ( points . size ( ) = = 3 ) plotfunc = [ & ] ( double t ) - > QPointF { return points [ 0 ] * B2_0 ( t ) + points [ 1 ] * B2_1 ( t ) + points [ 2 ] * B2_2 ( t ) ; } ;
else if ( points . size ( ) = = 4 ) plotfunc = [ & ] ( double t ) - > QPointF { return points [ 0 ] * B3_0 ( t ) + points [ 1 ] * B3_1 ( t ) + points [ 2 ] * B3_2 ( t ) + points [ 3 ] * B3_3 ( t ) ; } ;
else if ( points . size ( ) = = 5 ) plotfunc = [ & ] ( double t ) - > QPointF { return points [ 0 ] * B4_0 ( t ) + points [ 1 ] * B4_1 ( t ) + points [ 2 ] * B4_2 ( t ) + points [ 3 ] * B4_3 ( t ) + points [ 4 ] * B4_4 ( t ) ; } ;
} else {
for ( auto & p : pointsT ) p = transform ( p ) ;
if ( pointsT . size ( ) = = 2 ) plotfunc = [ & ] ( double t ) - > QPointF { return pointsT [ 0 ] + t * ( pointsT [ 1 ] - pointsT [ 0 ] ) ; } ;
else if ( pointsT . size ( ) = = 3 ) plotfunc = [ & ] ( double t ) - > QPointF { return pointsT [ 0 ] * B2_0 ( t ) + pointsT [ 1 ] * B2_1 ( t ) + pointsT [ 2 ] * B2_2 ( t ) ; } ;
else if ( pointsT . size ( ) = = 4 ) plotfunc = [ & ] ( double t ) - > QPointF { return pointsT [ 0 ] * B3_0 ( t ) + pointsT [ 1 ] * B3_1 ( t ) + pointsT [ 2 ] * B3_2 ( t ) + pointsT [ 3 ] * B3_3 ( t ) ; } ;
else if ( pointsT . size ( ) = = 5 ) plotfunc = [ & ] ( double t ) - > QPointF { return pointsT [ 0 ] * B4_0 ( t ) + pointsT [ 1 ] * B4_1 ( t ) + pointsT [ 2 ] * B4_2 ( t ) + pointsT [ 3 ] * B4_3 ( t ) + pointsT [ 4 ] * B4_4 ( t ) ; } ;
}
2024-02-14 06:49:23 +08:00
if ( plotfunc ) {
2024-02-14 20:57:16 +08:00
std : : function < QPointF ( double ) > fTransformedFunc ;
2024-02-14 06:49:23 +08:00
const int minSamples = 10 ;
const int maxRefinementDegree = 5 ;
const double slopeTolerance = 0.005 ;
const int minPixelPerSample = 32 ;
const double maxConsecutiveAngleDegree = 0.2 ;
2024-02-14 20:57:16 +08:00
if ( getDrawMode ( ) = = DrawAsMathematicalCurve ) fTransformedFunc = std : : bind ( [ plotfunc ] ( const JKQTPPlotElement * plot , double t ) - > QPointF { return plot - > transform ( plotfunc ( t ) ) ; } , this , std : : placeholders : : _1 ) ;
else fTransformedFunc = plotfunc ;
2024-02-14 06:49:23 +08:00
JKQTPAdaptiveFunctionGraphEvaluator evaluator ( fTransformedFunc , minSamples , maxRefinementDegree , slopeTolerance , minPixelPerSample ) ;
QVector < QPointF > data = evaluator . evaluate ( 0 , 1 ) ;
data = JKQTPSimplyfyLineSegemnts ( data , maxConsecutiveAngleDegree ) ;
painter . drawPolylineFast ( data . data ( ) , data . size ( ) ) ;
doDrawDecorator = true ;
}
}
}
// potentially draw line-end decorators/arrows
if ( doDrawDecorator ) {
painter . setBrush ( getLineColor ( ) ) ;
JKQTPPlotLineDecorator ( painter , xx1 . x ( ) , xx1 . y ( ) , angle1 , getTailDecoratorStyle ( ) , calcTailDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ;
JKQTPPlotLineDecorator ( painter , xx2 . x ( ) , xx2 . y ( ) , angle2 , getHeadDecoratorStyle ( ) , calcHeadDecoratorSize ( getLinePen ( painter , getParent ( ) ) . widthF ( ) ) ) ;
}
for ( const auto & p : points ) {
addHitTestData ( p . x ( ) , p . y ( ) ) ;
}
}
}
void JKQTPGeoBezierCurve : : setPoints ( const QVector < QPointF > & __value )
{
const int maxPoints = 5 ;
if ( points . size ( ) < 2 | | points . size ( ) > maxPoints ) throw std : : runtime_error ( " JKQTPGeoBezierCurve only supports 2, 3 ... or " + std : : to_string ( maxPoints ) + " points, but you supplied " + std : : to_string ( __value . size ( ) ) + " ! " ) ;
points = __value ;
}
QVector < QPointF > JKQTPGeoBezierCurve : : getPoints ( ) const
{
return points ;
}
QPointF JKQTPGeoBezierCurve : : getStart ( ) const
{
return points [ 0 ] ;
}
QPointF JKQTPGeoBezierCurve : : getEnd ( ) const
{
return points . last ( ) ;
}
QPointF JKQTPGeoBezierCurve : : getControl1 ( ) const
{
return points [ 1 ] ;
}
QPointF JKQTPGeoBezierCurve : : getControl2 ( ) const
{
return points [ 2 ] ;
}
void JKQTPGeoBezierCurve : : setLine ( const QPointF & start , const QPointF & end )
{
points = { start , end } ;
}
void JKQTPGeoBezierCurve : : setQuad ( const QPointF & start , const QPointF & control1 , const QPointF & end )
{
points = { start , control1 , end } ;
}
void JKQTPGeoBezierCurve : : setCubic ( const QPointF & start , const QPointF & control1 , const QPointF & control2 , const QPointF & end )
{
points = { start , control1 , control2 , end } ;
}
void JKQTPGeoBezierCurve : : setQuartic ( const QPointF & start , const QPointF & control1 , const QPointF & control2 , const QPointF & control3 , const QPointF & end )
{
points = { start , control1 , control2 , control3 , end } ;
}
int JKQTPGeoBezierCurve : : getDegree ( ) const
{
return points . size ( ) - 1 ;
}
int JKQTPGeoBezierCurve : : getNumberOfCOntrolPoints ( ) const
{
return points . size ( ) ;
}