2018-11-25 21:53:26 +08:00
/*
2024-02-06 21:50:49 +08:00
Copyright ( c ) 2008 - 2024 Jan W . Krieger ( < jan @ jkrieger . de > )
2018-11-25 21:53:26 +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
2019-02-08 00:24:46 +08:00
the Free Software Foundation , either version 2.1 of the License , or
2018-11-25 21:53:26 +08:00
( 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/>.
*/
2022-07-21 04:31:42 +08:00
# ifndef JKQTPGRAPHSBASE_H
# define JKQTPGRAPHSBASE_H
2018-11-25 21:53:26 +08:00
# include <QString>
# include <QPainter>
# include <QPair>
2018-12-28 05:52:00 +08:00
# include "jkqtplotter/jkqtpbaseelements.h"
# include "jkqtplotter/jkqtpbaseplotter.h"
2019-05-30 04:40:02 +08:00
# include "jkqtplotter/jkqtptools.h"
2019-06-22 20:21:32 +08:00
# include "jkqtplotter/jkqtplotter_imexport.h"
2019-05-30 04:40:02 +08:00
# include "jkqtplotter/jkqtpimagetools.h"
2018-11-25 21:53:26 +08:00
// forward declarations
2019-01-20 23:15:10 +08:00
class JKQTPlotter ;
2019-01-20 17:49:29 +08:00
class JKQTPDatastore ;
2019-05-06 01:31:20 +08:00
class JKQTPGraphErrorStyleMixin ;
2018-11-25 21:53:26 +08:00
2019-01-20 23:15:10 +08:00
/** \brief this virtual base class of every element, which is part of a JKQTPlotter plot and may appear in its key
2018-12-28 05:52:00 +08:00
* ( basically any type of graph , except overlay elements ! )
2019-01-13 01:53:16 +08:00
* \ ingroup jkqtplotter_basegraphs
2018-11-25 21:53:26 +08:00
*
2018-12-28 05:52:00 +08:00
* Each possible graph is represented by a child of this class . So additional plots may be created by
2019-01-20 17:49:29 +08:00
* deriving new JKQTPGraph classes . To do so implement / overwrite these functions :
2018-11-25 21:53:26 +08:00
* - void draw ( JKQTPEnhancedPainter & painter ) ;
2023-12-19 05:24:59 +08:00
* - void drawKeyMarker ( JKQTPEnhancedPainter & painter , const QRectF & rect ) ;
2018-11-25 21:53:26 +08:00
* - bool getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) ;
2019-02-03 21:04:48 +08:00
* - bool getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) ;
2019-04-22 19:27:50 +08:00
* - QColor getKeyLabelColor ( ) const = 0 ;
2019-02-03 21:04:48 +08:00
* .
2018-12-28 05:52:00 +08:00
*
* Optionally you may also overwrite these functions to draw elements outside the actual plot area ( like e . g . colorbars ) :
* - void getOutsideSize ( JKQTPEnhancedPainter & painter , int & leftSpace , int & rightSpace , int & topSpace , int & bottomSpace ) ;
* - void drawOutside ( JKQTPEnhancedPainter & painter , QRect leftSpace , QRect rightSpace , QRect topSpace , QRect bottomSpace ) ;
2018-11-25 21:53:26 +08:00
* .
*
2019-02-03 21:04:48 +08:00
* In addition this class provudes protected
* functions that do coordinate transforms based on the current coordinate system , of the paren
* JKQTPlotter ( i . e . using the axes JKQTPLott : xAxis and JKQTPlotter : : yAxis as basis for the plotting ) .
*
* \ see \ ref jkqtplotter_graphsgroup_classstructure
2018-11-25 21:53:26 +08:00
*/
2019-06-22 20:21:32 +08:00
class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement : public QObject {
2018-11-25 21:53:26 +08:00
Q_OBJECT
public :
2019-05-06 01:31:20 +08:00
2018-11-25 21:53:26 +08:00
/** \brief class constructor */
2019-01-20 17:49:29 +08:00
explicit JKQTPPlotElement ( JKQTBasePlotter * parent = nullptr ) ;
2018-11-25 21:53:26 +08:00
/** \brief default wirtual destructor */
2019-02-03 21:04:48 +08:00
virtual ~ JKQTPPlotElement ( ) = default ;
2018-11-25 21:53:26 +08:00
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw ( JKQTPEnhancedPainter & painter ) = 0 ;
2018-12-28 05:52:00 +08:00
2018-11-25 21:53:26 +08:00
/** \brief plots a key marker inside the specified rectangle \a rect */
2023-12-19 05:24:59 +08:00
virtual void drawKeyMarker ( JKQTPEnhancedPainter & painter , const QRectF & rect ) = 0 ;
2018-12-28 05:52:00 +08:00
2018-11-25 21:53:26 +08:00
/** \brief returns an image with a key marker inside */
QImage generateKeyMarker ( QSize size = QSize ( 16 , 16 ) ) ;
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call - by - reference parameters !
2024-02-05 05:06:09 +08:00
*
* \ param [ out ] minx minimal x - value used in the graph
* \ param [ out ] maxx maximal x - value used in the graph
* \ param [ out ] smallestGreaterZero the smalles x - value in the graph , which is larger than 0 ( this is used in auto - sizing for logarithmic axes )
* \ return \ c true on success , i . e . if there were datapoints in the plot , or \ c false on failure ( e . g . when the graph is empty )
2018-11-25 21:53:26 +08:00
*/
virtual bool getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) = 0 ;
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call - by - reference parameters !
2024-02-05 05:06:09 +08:00
*
* \ param [ out ] miny minimal y - value used in the graph
* \ param [ out ] maxy maximal y - value used in the graph
* \ param [ out ] smallestGreaterZero the smalles y - value in the graph , which is larger than 0 ( this is used in auto - sizing for logarithmic axes )
* \ return \ c true on success , i . e . if there were datapoints in the plot , or \ c false on failure ( e . g . when the graph is empty )
2018-11-25 21:53:26 +08:00
*/
virtual bool getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) = 0 ;
/** \brief returns the color to be used for the key label */
2019-04-22 19:27:50 +08:00
virtual QColor getKeyLabelColor ( ) const = 0 ;
2018-11-25 21:53:26 +08:00
2020-09-21 19:47:54 +08:00
/** \brief returns the the title of the plot */
2020-09-19 01:11:50 +08:00
QString getTitle ( ) const ;
2020-09-21 19:47:54 +08:00
/** \brief returns whether the graph is visible in the plot */
2020-09-19 01:11:50 +08:00
bool isVisible ( ) const ;
2020-09-21 19:47:54 +08:00
/** \brief returns whether the graph is shown in a highlighted style in the plot */
2020-09-19 01:11:50 +08:00
bool isHighlighted ( ) const ;
2018-11-25 21:53:26 +08:00
2020-09-19 04:03:12 +08:00
/** \brief returns the parent painter class */
inline const JKQTBasePlotter * getParent ( ) const { return parent ; }
2018-11-25 21:53:26 +08:00
/** \brief returns the parent painter class */
2019-01-20 17:49:29 +08:00
inline JKQTBasePlotter * getParent ( ) { return parent ; }
2018-11-25 21:53:26 +08:00
/** \brief sets the parent painter class */
2019-01-20 17:49:29 +08:00
virtual void setParent ( JKQTBasePlotter * parent ) ;
2018-11-25 21:53:26 +08:00
/** \brief sets the parent painter class */
2019-01-20 23:15:10 +08:00
virtual void setParent ( JKQTPlotter * parent ) ;
2018-11-25 21:53:26 +08:00
2020-09-19 01:11:50 +08:00
Q_PROPERTY ( bool visible READ isVisible WRITE setVisible )
Q_PROPERTY ( QString title READ getTitle WRITE setTitle )
Q_PROPERTY ( bool highlighted READ isHighlighted WRITE setHighlighted )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-21 19:47:54 +08:00
/** \brief sets whether the graph is visible in the plot */
2020-09-19 01:11:50 +08:00
void setVisible ( bool __value ) ;
2020-09-21 19:47:54 +08:00
/** \brief sets whether the graph is drawn in a highlighted style in the plot */
2020-09-19 01:11:50 +08:00
void setHighlighted ( bool __value ) ;
/** \brief sets the title of the plot (for display in key!).
*
* \ note If no title is supplied , no key entry is drawn . */
virtual void setTitle ( const QString & __value ) ;
public :
2018-11-25 21:53:26 +08:00
/*! \brief if the graph plots outside the actual plot field of view (e.g. color bars, scale bars, ...)
\ note If you want to draw outside , then you ' ll also have to implement drawOutside ( )
*/
virtual void getOutsideSize ( JKQTPEnhancedPainter & painter , int & leftSpace , int & rightSpace , int & topSpace , int & bottomSpace ) ;
/*! \brief plots outside the actual plot field of view (e.g. color bars, scale bars, ...)
\ note If you want to draw outside , then you ' ll also have to implement getOutsideSize ( ) , so enough space is reserved
The four value supplied tell the method where to draw ( inside one of the rectangles ) .
*/
virtual void drawOutside ( JKQTPEnhancedPainter & painter , QRect leftSpace , QRect rightSpace , QRect topSpace , QRect bottomSpace ) ;
2019-05-06 01:31:20 +08:00
/** \brief modes of operation for the function hitTest() */
enum HitTestMode {
HitTestXY , /*!< \brief find closest point in x- and y-direction simulatneously (i.e. measure direct distance) */
HitTestXOnly , /*!< \brief find closest point in x-direction only */
HitTestYOnly , /*!< \brief find closest point in y-direction only */
} ;
2020-09-19 01:11:50 +08:00
Q_ENUM ( HitTestMode )
2019-05-06 01:31:20 +08:00
/*! \brief returns the closest distance of the plot element to the (screen pixel) position \a pos, or \c NAN
This function is used to implement hit tests , i . e . to test whether a graph is close to a given position \ a posSystem .
The function will then return the distance of the closes graph - point and a label for this point . An example of what
can be done with this function is the tooltip tool that JKQTPlotter provides via its context - menu / toolbar . This tool
uses just the information of the closest point and its label to display a tooltip for that datapoint :
\ see jkqtpmdaToolTipForClosestDataPoint for details .
\ param posSystem position to test in system coordinates
\ param [ out ] closestSpotSystem optional output of the closest point found on the plot element in system coordinates
\ param [ out ] label optional output of a label for the closest point ( that might e . g . be used in a tooltip )
\ param mode search mode , i . e . use sqrt ( dx * dx + dy * dy ) as distance , or just the absoulte values along one of the
two coordinate axes . Note that the returned distance depends on this parameter !
\ return NAN if not implemented , or if \ a pos is very far from the plot element , or the closest distance ( in screen pixels )
of \ a pos from the plot element . Note that the returned distance depends on the choosen \ a mode ! ! !
You can use JKQTPIsOKFloat ( ) to check whether a valid distance was returned !
2022-09-20 03:53:53 +08:00
Since the graph base class does not have any knowledge about how to perform a hit test on you specific graph , there is only a
2019-05-06 01:31:20 +08:00
very general implementation in this class , which does not actually search through the graph itself , but searches through
extra data that hs to be written during draw ( ) and is stored in m_hitTestData . The implentation this base - class only searches this
list of points + metadata to implement a basic hit - test . If the list is empty , of no close - by points are found ( default ) , then
hitTest ( ) will simply return \ a NAN .
When writing a new graph , you can therefore implement hitTest ( ) in one of these ways :
2022-09-20 03:53:53 +08:00
< ol >
< li > You simply fill m_hitTestData with appropriate data and rely on the implementation in JKQTPPlotElement to do the work for you :
2019-05-06 01:31:20 +08:00
You then need to call clearHitTestData ( ) at the start of your draw ( ) function and whenever you draw a datapoint , you add
2019-05-18 02:46:52 +08:00
its location and metadata to the internal storage with addHitTestData ( )
2022-09-20 03:53:53 +08:00
< li > You derive from a graph class that already has an implementation . JKQTPXYGraph is an example of this . That class searches
2019-05-06 01:31:20 +08:00
through all x - / y - coordinates in the internally known columns and even takes into account possible graph errors in the label ,
when the graph is also derived from JKQTPXGraphErrorData or JKQTPYGraphErrorData . This implementation therefore covers
2019-05-18 02:46:52 +08:00
most graph types pre - packaged with JKQTPlotter
2022-09-20 03:53:53 +08:00
< li > You implement the function from scratch
< / ol >
2019-05-06 01:31:20 +08:00
\ see addHitTestData ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation
*/
virtual double hitTest ( const QPointF & posSystem , QPointF * closestSpotSystem = nullptr , QString * label = nullptr , HitTestMode mode = HitTestXY ) const ;
/** \brief Dataset for a single point on the graph, associated with its data-column index and a label that can be used by a basic implementation of hitTest()
*
* \ see hitTest ( )
*/
struct HitTestLocation {
2019-05-11 21:56:11 +08:00
inline HitTestLocation ( ) : pos ( JKQTP_NAN , JKQTP_NAN ) , index ( - 1 ) , label ( " " ) { }
2019-05-06 01:31:20 +08:00
inline HitTestLocation ( double x_ , double y_ , const QString & label_ ) : pos ( x_ , y_ ) , index ( - 1 ) , label ( label_ ) { }
inline HitTestLocation ( const QPointF & pos_ , const QString & label_ ) : pos ( pos_ ) , index ( - 1 ) , label ( label_ ) { }
inline HitTestLocation ( double x_ , double y_ , int index_ , const QString & label_ ) : pos ( x_ , y_ ) , index ( index_ ) , label ( label_ ) { }
inline HitTestLocation ( const QPointF & pos_ , int index_ , const QString & label_ ) : pos ( pos_ ) , index ( index_ ) , label ( label_ ) { }
/** \brief position of the hit-test point */
QPointF pos ;
/** \brief index of the hit-test point in the linked data-columns (or -1) */
int index ;
/** \brief label for that specific hit-test point */
QString label ;
} ;
2018-11-25 21:53:26 +08:00
2023-03-23 20:55:18 +08:00
/** \brief tool routine that transforms an x-coordinate (plot coordinate --> pixels) for this plot element, uses the axis referenced in xAxisRef */
2020-09-19 01:11:50 +08:00
double transformX ( double x ) const ;
2018-12-28 05:52:00 +08:00
2023-03-23 20:55:18 +08:00
/** \brief tool routine that transforms a y-coordinate (plot coordinate --> pixels) for this plot element, uses the axis referenced in yAxisRef */
2020-09-19 01:11:50 +08:00
double transformY ( double y ) const ;
2018-12-28 05:52:00 +08:00
2023-03-23 20:55:18 +08:00
/** \brief tool routine that backtransforms an x-coordinate (pixels --> plot coordinate) for this plot element, uses the axis referenced in xAxisRef */
2020-09-19 01:11:50 +08:00
double backtransformX ( double x ) const ;
2018-12-28 05:52:00 +08:00
2023-03-23 20:55:18 +08:00
/** \brief tool routine that backtransforms a y-coordinate (pixels --> plot coordinate) for this plot element, uses the axis referenced in yAxisRef */
2020-09-19 01:11:50 +08:00
double backtransformY ( double y ) const ;
2018-12-28 05:52:00 +08:00
2019-02-03 21:04:48 +08:00
/** \brief tool routine that transforms a QPointF according to the parent's transformation rules (plot coordinate --> pixels) */
2019-05-06 01:31:20 +08:00
inline QPointF transform ( const QPointF & x ) const {
2018-12-28 05:52:00 +08:00
return QPointF ( transformX ( x . x ( ) ) , transformY ( x . y ( ) ) ) ;
}
2018-11-25 21:53:26 +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
2019-02-03 21:04:48 +08:00
/** \brief tool routine that back-transforms a QPointF according to the parent's transformation rules (pixels --> plot coordinate) */
2019-05-06 01:31:20 +08:00
inline QPointF backTransform ( const QPointF & x ) const {
2018-12-28 05:52:00 +08:00
return QPointF ( backtransformX ( x . x ( ) ) , backtransformY ( x . y ( ) ) ) ;
}
2018-11-25 21:53:26 +08:00
2019-02-03 21:04:48 +08:00
/** \brief tool routine that transforms a QPointF according to the parent's transformation rules (plot coordinate --> pixels) */
2019-05-06 01:31:20 +08:00
inline QPointF transform ( double x , double y ) const {
2018-11-25 21:53:26 +08:00
return transform ( 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
2019-02-03 21:04:48 +08:00
/** \brief tool routine that back-transforms a QPointF according to the parent's transformation rules (pixels --> plot coordinate) */
2019-05-06 01:31:20 +08:00
inline QPointF backTransform ( double x , double y ) const {
2018-11-25 21:53:26 +08:00
return backTransform ( QPointF ( x , y ) ) ;
}
2022-08-25 23:46:57 +08:00
/** \brief tool routine that transforms a QPolygonF according to the parent's transformation rules (plot coordinate --> pixels) */
QPolygonF transform ( const QPolygonF & x ) const ;
2018-11-25 21:53:26 +08:00
2022-08-25 23:46:57 +08:00
/** \brief tool routine that transforms a QPolygonF according to the parent's transformation rules
2019-02-03 21:04:48 +08:00
* and returns a ( non - closed ) path consisting of lines ( plot coordinate - - > pixels ) */
2022-08-25 23:46:57 +08:00
QPainterPath transformToLinePath ( const QPolygonF & x ) const ;
2018-11-25 21:53:26 +08:00
2019-02-03 21:04:48 +08:00
2019-06-17 01:15:07 +08:00
/** \brief transform all x-coordinates in a vector \a x */
QVector < double > transformX ( const QVector < double > & x ) const ;
/** \brief transform all y-coordinates in a vector \a x */
QVector < double > transformY ( const QVector < double > & x ) const ;
2023-03-23 20:55:18 +08:00
/** \copydoc xAxisRef */
void setXAxis ( JKQTPCoordinateAxisRef ref ) ;
/** \copydoc xAxisRef */
JKQTPCoordinateAxisRef getXAxisRef ( ) const ;
/** \copydoc yAxisRef */
void setYAxis ( JKQTPCoordinateAxisRef ref ) ;
/** \copydoc yAxisRef */
JKQTPCoordinateAxisRef getYAxisRef ( ) const ;
/** \brief returns the actual x-Axis-object from the parent plotter, referenced in xAxisRef */
/** \brief returns the actual x-Axis-object from the parent plotter, referenced in xAxisRef */
inline const JKQTPCoordinateAxis * getXAxis ( ) const {
return parent - > getXAxis ( xAxisRef ) ;
}
/** \brief returns the actual y-Axis-object from the parent plotter, referenced in yAxisRef */
inline const JKQTPCoordinateAxis * getYAxis ( ) const {
return parent - > getYAxis ( yAxisRef ) ;
}
/** \brief set the coordinate axes to use for this plot element
*
* \ see xAxisRef , yAxisRef , transformX ( ) , transformY ( )
*/
void setAxes ( JKQTPCoordinateAxisRef ref ) ;
Q_PROPERTY ( JKQTPCoordinateAxisRef xAxisRef READ getXAxisRef WRITE setXAxis )
Q_PROPERTY ( JKQTPCoordinateAxisRef yAxisRef READ getYAxisRef WRITE setYAxis )
2019-05-06 01:31:20 +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
protected :
2019-05-06 01:31:20 +08:00
/** \brief clear the internal datastore for hitTest()
*
* \ note This function has to be called at the start of draw ( )
* \ see hitTest ( ) , addHitTestData ( ) , m_hitTestData , HitTestLocation
*/
inline void clearHitTestData ( ) { m_hitTestData . clear ( ) ; }
/** \brief reserve list entries for up to \a points graph points in the internal datastore for hitTest()
*
* \ note Call this after clearHitTestData ( ) for improved speed of subsequent addHitTestData ( ) calls !
* \ see hitTest ( ) , addHitTestData ( ) , m_hitTestData , HitTestLocation
*/
inline void reserveHitTestData ( int points ) { m_hitTestData . reserve ( qMax ( 10 , abs ( points ) ) ) ; }
/** \brief clear the internal datastore for hitTest()
*
* \ note This function has to be called at the start of draw ( )
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( const HitTestLocation & loc ) { m_hitTestData < < loc ; }
/** \brief add a new point on the graph to the internal datastore for hitTest()
*
* \ param x_ x - position of the graph point in system coordinates
* \ param y_ y - position of the graph point in system coordinates
* \ param label_ a label for this datapoint , that can e . g . be displayed in a tooltip for this point
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( double x_ , double y_ , const QString & label_ ) { addHitTestData ( HitTestLocation ( x_ , y_ , label_ ) ) ; }
/** \brief clear the internal datastore for hitTest()
*
* \ param pos_ position of the graph point in system coordinates
* \ param label_ a label for this datapoint , that can e . g . be displayed in a tooltip for this point
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( const QPointF & pos_ , const QString & label_ ) { addHitTestData ( HitTestLocation ( pos_ , label_ ) ) ; }
/** \brief add a new point on the graph to the internal datastore for hitTest(),
* this variant uses formatHitTestDefaultLabel ( ) to auto - generate the label
*
* \ param x_ x - position of the graph point in system coordinates
* \ param y_ y - position of the graph point in system coordinates
* \ param index_ index of the graph point in the internal data columns , or - 1
* \ param datastore datastore for formatHitTestDefaultLabel ( )
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( double x_ , double y_ , int index_ = - 1 , JKQTPDatastore * datastore = nullptr ) { addHitTestData ( HitTestLocation ( x_ , y_ , formatHitTestDefaultLabel ( x_ , y_ , index_ , datastore ) ) ) ; }
/** \brief clear the internal datastore for hitTest(),
* this variant uses formatHitTestDefaultLabel ( ) to auto - generate the label
*
* \ param pos_ position of the graph point in system coordinates
* \ param index_ index of the graph point in the internal data columns , or - 1
* \ param datastore datastore for formatHitTestDefaultLabel ( )
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( const QPointF & pos_ , int index_ = - 1 , JKQTPDatastore * datastore = nullptr ) { addHitTestData ( HitTestLocation ( pos_ , formatHitTestDefaultLabel ( pos_ . x ( ) , pos_ . y ( ) , index_ , datastore ) ) ) ; }
/** \brief clear the internal datastore for hitTest()
*
* \ param x_ x - position of the graph point in system coordinates
* \ param y_ y - position of the graph point in system coordinates
* \ param index_ index of the graph point in the internal data columns
* \ param label_ a label for this datapoint , that can e . g . be displayed in a tooltip for this point
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( double x_ , double y_ , int index_ , const QString & label_ ) { addHitTestData ( HitTestLocation ( x_ , y_ , index_ , label_ ) ) ; }
/** \brief clear the internal datastore for hitTest()
*
* \ param pos_ position of the graph point in system coordinates
* \ param index_ index of the graph point in the internal data columns
* \ param label_ a label for this datapoint , that can e . g . be displayed in a tooltip for this point
*
* \ see hitTest ( ) , clearHitTestData ( ) , m_hitTestData , HitTestLocation , reserveHitTestData ( )
*/
inline void addHitTestData ( const QPointF & pos_ , int index_ , const QString & label_ ) { addHitTestData ( HitTestLocation ( pos_ , index_ , label_ ) ) ; }
/** \brief tool-function for hitTest(), which formats a default label, taking into account the x- and y-position (both provided)
* and optionally the errors of these positions .
*
* \ param x x - position of the datapoint in system coordinates
* \ param y y - position of the datapoint in system coordinates
* \ param index the index of the data point in the associated data column ( s ) , or - 1 ( optional ! )
* \ param datastore The datastore to read error data from ( optional ! )
* \ returns a LaTeX formatted label
*/
virtual QString formatHitTestDefaultLabel ( double x , double y , int index = - 1 , JKQTPDatastore * datastore = nullptr ) const ;
2019-02-03 21:04:48 +08:00
/** \brief the plotter object this object belongs to */
JKQTBasePlotter * parent ;
/** \brief title of the plot (for display in key!). If no title is supplied, no key entry is drawn. */
QString title ;
/** \brief indicates whether the graph is visible in the plot */
bool visible ;
2019-04-22 19:27:50 +08:00
/** \brief indicates whether the graph is shown in a "highlghted" in the plot */
bool highlighted ;
/** \brief internal storage for the used parent plot style */
int parentPlotStyle ;
2023-03-23 20:55:18 +08:00
/** \brief indicates which coordinate axis to use for coordinate transforms in x-direction */
JKQTPCoordinateAxisRef xAxisRef ;
/** \brief indicates which coordinate axis to use for coordinate transforms in y-direction */
JKQTPCoordinateAxisRef yAxisRef ;
2019-05-06 01:31:20 +08:00
2024-02-05 05:06:09 +08:00
/** \brief dataset with graph-points and associated data from the function hitTest()
2019-05-06 01:31:20 +08:00
* \ see hitTest ( ) , HitTestLocation
*/
QVector < HitTestLocation > m_hitTestData ;
2018-12-28 05:52:00 +08:00
} ;
/** \brief this virtual base class of the (data-column based) graphs,
2019-01-20 23:15:10 +08:00
* which are part of a JKQTPlotter plot and which use the coordinate system
2019-01-26 03:16:04 +08:00
* of the JKQTPlotter ( i . e . the two coordinate axes getXAxis ( ) and getYAxis ( ) )
2018-12-28 05:52:00 +08:00
* as basis for the graphs
2019-01-13 01:53:16 +08:00
* \ ingroup jkqtplotter_basegraphs
2018-12-28 05:52:00 +08:00
*
2019-02-03 21:04:48 +08:00
* This class adds features to work with data columns .
* - There are two properties datarange_start and datarange_end . By default they are - 1 and therefore ignored .
* if they are ! = - 1 the plotter only displays the datapoints with the indexes [ datarange_start . . datarange_end ]
* although there might be more data points available ( range [ 0 . . maxDataPoints ] ) . The datarange is cut at the
* full range , i . e . if datarange_end > maxDataPoints the plotter displays [ datarange_start . . maxDataPoints ] .
* - Also there is a virtual function usesColumn ( ) which checks whether a given column is used by this graph .
* Override this function in your derived graphs to indicate to JKQTPlotter / JKQTBasePlotter , which columns
* from the internal JKQTPDatastore are actually used . This information can be used e . g . for graph - specific data - export .
* .
2018-12-28 05:52:00 +08:00
*
2019-02-03 21:04:48 +08:00
* \ see \ ref jkqtplotter_graphsgroup_classstructure
2018-12-28 05:52:00 +08:00
*/
2019-06-22 20:21:32 +08:00
class JKQTPLOTTER_LIB_EXPORT JKQTPGraph : public JKQTPPlotElement {
2018-12-28 05:52:00 +08:00
Q_OBJECT
public :
/** \brief class constructor */
2019-01-20 17:49:29 +08:00
explicit JKQTPGraph ( JKQTBasePlotter * parent = nullptr ) ;
2018-12-28 05:52:00 +08:00
/** \brief default wirtual destructor */
2019-02-03 21:04:48 +08:00
virtual ~ JKQTPGraph ( ) = default ;
2018-12-28 05:52:00 +08:00
2019-02-03 21:04:48 +08:00
/** \brief returns \c true if the given column is used by the graph
*
* This virtual function indicates whether a given column is used by this graph .
* Override this function in your derived graphs to indicate to JKQTPlotter / JKQTBasePlotter , which columns
* from the internal JKQTPDatastore are actually used . This information can be used e . g . for graph - specific data - export .
*/
2018-12-28 05:52:00 +08:00
virtual bool usesColumn ( int column ) const ;
protected :
/** \brief this function is used to plot error inidcators before plotting the graphs.
*
* By default this function does nothing . But children of this class may overwrite it to implement
* drawing error indicators .
*/
virtual void drawErrorsBefore ( JKQTPEnhancedPainter & /*painter*/ ) ;
/** \brief this function is used to plot error inidcators after plotting the graphs.
*
* By default this function does nothing . But children of this class may overwrite it to implement
* drawing error indicators .
*/
virtual void drawErrorsAfter ( JKQTPEnhancedPainter & /*painter*/ ) ;
2018-11-25 21:53:26 +08:00
/** \brief get the maximum and minimum value of the given column
*
* The result is given in the two parameters which are call - by - reference parameters !
*/
bool getDataMinMax ( int column , double & minx , double & maxx , double & smallestGreaterZero ) ;
2019-02-03 21:04:48 +08:00
protected :
2019-05-06 01:31:20 +08:00
friend class JKQTPGraphErrorStyleMixin ;
2018-11-25 21:53:26 +08:00
} ;
2019-01-20 23:15:10 +08:00
/** \brief this is the virtual base class of all JKQTPPlotElement's in a JKQTPlotter plot that
2020-09-21 19:15:57 +08:00
* represent geometric forms .
- 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
* \ ingroup jkqtplotter_basegraphs
2018-12-28 05:52:00 +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
* \ see \ ref jkqtplotter_graphsgroup_classstructure , \ ref JKQTPlotterGeometricGraphs
*
2020-09-21 19:15:57 +08:00
* \ section JKQTPGeometricPlotElement_coordinates Coordinate Systems
* JKQTPGeometricPlotElement ' s have extended coordinate transform capabilities , because in addition to using
- 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
* the plot coordinates , you can also choose to use different other coordinate systems .
*
2020-09-21 19:15:57 +08:00
* \ section JKQTPGeometricPlotElement_DrawMode Draw Modes
2019-02-03 21:04:48 +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
* \ copydetails m_drawMode
2018-12-28 05:52:00 +08:00
*/
2020-09-21 19:15:57 +08:00
class JKQTPLOTTER_LIB_EXPORT JKQTPGeometricPlotElement : public JKQTPPlotElement {
Q_OBJECT
public :
- 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-09-21 19:15:57 +08:00
/** \brief indicates how to draw the geometric object */
enum DrawMode {
DrawAsGraphicElement , /*!< \brief draw lines as lines (i.e. graphic elements) \image html JKQTPGeometricPlotElement_DrawAsGraphicElement.png */
DrawAsMathematicalCurve /*!< \brief draw lines as the mathematically correct curve \image html JKQTPGeometricPlotElement_DrawAsMathematicalCurve.png */
} ;
Q_ENUM ( DrawMode )
- 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-09-21 19:15:57 +08:00
/** \brief class constructor */
explicit JKQTPGeometricPlotElement ( DrawMode drawMode = DrawAsGraphicElement , JKQTBasePlotter * parent = nullptr ) ;
2018-12-28 05:52:00 +08:00
2020-09-21 19:15:57 +08:00
/** \brief default wirtual destructor */
virtual ~ JKQTPGeometricPlotElement ( ) ;
/** \copybrief m_drawMode
- 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
*
* \ return the currently set DrawMode
* \ see m_drawMode , DrawMode
*/
2020-09-21 19:15:57 +08:00
DrawMode getDrawMode ( ) const ;
2020-09-19 01:11:50 +08:00
2020-09-21 19:15:57 +08:00
Q_PROPERTY ( DrawMode drawMode READ getDrawMode WRITE setDrawMode )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-21 19:15:57 +08:00
/** \copybrief m_drawMode
- 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
*
* \ param mode the DrawMode to use from now on
* \ see m_drawMode , DrawMode
*/
2020-09-21 19:15:57 +08:00
void setDrawMode ( DrawMode mode ) ;
protected :
/** \brief indicated whether to draw lines as graphic elements (even on non-linear coordinate systems),
- 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
* or as mathematically correct curves
*
* It is possible to define in which ways the forms shall be treated / drawn into non - linear
* coordinate systems ( e . g . semi - log or log - log plots ) . Imagine drawing a line from ( x1 , y1 ) to ( x2 , y2 )
* In a linear coordinate system , this is always a line , but in a non - linear system , the line might
2020-09-21 19:15:57 +08:00
* have to be represented by a curve instead . Depending on how you want to use the JKQTPGeometricPlotElement you
- 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
* can choose to still draw it as a line connecting the points ( x1 , y1 ) and ( x2 , y2 ) , or as the -
* mathematically correct - curve connecting these two points :
*
2020-09-21 19:15:57 +08:00
* \ image html JKQTPGeometricPlotElement_DrawAsMathematicalCurve . png
- 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-09-21 19:15:57 +08:00
* \ image html JKQTPGeometricPlotElement_DrawAsGraphicElement . png
- 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
*
* \ see DrawMode , setDrawMode ( ) , getDrawMode ( )
*/
2020-09-21 19:15:57 +08:00
DrawMode m_drawMode ;
} ;
/** \brief this is the virtual base class of all JKQTPPlotElement's in a JKQTPlotter plot that
* represent annotations of a plot . It differs from JKQTPGeometricPlotElement by not providing a
* selection of drawModes , as annotations are always drawn as graphic elements .
* \ ingroup jkqtplotter_basegraphs
*
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPPlotAnnotationElement : public JKQTPPlotElement {
Q_OBJECT
public :
/** \brief class constructor */
explicit JKQTPPlotAnnotationElement ( JKQTBasePlotter * parent = nullptr ) ;
/** \brief default wirtual destructor */
virtual ~ JKQTPPlotAnnotationElement ( ) ;
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-21 19:15:57 +08:00
protected :
2018-12-28 05:52:00 +08:00
} ;
2020-09-19 01:11:50 +08:00
/** \brief This virtual JKQTPGraph descendent may be used as base for all graphs that use at least two columns
* that specify x and y coordinates for the single plot points .
* \ ingroup jkqtplotter_basegraphs
*
* This class implements basic management facilities for the data columns :
* - setXColumn ( ) , setYColumn ( ) to set the columns to be used for the graph data
* - setDataSortOrder ( ) to specify whether and how the data should be sorted before drawing
* \ image html jkqtplotter_unsorted . png " Unsorted Data "
* \ image html jkqtplotter_sortedx . png " Data sorted along x-axis (DataSortOrder::SortedX) "
* .
*
* . . . and overrides / implements the functions :
* - getXMinMax ( )
* - getYMinMax ( )
2020-09-19 01:35:53 +08:00
* - usesColumn ( )
2020-09-19 01:11:50 +08:00
* .
*
2018-11-25 21:53:26 +08:00
*/
2019-06-22 20:21:32 +08:00
class JKQTPLOTTER_LIB_EXPORT JKQTPXYGraph : public JKQTPGraph {
2020-09-19 01:35:53 +08:00
Q_OBJECT
public :
/** \brief specifies how to sort the data in a JKQTPXYGraph before drawing
*
* \ image html jkqtplotter_unsorted . png " Unsorted Data "
*
* \ image html jkqtplotter_sortedx . png " Data sorted along x-axis (DataSortOrder::SortedX) "
*/
enum DataSortOrder {
Unsorted = 0 , /*!< \brief the data for a JKQTPXYGraph is not sorted before drawing */
SortedX = 1 , /*!< \brief the data for a JKQTPXYGraph is sorted so the x-values appear in ascending before drawing */
SortedY = 2 /*!< \brief the data for a JKQTPXYGraph is sorted so the y-values appear in ascending before drawing */
} ;
Q_ENUM ( DataSortOrder )
/** \brief class constructor */
JKQTPXYGraph ( JKQTBasePlotter * parent = nullptr ) ;
2024-02-05 05:06:09 +08:00
/** \copydoc JKQTPPlotElement::getXMinMax() */
2020-09-19 01:35:53 +08:00
virtual bool getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) override ;
2024-02-05 05:06:09 +08:00
/** \copydoc JKQTPPlotElement::getYMinMax() */
2020-09-19 01:35:53 +08:00
virtual bool getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) override ;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn ( int column ) const override ;
2020-09-21 19:47:54 +08:00
/** \copydoc xColumn */
2020-09-19 01:35:53 +08:00
int getXColumn ( ) const ;
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn */
2020-09-19 01:35:53 +08:00
int getYColumn ( ) const ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2020-09-19 01:35:53 +08:00
DataSortOrder getDataSortOrder ( ) const ;
2022-09-10 19:38:29 +08:00
/** \brief returns the column used as "key" for the current graph (typically this call getXColumn(), but for horizontal graphs like filled curves or barcharts it may call getYColumn() ) */
virtual int getKeyColumn ( ) const ;
/** \brief returns the column used as "value" for the current graph (typically this call getXColumn(), but for horizontal graphs like filled curves or barcharts it may call getYColumn() ) */
virtual int getValueColumn ( ) const ;
2020-09-19 01:35:53 +08:00
Q_PROPERTY ( DataSortOrder sortData READ getDataSortOrder WRITE setDataSortOrder )
Q_PROPERTY ( int xColumn READ getXColumn WRITE setXColumn )
Q_PROPERTY ( int yColumn READ getYColumn WRITE setYColumn )
/** \brief Implmentation of JKQTPPlotElement::hitTest(), which searches through all graph points defined by xColumn and yColumn
* and returns a general x / y - label , also taking into account possibly known errors to the graphs ( if it is derived
* from JKQTPXGraphErrorData and / or JKQTPYGraphErrorData
*
* \ note This function first checks whether JKQTPPlotElement : : hitTest ( ) returns any result , so you can use the basic implementation
* in JKQTPPlotElement to override the behaviour here , by simply calling addHitTestData ( ) during your draw ( ) implementation
*
* \ see See JKQTPPlotElement : : hitTest ( ) for details on the function definition !
*/
virtual double hitTest ( const QPointF & posSystem , QPointF * closestSpotSystem = nullptr , QString * label = nullptr , HitTestMode mode = HitTestXY ) const override ;
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-19 01:35:53 +08:00
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( size_t xCol , size_t yCol ) ;
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( int xCol , int yCol ) ;
2022-04-21 16:57:24 +08:00
# if QT_VERSION<QT_VERSION_CHECK(6,0,0)
2020-09-19 01:35:53 +08:00
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( std : : pair < int , int > xyColPair ) ;
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( std : : pair < size_t , size_t > xyColPair ) ;
2022-04-21 16:57:24 +08:00
# endif
2020-09-19 01:35:53 +08:00
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( QPair < int , int > xyColPair ) ;
/** \brief sets xColumn and yColumn at the same time */
void setXYColumns ( QPair < size_t , size_t > xyColPair ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2020-09-19 01:35:53 +08:00
void setDataSortOrder ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2020-09-19 01:35:53 +08:00
void setDataSortOrder ( DataSortOrder __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc xColumn */
2020-09-19 01:35:53 +08:00
void setXColumn ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc xColumn */
2020-09-19 01:35:53 +08:00
void setXColumn ( size_t __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn */
2020-09-19 01:35:53 +08:00
void setYColumn ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn */
2020-09-19 01:35:53 +08:00
void setYColumn ( size_t __value ) ;
2022-09-10 19:38:29 +08:00
/** \brief sets the column used as "key" for the current graph (typically this call setXColumn(), but for horizontal graphs like filled curves or barcharts it may call setYColumn() ) */
virtual void setKeyColumn ( int __value ) ;
/** \brief sets the column used as "value" for the current graph (typically this call setXColumn(), but for horizontal graphs like filled curves or barcharts it may call setYColumn() ) */
virtual void setValueColumn ( int __value ) ;
2020-09-19 01:35:53 +08:00
protected :
/** \brief the column that contains the x-component of the datapoints */
int xColumn ;
/** \brief the column that contains the y-component of the datapoints */
int yColumn ;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData ;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector < int > sortedIndices ;
/** \brief sorts data according to the specified criterion in \a sortData ... The result is stored as a index-map in sorted Indices */
virtual void intSortData ( ) ;
/** \brief returns the index of the i-th datapoint (where i is an index into the SORTED datapoints)
*
* This function can beu used to get the correct datapoint after sorting the datapoints ,
* As sorting is done by sorting an index and not reordering the data in the columns themselves .
*
* \ see setDataSortOrder ( ) , getDataSortOrder ( )
* */
2020-09-19 04:03:12 +08:00
inline int getDataIndex ( int i ) const {
2020-09-19 01:35:53 +08:00
if ( sortData = = Unsorted ) return i ;
return sortedIndices . value ( i , i ) ;
}
/** \brief determines the range of row indexes available in the data columns of this graph
*
* \ param [ out ] imin first usable row - index
* \ param [ out ] imax last usable row - index
* \ return \ c true on success and \ c false if the information is not available
*/
virtual bool getIndexRange ( int & imin , int & imax ) const ;
} ;
2018-11-25 21:53:26 +08:00
2020-09-19 21:08:32 +08:00
/** \brief This virtual JKQTPGraph descendent extends JKQTPXYGraph adds a baseline-property, which is necessary, e.g. for barcharts, filled graphs to indicate until where to draw the bar or fill the curve (default is 0).
* \ ingroup jkqtplotter_basegraphs
*
* \ see JKQTPSpecialLineHorizontalGraph , JKQTPBarVerticalGraph , JKQTPImpulsesHorizontalGraph , . . .
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYBaselineGraph : public JKQTPXYGraph {
Q_OBJECT
public :
/** \brief class constructor */
JKQTPXYBaselineGraph ( JKQTBasePlotter * parent = nullptr ) ;
/** \copydoc m_baseline */
double getBaseline ( ) const ;
Q_PROPERTY ( double baseline READ getBaseline WRITE setBaseline )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-19 21:08:32 +08:00
/** \copydoc m_baseline */
void setBaseline ( double __value ) ;
protected :
2022-11-03 22:48:48 +08:00
/** \brief can be called by JKQTPGraph::getXMinMax() or JKQTPGraph::getYMinMax() calculates min/max/... for data from the given column, including the baseline */
bool getMinMaxWithBaseline ( int dataColumn , double & minv , double & maxv , double & smallestGreaterZero ) ;
/** \brief can be called by JKQTPGraph::getXMinMax() or JKQTPGraph::getYMinMax() calculates min/max/... for data from the given column, including the baseline and an optional error */
bool getMinMaxWithErrorsAndBaseline ( int dataColumn , int errorColumn , int errorColumnLower , bool errorSymmetric , double & minv , double & maxv , double & smallestGreaterZero ) ;
2020-09-19 21:08:32 +08:00
/** \brief baseline of the plot (NOTE: 0 is interpreted as until plot border in log-mode!!!)
*
* \ image html impulsesplot_baseline . png
*/
double m_baseline ;
2022-11-03 22:48:48 +08:00
private :
/** \brief returns the upper error for the i-th datapoint, read from datastore \a ds */
double getErrorU ( int i , const JKQTPDatastore * ds , int xErrorColumn ) const ;
/** \brief returns the lower error for the i-th datapoint, read from datastore \a ds */
double getErrorL ( int i , const JKQTPDatastore * ds , int xErrorColumn , int xErrorColumnLower , bool xErrorSymmetric ) const ;
2020-09-19 21:08:32 +08:00
} ;
2020-09-19 01:35:53 +08:00
/** \brief This virtual JKQTPGraph descendent extends JKQTPXYGraph to two columns for y-values (e.g. for filled range plots in JKQTPFilledVerticalRangeGraph).
* \ ingroup jkqtplotter_basegraphs
*
* \ see JKQTPXXYGraph and e . g . JKQTPFilledVerticalRangeGraph
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYYGraph : public JKQTPXYGraph {
Q_OBJECT
public :
2018-11-25 21:53:26 +08:00
2020-09-19 01:35:53 +08:00
/** \brief class constructor */
JKQTPXYYGraph ( JKQTBasePlotter * parent = nullptr ) ;
2018-11-25 21:53:26 +08:00
2024-02-05 05:06:09 +08:00
/** \copydoc JKQTPPlotElement::getYMinMax() */
2020-09-19 01:35:53 +08:00
virtual bool getYMinMax ( double & miny , double & maxy , double & smallestGreaterZero ) override ;
2019-05-13 04:22:48 +08:00
2020-09-19 01:35:53 +08:00
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn ( int column ) const override ;
2019-05-06 01:31:20 +08:00
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn2 */
2020-09-19 01:35:53 +08:00
int getYColumn2 ( ) const ;
2022-09-10 19:38:29 +08:00
/** \brief returns the column used as secondary "value" for the current graph (typically this call getXColumn(), but for horizontal graphs like filled curves or barcharts it may call getYColumn() ) */
virtual int getValue2Column ( ) const ;
2018-11-25 21:53:26 +08:00
2020-09-19 01:35:53 +08:00
/** \copydoc JKQTPXYGraph::hitTest() */
virtual double hitTest ( const QPointF & posSystem , QPointF * closestSpotSystem = nullptr , QString * label = nullptr , HitTestMode mode = HitTestXY ) const override ;
2019-05-06 01:31:20 +08:00
2020-09-19 01:35:53 +08:00
Q_PROPERTY ( int yColumn2 READ getYColumn2 WRITE setYColumn2 )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-19 01:35:53 +08:00
/** \brief sets xColumn, yColumn and yColumn2 at the same time */
void setXYYColumns ( size_t xCol , size_t yCol , size_t y2Col ) ;
/** \brief sets xColumn, yColumn and yColumn2 at the same time */
void setXYYColumns ( int xCol , int yCol , int y2Col ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn2 */
2020-09-19 01:35:53 +08:00
void setYColumn2 ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc yColumn2 */
2020-09-19 01:35:53 +08:00
void setYColumn2 ( size_t __value ) ;
2022-09-10 19:38:29 +08:00
/** \brief sets the column used as secondary "value" for the current graph (typically this call setXColumn(), but for horizontal graphs like filled curves or barcharts it may call setYColumn() ) */
virtual void setValue2Column ( int __value ) ;
2020-09-19 01:35:53 +08:00
protected :
/** \brief the column that contains the second y-component of the datapoints */
int yColumn2 ;
/** \brief determines the range of row indexes available in the data columns of this graph
*
* \ param [ out ] imin first usable row - index
* \ param [ out ] imax last usable row - index
* \ return \ c true on success and \ c false if the information is not available
*/
2020-09-19 04:03:12 +08:00
virtual bool getIndexRange ( int & imin , int & imax ) const override ;
2018-11-25 21:53:26 +08:00
} ;
2020-09-19 01:35:53 +08:00
/** \brief This virtual JKQTPGraph descendent extends JKQTPXYGraph to two columns for x-values (e.g. for filled range plots).
* \ ingroup jkqtplotter_basegraphs
*
* \ see JKQTPXYYGraph and e . g . JKQTPFilledVerticalRangeGraph
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXXYGraph : public JKQTPXYGraph {
Q_OBJECT
public :
/** \brief class constructor */
JKQTPXXYGraph ( JKQTBasePlotter * parent = nullptr ) ;
2024-02-05 05:06:09 +08:00
/** \copydoc JKQTPPlotElement::getXMinMax() */
2020-09-19 01:35:53 +08:00
virtual bool getXMinMax ( double & minx , double & maxx , double & smallestGreaterZero ) override ;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn ( int column ) const override ;
2020-09-21 19:47:54 +08:00
/** \copydoc xColumn2 */
2020-09-19 01:35:53 +08:00
int getXColumn2 ( ) const ;
2022-09-10 19:38:29 +08:00
/** \brief returns the column used as "key" for the current graph (typically this call getXColumn(), but for horizontal graphs like filled curves or barcharts it may call getYColumn() ) */
virtual int getKey2Column ( ) const ;
2020-09-19 01:35:53 +08:00
/** \copydoc JKQTPXYGraph::hitTest() */
virtual double hitTest ( const QPointF & posSystem , QPointF * closestSpotSystem = nullptr , QString * label = nullptr , HitTestMode mode = HitTestXY ) const override ;
Q_PROPERTY ( int xColumn2 READ getXColumn2 WRITE setXColumn2 )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-19 01:35:53 +08:00
/** \brief sets xColumn, yColumn and xColumn2 at the same time */
void setXXYColumns ( size_t xCol , size_t x2Col , size_t yCol ) ;
/** \brief sets xColumn, yColumn and xColumn2 at the same time */
void setXXYColumns ( int xCol , int x2Col , int yCol ) ;
2022-04-24 19:23:59 +08:00
/** \copydoc xColumn2 */
2020-09-19 01:35:53 +08:00
void setXColumn2 ( int __value ) ;
2022-04-24 19:23:59 +08:00
/** \copydoc xColumn2 */
2020-09-19 01:35:53 +08:00
void setXColumn2 ( size_t __value ) ;
2022-09-10 19:38:29 +08:00
/** \brief sets the column used as "key" for the current graph (typically this call setXColumn(), but for horizontal graphs like filled curves or barcharts it may call setYColumn() ) */
virtual void setKey2Column ( int __value ) ;
2020-09-19 01:35:53 +08:00
protected :
/** \brief the column that contains the second y-component of the datapoints */
int xColumn2 ;
/** \brief determines the range of row indexes available in the data columns of this graph
*
* \ param [ out ] imin first usable row - index
* \ param [ out ] imax last usable row - index
* \ return \ c true on success and \ c false if the information is not available
*/
2020-09-19 04:03:12 +08:00
virtual bool getIndexRange ( int & imin , int & imax ) const override ;
2020-09-19 01:35:53 +08:00
} ;
2018-11-25 21:53:26 +08:00
2019-02-03 21:04:48 +08:00
2020-09-19 01:11:50 +08:00
/** \brief This virtual JKQTPGraph descendent may be used as base for all graphs that use at least one column
* of data
* \ ingroup jkqtplotter_basegraphs
*
*
* \ see \ ref jkqtplotter_graphsgroup_classstructure
*
2018-11-25 21:53:26 +08:00
*/
2019-06-22 20:21:32 +08:00
class JKQTPLOTTER_LIB_EXPORT JKQTPSingleColumnGraph : public JKQTPGraph {
2018-11-25 21:53:26 +08:00
Q_OBJECT
public :
2019-02-03 21:04:48 +08:00
/** \brief specifies how to sort the data for a JKQTPSingleColumnGraph before drawing
*
* \ image html jkqtplotter_unsorted . png " Unsorted Data "
*
* \ image html jkqtplotter_sortedx . png " Data sorted along x-axis (DataSortOrder::SortedX) "
*/
2018-11-25 21:53:26 +08:00
enum DataSortOrder {
2019-02-03 21:04:48 +08:00
Unsorted = 0 , /*!< \brief the data for a JKQTPSingleColumnGraph is not sorted before drawing */
Sorted = 1 /*!< \brief the data for a JKQTPSingleColumnGraph is sorted (in ascending order) before drawing */
2018-11-25 21:53:26 +08:00
} ;
2020-09-19 01:11:50 +08:00
Q_ENUM ( DataSortOrder )
2019-01-20 23:15:10 +08:00
2019-02-03 21:04:48 +08:00
/** \brief specifies whether the data for a JKQTPSingleColumnGraph represent x-axis or y-axis values */
2019-01-20 23:15:10 +08:00
enum class DataDirection {
2019-02-03 21:04:48 +08:00
X , /*!< \brief the data for a JKQTPSingleColumnGraph is data belonging to the x-axis of the plot */
Y /*!< \brief the data for a JKQTPSingleColumnGraph is data belonging to the y-axis of the plot */
2019-01-20 23:15:10 +08:00
} ;
2020-09-19 01:11:50 +08:00
Q_ENUM ( DataDirection )
2019-01-20 23:15:10 +08:00
2018-11-25 21:53:26 +08:00
/** \brief class constructor */
2019-01-20 17:49:29 +08:00
JKQTPSingleColumnGraph ( JKQTBasePlotter * parent = nullptr ) ;
2018-11-25 21:53:26 +08:00
2020-09-21 19:47:54 +08:00
/** \copydoc dataColumn */
2019-04-22 19:27:50 +08:00
int getDataColumn ( ) const ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2019-04-22 19:27:50 +08:00
DataSortOrder getDataSortOrder ( ) const ;
2018-11-25 21:53:26 +08:00
2019-04-22 19:27:50 +08:00
2020-09-21 19:47:54 +08:00
/** \copydoc dataDirection */
2019-04-22 19:27:50 +08:00
DataDirection getDataDirection ( ) const ;
2019-01-20 17:49:29 +08:00
/** \copydoc JKQTPGraph::usesColumn() */
2018-12-28 05:52:00 +08:00
virtual bool usesColumn ( int c ) const override ;
2018-11-25 21:53:26 +08:00
2020-09-19 01:11:50 +08:00
Q_PROPERTY ( DataSortOrder sortData READ getDataSortOrder WRITE setDataSortOrder )
Q_PROPERTY ( int dataColumn READ getDataColumn WRITE setDataColumn )
Q_PROPERTY ( DataDirection dataDirection READ getDataDirection WRITE setDataDirection )
2023-07-22 20:26:02 +08:00
public Q_SLOTS :
2020-09-21 19:47:54 +08:00
/** \copydoc dataColumn */
2020-09-19 01:11:50 +08:00
void setDataColumn ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc dataColumn */
2020-09-19 01:11:50 +08:00
void setDataColumn ( size_t __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc dataDirection */
2020-09-19 01:11:50 +08:00
void setDataDirection ( DataDirection __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2020-09-19 01:11:50 +08:00
void setDataSortOrder ( int __value ) ;
2020-09-21 19:47:54 +08:00
/** \copydoc sortData */
2020-09-19 01:11:50 +08:00
void setDataSortOrder ( DataSortOrder __value ) ;
2018-11-25 21:53:26 +08:00
protected :
/** \brief the column that contains the datapoints */
int dataColumn ;
2019-04-22 19:27:50 +08:00
/** \brief interpret the data from dataColumn either as X- or Y-data */
DataDirection dataDirection ;
2018-11-25 21:53:26 +08:00
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData ;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector < int > sortedIndices ;
virtual void intSortData ( ) ;
2018-12-28 05:52:00 +08:00
/** \brief returns the index of the i-th datapoint (where i is an index into the SORTED datapoints)
*
* This function can beu used to get the correct datapoint after sorting the datapoints ,
* As sorting is done by sorting an index and not reordering the data in the columns themselves .
* */
2020-09-19 04:03:12 +08:00
inline int getDataIndex ( int i ) const {
2018-11-25 21:53:26 +08:00
if ( sortData = = Unsorted ) return i ;
return sortedIndices . value ( i , i ) ;
}
2019-05-06 01:31:20 +08:00
/** \brief determines the range of row indexes available in the data columns of this graph
*
* \ param [ out ] imin first usable row - index
* \ param [ out ] imax last usable row - index
* \ return \ c true on success and \ c false if the information is not available
*/
virtual bool getIndexRange ( int & imin , int & imax ) const ;
2018-12-28 05:52:00 +08:00
2018-11-25 21:53:26 +08:00
} ;
2019-02-08 00:24:46 +08:00
# endif // JKQTPGRAPHSBASE_H