-
Notifications
You must be signed in to change notification settings - Fork 13
/
qcustomplot.h
2171 lines (1899 loc) · 84.2 KB
/
qcustomplot.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***************************************************************************
** **
** QCustomPlot, a simple to use, modern plotting widget for Qt **
** Copyright (C) 2012 Emanuel Eichhammer **
** **
** This program is free software: you can redistribute it and/or modify **
** it under the terms of the GNU General Public License as published by **
** the Free Software Foundation, either version 3 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 General Public License for more details. **
** **
** You should have received a copy of the GNU General Public License **
** along with this program. If not, see http://www.gnu.org/licenses/. **
** **
****************************************************************************
** Author: Emanuel Eichhammer **
** Website/Contact: http://www.WorksLikeClockwork.com/ **
** Date: 09.06.12 **
****************************************************************************/
/*! \file */
#ifndef QCUSTOMPLOT_H
#define QCUSTOMPLOT_H
#include <QObject>
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QPixmap>
#include <QVector>
#include <QString>
#include <QPrinter>
#include <QDateTime>
#include <QMultiMap>
#include <QFlags>
#include <QDebug>
#include <QVector2D>
#include <QStack>
#include <qmath.h>
#include <limits>
// decl definitions for shared library compilation/usage:
#if defined(QCUSTOMPLOT_COMPILE_LIBRARY)
# define QCP_LIB_DECL Q_DECL_EXPORT
#elif defined(QCUSTOMPLOT_USE_LIBRARY)
# define QCP_LIB_DECL Q_DECL_IMPORT
#else
# define QCP_LIB_DECL
#endif
class QCustomPlot;
class QCPLegend;
class QCPRange;
class QCPLayerable;
class QCPAbstractItem;
class QCPItemPosition;
class QCPAxis;
class QCPData;
/*!
The QCP Namespace contains general enums and QFlags
*/
namespace QCP
{
/*!
Defines the symbol used for scatter points.
On plottables/items that draw scatters, the sizes of these visualizations (with exception of \ref
QCP::ssDot and \ref QCP::ssPixmap) can be controlled with a \a setScatterSize function. Scatters
are in general drawn with the main pen set on the plottable/item.
\see QCPGraph::setScatterStyle, QCPStatisticalBox::setOutlierStyle
*/
enum ScatterStyle { ssNone ///< no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines)
,ssDot ///< a single pixel
,ssCross ///< a cross (x)
,ssPlus ///< a plus (+)
,ssCircle ///< a circle which is not filled
,ssDisc ///< a circle which is filled with the color of the pen (not the brush!)
,ssSquare ///< a square which is not filled
,ssDiamond ///< a diamond which is not filled
,ssStar ///< a star with eight arms, i.e. a combination of cross and plus
,ssTriangle ///< an equilateral triangle which is not filled, standing on baseline
,ssTriangleInverted ///< an equilateral triangle which is not filled, standing on corner
,ssCrossSquare ///< a square which is not filled, with a cross inside
,ssPlusSquare ///< a square which is not filled, with a plus inside
,ssCrossCircle ///< a circle which is not filled, with a cross inside
,ssPlusCircle ///< a circle which is not filled, with a plus inside
,ssPeace ///< a circle which is not filled, with one vertical and two downward diagonal lines
,ssPixmap ///< a custom pixmap specified by setScatterPixmap, centered on the data point coordinates
};
/*!
Defines what elements of a plot can be forcibly drawn antialiased/not antialiased. If an
element is neither forcibly drawn antialiased nor forcibly drawn not antialiased, it is up to
the respective element how it is drawn. Typically it provides a \a setAntialiased function for
this.
\c AntialiasedElements is a flag of or-combined elements of this enum type.
\see QCustomPlot::setAntialiasedElements, QCustomPlot::setNotAntialiasedElements
*/
enum AntialiasedElement { aeAxes = 0x0001 ///< <tt>0x0001</tt> Axis base line and tick marks
,aeGrid = 0x0002 ///< <tt>0x0002</tt> Grid lines
,aeSubGrid = 0x0004 ///< <tt>0x0004</tt> Sub grid lines
,aeLegend = 0x0008 ///< <tt>0x0008</tt> Legend box
,aeLegendItems = 0x0010 ///< <tt>0x0010</tt> Legend items
,aePlottables = 0x0020 ///< <tt>0x0020</tt> Main lines of plottables (excluding error bars, see element \ref aeErrorBars)
,aeItems = 0x0040 ///< <tt>0x0040</tt> Main lines of items
,aeScatters = 0x0080 ///< <tt>0x0080</tt> Scatter symbols of plottables (excluding scatter symbols of type ssPixmap)
,aeErrorBars = 0x0100 ///< <tt>0x0100</tt> Error bars
,aeFills = 0x0200 ///< <tt>0x0200</tt> Borders of fills (e.g. under or between graphs)
,aeZeroLine = 0x0400 ///< <tt>0x0400</tt> Zero-lines, see \ref QCPAxis::setZeroLinePen
,aeAll = 0xFFFF ///< <tt>0xFFFF</tt> All elements
,aeNone = 0x0000 ///< <tt>0x0000</tt> No elements
};
Q_DECLARE_FLAGS(AntialiasedElements, AntialiasedElement)
/*!
Defines plotting hints that control various aspects of the quality and speed of plotting.
\see QCustomPlot::setPlottingHints
*/
enum PlottingHint { phNone = 0x000 ///< <tt>0x000</tt> No hints are set
,phFastPolylines = 0x001 ///< <tt>0x001</tt> Graph/Curve lines are drawn with a faster method. This reduces the quality
///< especially of the line segment joins. (Only used for solid line pens.)
,phForceRepaint = 0x002 ///< <tt>0x002</tt> causes an immediate repaint() instead of a soft update() when QCustomPlot::replot() is called. This is set by default
///< on Windows-Systems to prevent the plot from freezing on fast consecutive replots (e.g. user drags ranges with mouse).
};
Q_DECLARE_FLAGS(PlottingHints, PlottingHint)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::AntialiasedElements)
Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::PlottingHints)
class QCP_LIB_DECL QCPData
{
public:
QCPData();
QCPData(double key, double value);
double key, value;
double keyErrorPlus, keyErrorMinus;
double valueErrorPlus, valueErrorMinus;
};
Q_DECLARE_TYPEINFO(QCPData, Q_MOVABLE_TYPE);
/*! \typedef QCPDataMap
Container for storing QCPData items in a sorted fashion. The key of the map
is the key member of the QCPData instance.
This is the container in which QCPGraph holds its data.
\see QCPData, QCPGraph::setData
*/
typedef QMap<double, QCPData> QCPDataMap;
typedef QMapIterator<double, QCPData> QCPDataMapIterator;
typedef QMutableMapIterator<double, QCPData> QCPDataMutableMapIterator;
class QCP_LIB_DECL QCPCurveData
{
public:
QCPCurveData();
QCPCurveData(double t, double key, double value);
double t, key, value;
};
Q_DECLARE_TYPEINFO(QCPCurveData, Q_MOVABLE_TYPE);
/*! \typedef QCPCurveDataMap
Container for storing QCPCurveData items in a sorted fashion. The key of the map
is the t member of the QCPCurveData instance.
This is the container in which QCPCurve holds its data.
\see QCPCurveData, QCPCurve::setData
*/
typedef QMap<double, QCPCurveData> QCPCurveDataMap;
typedef QMapIterator<double, QCPCurveData> QCPCurveDataMapIterator;
typedef QMutableMapIterator<double, QCPCurveData> QCPCurveDataMutableMapIterator;
class QCP_LIB_DECL QCPBarData
{
public:
QCPBarData();
QCPBarData(double key, double value);
double key, value;
};
Q_DECLARE_TYPEINFO(QCPBarData, Q_MOVABLE_TYPE);
/*! \typedef QCPBarDataMap
Container for storing QCPBarData items in a sorted fashion. The key of the map
is the key member of the QCPBarData instance.
This is the container in which QCPBars holds its data.
\see QCPBarData, QCPBars::setData
*/
typedef QMap<double, QCPBarData> QCPBarDataMap;
typedef QMapIterator<double, QCPBarData> QCPBarDataMapIterator;
typedef QMutableMapIterator<double, QCPBarData> QCPBarDataMutableMapIterator;
class QCP_LIB_DECL QCPPainter : public QPainter
{
public:
QCPPainter();
QCPPainter(QPaintDevice *device);
~QCPPainter();
// getters:
QPixmap scatterPixmap() const { return mScatterPixmap; }
bool antialiasing() const { return testRenderHint(QPainter::Antialiasing); }
bool pdfExportMode() const { return mPdfExportMode; }
bool scaledExportMode() const { return mScaledExportMode; }
// setters:
void setScatterPixmap(const QPixmap pm);
void setAntialiasing(bool enabled);
void setPdfExportMode(bool enabled);
void setScaledExportMode(bool enabled);
// methods hiding non-virtual base class functions (QPainter bug workarounds):
void setPen(const QPen &pen);
void setPen(const QColor &color);
void setPen(Qt::PenStyle penStyle);
void drawLine(const QLineF &line);
void drawLine(const QPointF &p1, const QPointF &p2) {drawLine(QLineF(p1, p2));}
void save();
void restore();
// helpers:
void fixScaledPen();
void drawScatter(double x, double y, double size, QCP::ScatterStyle style);
protected:
QPixmap mScatterPixmap;
bool mScaledExportMode;
bool mPdfExportMode;
bool mIsAntialiasing;
QStack<bool> mAntialiasingStack;
};
class QCP_LIB_DECL QCPLineEnding
{
public:
/*!
Defines the type of ending decoration for line-like items, e.g. an arrow.
\image html QCPLineEnding.png
The width and length of these decorations can be controlled with the functions \ref setWidth
and \ref setLength. Some decorations like \ref esDisc, \ref esSquare, \ref esDiamond and \ref esBar only
support a width, the length property is ignored.
\see QCPItemLine::setHead, QCPItemLine::setTail, QCPItemCurve::setHead, QCPItemCurve::setTail
*/
enum EndingStyle { esNone ///< No ending decoration
,esFlatArrow ///< A filled arrow head with a straight/flat back (a triangle)
,esSpikeArrow ///< A filled arrow head with an indented back
,esLineArrow ///< A non-filled arrow head with open back
,esDisc ///< A filled circle
,esSquare ///< A filled square
,esDiamond ///< A filled diamond (45° rotated square)
,esBar ///< A bar perpendicular to the line
};
QCPLineEnding();
QCPLineEnding(EndingStyle style, double width=8, double length=10, bool inverted=false);
// getters:
EndingStyle style() const { return mStyle; }
double width() const { return mWidth; }
double length() const { return mLength; }
bool inverted() const { return mInverted; }
// setters:
void setStyle(EndingStyle style);
void setWidth(double width);
void setLength(double length);
void setInverted(bool inverted);
// non-property methods:
double boundingDistance() const;
void draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const;
void draw(QCPPainter *painter, const QVector2D &pos, double angle) const;
protected:
EndingStyle mStyle;
double mWidth, mLength;
bool mInverted;
};
Q_DECLARE_TYPEINFO(QCPLineEnding, Q_MOVABLE_TYPE);
class QCP_LIB_DECL QCPLayer
{
public:
QCPLayer(QCustomPlot* parentPlot, const QString &layerName);
~QCPLayer();
// getters:
QCustomPlot *parentPlot() const { return mParentPlot; }
QString name() const { return mName; }
int index() const;
QList<QCPLayerable*> children() const { return mChildren; }
protected:
QCustomPlot *mParentPlot;
QString mName;
QList<QCPLayerable*> mChildren;
void addChild(QCPLayerable *layerable, bool prepend);
void removeChild(QCPLayerable *layerable);
private:
Q_DISABLE_COPY(QCPLayer)
friend class QCPLayerable;
};
class QCP_LIB_DECL QCPLayerable : public QObject
{
Q_OBJECT
public:
QCPLayerable(QCustomPlot *parentPlot);
~QCPLayerable();
// getters:
bool visible() const { return mVisible; }
QCustomPlot *parentPlot() const { return mParentPlot; }
QCPLayer *layer() const { return mLayer; }
bool antialiased() const { return mAntialiased; }
// setters:
void setVisible(bool on);
bool setLayer(QCPLayer *layer);
bool setLayer(const QString &layerName);
void setAntialiased(bool enabled);
protected:
bool mVisible;
QCustomPlot *mParentPlot;
QCPLayer *mLayer;
bool mAntialiased;
// non-property methods:
bool moveToLayer(QCPLayer *layer, bool prepend);
void applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const;
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const = 0;
virtual QRect clipRect() const;
virtual void draw(QCPPainter *painter) = 0;
private:
Q_DISABLE_COPY(QCPLayerable)
friend class QCustomPlot;
};
class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable
{
Q_OBJECT
public:
QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis);
virtual ~QCPAbstractPlottable() {}
// getters:
QString name() const { return mName; }
bool antialiasedFill() const { return mAntialiasedFill; }
bool antialiasedScatters() const { return mAntialiasedScatters; }
bool antialiasedErrorBars() const { return mAntialiasedErrorBars; }
QPen pen() const { return mPen; }
QPen selectedPen() const { return mSelectedPen; }
QBrush brush() const { return mBrush; }
QBrush selectedBrush() const { return mSelectedBrush; }
QCPAxis *keyAxis() const { return mKeyAxis; }
QCPAxis *valueAxis() const { return mValueAxis; }
bool selectable() const { return mSelectable; }
bool selected() const { return mSelected; }
// setters:
void setName(const QString &name);
void setAntialiasedFill(bool enabled);
void setAntialiasedScatters(bool enabled);
void setAntialiasedErrorBars(bool enabled);
void setPen(const QPen &pen);
void setSelectedPen(const QPen &pen);
void setBrush(const QBrush &brush);
void setSelectedBrush(const QBrush &brush);
void setKeyAxis(QCPAxis *axis);
void setValueAxis(QCPAxis *axis);
void setSelectable(bool selectable);
void setSelected(bool selected);
// non-property methods:
void rescaleAxes(bool onlyEnlarge=false) const;
void rescaleKeyAxis(bool onlyEnlarge=false) const;
void rescaleValueAxis(bool onlyEnlarge=false) const;
virtual void clearData() = 0;
virtual double selectTest(const QPointF &pos) const = 0;
virtual bool addToLegend();
virtual bool removeFromLegend() const;
signals:
void selectionChanged(bool selected);
protected:
/*!
Represents negative and positive sign domain for passing to \ref getKeyRange and \ref getValueRange.
*/
enum SignDomain { sdNegative ///< The negative sign domain, i.e. numbers smaller than zero
,sdBoth ///< Both sign domains, including zero, i.e. all (rational) numbers
,sdPositive ///< The positive sign domain, i.e. numbers greater than zero
};
QString mName;
bool mAntialiasedFill, mAntialiasedScatters, mAntialiasedErrorBars;
QPen mPen, mSelectedPen;
QBrush mBrush, mSelectedBrush;
QCPAxis *mKeyAxis, *mValueAxis;
bool mSelected, mSelectable;
virtual QRect clipRect() const;
virtual void draw(QCPPainter *painter) = 0;
virtual void drawLegendIcon(QCPPainter *painter, const QRect &rect) const = 0;
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const = 0;
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const = 0;
// painting and coordinate transformation helpers:
void coordsToPixels(double key, double value, double &x, double &y) const;
const QPointF coordsToPixels(double key, double value) const;
void pixelsToCoords(double x, double y, double &key, double &value) const;
void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const;
QPen mainPen() const;
QBrush mainBrush() const;
void applyDefaultAntialiasingHint(QCPPainter *painter) const;
void applyFillAntialiasingHint(QCPPainter *painter) const;
void applyScattersAntialiasingHint(QCPPainter *painter) const;
void applyErrorBarsAntialiasingHint(QCPPainter *painter) const;
// selection test helpers:
double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const;
private:
Q_DISABLE_COPY(QCPAbstractPlottable)
friend class QCustomPlot;
friend class QCPPlottableLegendItem;
};
class QCP_LIB_DECL QCPGraph : public QCPAbstractPlottable
{
Q_OBJECT
public:
/*!
Defines how the graph's line is represented visually in the plot. The line is drawn with the
current pen of the graph (\ref setPen).
\see setLineStyle
*/
enum LineStyle { lsNone ///< data points are not connected with any lines (e.g. data only represented
///< with symbols according to the scatter style, see \ref setScatterStyle)
,lsLine ///< data points are connected by a straight line
,lsStepLeft ///< line is drawn as steps where the step height is the value of the left data point
,lsStepRight ///< line is drawn as steps where the step height is the value of the right data point
,lsStepCenter ///< line is drawn as steps where the step is in between two data points
,lsImpulse ///< each data point is represented by a line parallel to the value axis, which reaches from the data point to the zero-value-line
};
Q_ENUMS(LineStyle)
/*!
Defines what kind of error bars are drawn for each data point
*/
enum ErrorType { etNone ///< No error bars are shown
,etKey ///< Error bars for the key dimension of the data point are shown
,etValue ///< Error bars for the value dimension of the data point are shown
,etBoth ///< Error bars for both key and value dimensions of the data point are shown
};
Q_ENUMS(ErrorType)
explicit QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis);
virtual ~QCPGraph();
// getters:
const QCPDataMap *data() const { return mData; }
LineStyle lineStyle() const { return mLineStyle; }
QCP::ScatterStyle scatterStyle() const { return mScatterStyle; }
double scatterSize() const { return mScatterSize; }
const QPixmap scatterPixmap() const { return mScatterPixmap; }
ErrorType errorType() const { return mErrorType; }
QPen errorPen() const { return mErrorPen; }
double errorBarSize() const { return mErrorBarSize; }
bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; }
QCPGraph *channelFillGraph() const { return mChannelFillGraph; }
// setters:
void setData(QCPDataMap *data, bool copy=false);
void setData(const QVector<double> &key, const QVector<double> &value);
void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError);
void setDataKeyError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus);
void setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueError);
void setDataValueError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus);
void setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyError, const QVector<double> &valueError);
void setDataBothError(const QVector<double> &key, const QVector<double> &value, const QVector<double> &keyErrorMinus, const QVector<double> &keyErrorPlus, const QVector<double> &valueErrorMinus, const QVector<double> &valueErrorPlus);
void setLineStyle(LineStyle ls);
void setScatterStyle(QCP::ScatterStyle ss);
void setScatterSize(double size);
void setScatterPixmap(const QPixmap &pixmap);
void setErrorType(ErrorType errorType);
void setErrorPen(const QPen &pen);
void setErrorBarSize(double size);
void setErrorBarSkipSymbol(bool enabled);
void setChannelFillGraph(QCPGraph *targetGraph);
// non-property methods:
void addData(const QCPDataMap &dataMap);
void addData(const QCPData &data);
void addData(double key, double value);
void addData(const QVector<double> &keys, const QVector<double> &values);
void removeDataBefore(double key);
void removeDataAfter(double key);
void removeData(double fromKey, double toKey);
void removeData(double key);
virtual void clearData();
virtual double selectTest(const QPointF &pos) const;
using QCPAbstractPlottable::rescaleAxes;
using QCPAbstractPlottable::rescaleKeyAxis;
using QCPAbstractPlottable::rescaleValueAxis;
virtual void rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface
virtual void rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface
virtual void rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface
protected:
QCPDataMap *mData;
QPen mErrorPen;
LineStyle mLineStyle;
QCP::ScatterStyle mScatterStyle;
double mScatterSize;
QPixmap mScatterPixmap;
ErrorType mErrorType;
double mErrorBarSize;
bool mErrorBarSkipSymbol;
QCPGraph *mChannelFillGraph;
virtual void draw(QCPPainter *painter);
virtual void drawLegendIcon(QCPPainter *painter, const QRect &rect) const;
// functions to generate plot data points in pixel coordinates:
void getPlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
// plot style specific functions to generate plot data, used by getPlotData:
void getScatterPlotData(QVector<QCPData> *pointData) const;
void getLinePlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
void getStepLeftPlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
void getStepRightPlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
void getStepCenterPlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
void getImpulsePlotData(QVector<QPointF> *lineData, QVector<QCPData> *pointData) const;
// helper functions for drawing:
void drawFill(QCPPainter *painter, QVector<QPointF> *lineData) const;
void drawScatterPlot(QCPPainter *painter, QVector<QCPData> *pointData) const;
void drawLinePlot(QCPPainter *painter, QVector<QPointF> *lineData) const;
void drawImpulsePlot(QCPPainter *painter, QVector<QPointF> *lineData) const;
void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const;
// helper functions:
void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper, int &count) const;
void addFillBasePoints(QVector<QPointF> *lineData) const;
void removeFillBasePoints(QVector<QPointF> *lineData) const;
QPointF lowerFillBasePoint(double lowerKey) const;
QPointF upperFillBasePoint(double upperKey) const;
const QPolygonF getChannelFillPolygon(const QVector<QPointF> *lineData) const;
int findIndexBelowX(const QVector<QPointF> *data, double x) const;
int findIndexAboveX(const QVector<QPointF> *data, double x) const;
int findIndexBelowY(const QVector<QPointF> *data, double y) const;
int findIndexAboveY(const QVector<QPointF> *data, double y) const;
double pointDistance(const QPointF &pixelPoint) const;
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface
friend class QCustomPlot;
friend class QCPLegend;
};
class QCP_LIB_DECL QCPCurve : public QCPAbstractPlottable
{
Q_OBJECT
public:
/*!
Defines how the curve's line is represented visually in the plot. The line is drawn with the
current pen of the curve (\ref setPen).
\see setLineStyle
*/
enum LineStyle { lsNone, ///< No line is drawn between data points (e.g. only scatters)
lsLine ///< Data points are connected with a straight line
};
explicit QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis);
virtual ~QCPCurve();
// getters:
const QCPCurveDataMap *data() const { return mData; }
QCP::ScatterStyle scatterStyle() const { return mScatterStyle; }
double scatterSize() const { return mScatterSize; }
QPixmap scatterPixmap() const { return mScatterPixmap; }
LineStyle lineStyle() const { return mLineStyle; }
// setters:
void setData(QCPCurveDataMap *data, bool copy=false);
void setData(const QVector<double> &t, const QVector<double> &key, const QVector<double> &value);
void setData(const QVector<double> &key, const QVector<double> &value);
void setScatterStyle(QCP::ScatterStyle style);
void setScatterSize(double size);
void setScatterPixmap(const QPixmap &pixmap);
void setLineStyle(LineStyle style);
// non-property methods:
void addData(const QCPCurveDataMap &dataMap);
void addData(const QCPCurveData &data);
void addData(double t, double key, double value);
void addData(double key, double value);
void addData(const QVector<double> &ts, const QVector<double> &keys, const QVector<double> &values);
void removeDataBefore(double t);
void removeDataAfter(double t);
void removeData(double fromt, double tot);
void removeData(double t);
virtual void clearData();
virtual double selectTest(const QPointF &pos) const;
protected:
QCPCurveDataMap *mData;
QCP::ScatterStyle mScatterStyle;
double mScatterSize;
QPixmap mScatterPixmap;
LineStyle mLineStyle;
virtual void draw(QCPPainter *painter);
virtual void drawLegendIcon(QCPPainter *painter, const QRect &rect) const;
// drawing helpers:
virtual void drawScatterPlot(QCPPainter *painter, const QVector<QPointF> *pointData) const;
// helper functions:
void getCurveData(QVector<QPointF> *lineData) const;
double pointDistance(const QPointF &pixelPoint) const;
QPointF outsideCoordsToPixels(double key, double value, int region) const;
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
friend class QCustomPlot;
friend class QCPLegend;
};
class QCP_LIB_DECL QCPBars : public QCPAbstractPlottable
{
Q_OBJECT
public:
explicit QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis);
virtual ~QCPBars();
// getters:
double width() const { return mWidth; }
QCPBars *barBelow() const { return mBarBelow; }
QCPBars *barAbove() const { return mBarAbove; }
const QCPBarDataMap *data() const { return mData; }
// setters:
void setWidth(double width);
void setData(QCPBarDataMap *data, bool copy=false);
void setData(const QVector<double> &key, const QVector<double> &value);
// non-property methods:
void moveBelow(QCPBars *bars);
void moveAbove(QCPBars *bars);
void addData(const QCPBarDataMap &dataMap);
void addData(const QCPBarData &data);
void addData(double key, double value);
void addData(const QVector<double> &keys, const QVector<double> &values);
void removeDataBefore(double key);
void removeDataAfter(double key);
void removeData(double fromKey, double toKey);
void removeData(double key);
virtual void clearData();
virtual double selectTest(const QPointF &pos) const;
protected:
QCPBarDataMap *mData;
double mWidth;
QCPBars *mBarBelow, *mBarAbove;
virtual void draw(QCPPainter *painter);
virtual void drawLegendIcon(QCPPainter *painter, const QRect &rect) const;
QPolygonF getBarPolygon(double key, double value) const;
double getBaseValue(double key, bool positive) const;
static void connectBars(QCPBars* lower, QCPBars* upper);
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
friend class QCustomPlot;
friend class QCPLegend;
};
class QCP_LIB_DECL QCPStatisticalBox : public QCPAbstractPlottable
{
Q_OBJECT
public:
explicit QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis);
virtual ~QCPStatisticalBox();
// getters:
double key() const { return mKey; }
double minimum() const { return mMinimum; }
double lowerQuartile() const { return mLowerQuartile; }
double median() const { return mMedian; }
double upperQuartile() const { return mUpperQuartile; }
double maximum() const { return mMaximum; }
QVector<double> outliers() const { return mOutliers; }
double width() const { return mWidth; }
double whiskerWidth() const { return mWhiskerWidth; }
QPen whiskerPen() const { return mWhiskerPen; }
QPen whiskerBarPen() const { return mWhiskerBarPen; }
QPen medianPen() const { return mMedianPen; }
double outlierSize() const { return mOutlierSize; }
QPen outlierPen() const { return mOutlierPen; }
QCP::ScatterStyle outlierStyle() const { return mOutlierStyle; }
// setters:
void setKey(double key);
void setMinimum(double value);
void setLowerQuartile(double value);
void setMedian(double value);
void setUpperQuartile(double value);
void setMaximum(double value);
void setOutliers(const QVector<double> &values);
void setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum);
void setWidth(double width);
void setWhiskerWidth(double width);
void setWhiskerPen(const QPen &pen);
void setWhiskerBarPen(const QPen &pen);
void setMedianPen(const QPen &pen);
void setOutlierSize(double pixels);
void setOutlierPen(const QPen &pen);
void setOutlierStyle(QCP::ScatterStyle style);
// non-property methods:
virtual void clearData();
virtual double selectTest(const QPointF &pos) const;
protected:
QVector<double> mOutliers;
double mKey, mMinimum, mLowerQuartile, mMedian, mUpperQuartile, mMaximum;
double mWidth;
double mWhiskerWidth;
double mOutlierSize;
QPen mWhiskerPen, mWhiskerBarPen, mOutlierPen, mMedianPen;
QCP::ScatterStyle mOutlierStyle;
virtual void draw(QCPPainter *painter);
virtual void drawLegendIcon(QCPPainter *painter, const QRect &rect) const;
virtual void drawQuartileBox(QCPPainter *painter, QRectF *quartileBox=0) const;
virtual void drawMedian(QCPPainter *painter) const;
virtual void drawWhiskers(QCPPainter *painter) const;
virtual void drawOutliers(QCPPainter *painter) const;
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
friend class QCustomPlot;
friend class QCPLegend;
};
class QCP_LIB_DECL QCPItemAnchor
{
public:
QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId=-1);
virtual ~QCPItemAnchor();
QString name() const { return mName; }
virtual QPointF pixelPoint() const;
protected:
QCustomPlot *mParentPlot;
QCPAbstractItem *mParentItem;
int mAnchorId;
QString mName;
// non-property members:
QSet<QCPItemPosition*> mChildren;
void addChild(QCPItemPosition* pos); // called from pos when this anchor is set as parent
void removeChild(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted
private:
Q_DISABLE_COPY(QCPItemAnchor)
friend class QCPItemPosition;
};
class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor
{
public:
/*!
Defines the ways an item position can be specified. Thus it defines what the numbers passed to
\ref setCoords actually mean.
\see setType
*/
enum PositionType { ptAbsolute ///< Static positioning in pixels, starting from the top left corner of the viewport/widget.
,ptViewportRatio ///< Static positioning given by a ratio of the current viewport (coordinates 0 to 1).
,ptAxisRectRatio ///< Static positioning given by a ratio of the current axis rect (coordinates 0 to 1).
,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes).
};
QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name);
virtual ~QCPItemPosition();
// getters:
PositionType type() const { return mPositionType; }
QCPItemAnchor *parentAnchor() const { return mParentAnchor; }
double key() const { return mKey; }
double value() const { return mValue; }
QPointF coords() const { return QPointF(mKey, mValue); }
QCPAxis *keyAxis() const { return mKeyAxis; }
QCPAxis *valueAxis() const { return mValueAxis; }
virtual QPointF pixelPoint() const;
// setters:
void setType(PositionType type);
bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false);
void setCoords(double key, double value);
void setCoords(const QPointF &coords);
void setAxes(QCPAxis* keyAxis, QCPAxis* valueAxis);
void setPixelPoint(const QPointF &pixelPoint);
protected:
PositionType mPositionType;
QCPAxis *mKeyAxis, *mValueAxis;
double mKey, mValue;
QCPItemAnchor *mParentAnchor;
private:
Q_DISABLE_COPY(QCPItemPosition)
};
class QCP_LIB_DECL QCPAbstractItem : public QCPLayerable
{
Q_OBJECT
public:
QCPAbstractItem(QCustomPlot *parentPlot);
virtual ~QCPAbstractItem();
// getters:
bool clipToAxisRect() const { return mClipToAxisRect; }
QCPAxis *clipKeyAxis() const { return mClipKeyAxis; }
QCPAxis *clipValueAxis() const { return mClipValueAxis; }
bool selectable() const { return mSelectable; }
bool selected() const { return mSelected; }
// setters:
void setClipToAxisRect(bool clip);
void setClipAxes(QCPAxis *keyAxis, QCPAxis *valueAxis);
void setClipKeyAxis(QCPAxis *axis);
void setClipValueAxis(QCPAxis *axis);
void setSelectable(bool selectable);
void setSelected(bool selected);
// non-property methods:
virtual double selectTest(const QPointF &pos) const = 0;
QList<QCPItemPosition*> positions() const { return mPositions; }
QList<QCPItemAnchor*> anchors() const { return mAnchors; }
QCPItemPosition *position(const QString &name) const;
QCPItemAnchor *anchor(const QString &name) const;
bool hasAnchor(const QString &name) const;
protected:
bool mClipToAxisRect;
QCPAxis *mClipKeyAxis, *mClipValueAxis;
bool mSelectable, mSelected;
QList<QCPItemPosition*> mPositions;
QList<QCPItemAnchor*> mAnchors;
virtual QRect clipRect() const;
virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const;
virtual void draw(QCPPainter *painter) = 0;
// helper functions for subclasses:
double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const;
double rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const;
// anchor/position interface:
virtual QPointF anchorPixelPoint(int anchorId) const;
QCPItemPosition *createPosition(const QString &name);
QCPItemAnchor *createAnchor(const QString &name, int anchorId);
signals:
void selectionChanged(bool selected);
private:
Q_DISABLE_COPY(QCPAbstractItem)
friend class QCustomPlot;
friend class QCPItemAnchor;
};
class QCP_LIB_DECL QCPItemStraightLine : public QCPAbstractItem
{
Q_OBJECT
public:
QCPItemStraightLine(QCustomPlot *parentPlot);
virtual ~QCPItemStraightLine();
// getters:
QPen pen() const { return mPen; }
QPen selectedPen() const { return mSelectedPen; }
// setters;
void setPen(const QPen &pen);
void setSelectedPen(const QPen &pen);
// non-property methods:
virtual double selectTest(const QPointF &pos) const;
QCPItemPosition * const point1;
QCPItemPosition * const point2;
protected:
QPen mPen, mSelectedPen;
virtual void draw(QCPPainter *painter);
// helper functions:
double distToStraightLine(const QVector2D &point1, const QVector2D &vec, const QVector2D &point) const;
QLineF getRectClippedStraightLine(const QVector2D &point1, const QVector2D &vec, const QRect &rect) const;
QPen mainPen() const;
};
class QCP_LIB_DECL QCPItemLine : public QCPAbstractItem
{
Q_OBJECT
public:
QCPItemLine(QCustomPlot *parentPlot);
virtual ~QCPItemLine();
// getters:
QPen pen() const { return mPen; }
QPen selectedPen() const { return mSelectedPen; }
QCPLineEnding head() const { return mHead; }
QCPLineEnding tail() const { return mTail; }
// setters;
void setPen(const QPen &pen);
void setSelectedPen(const QPen &pen);
void setHead(const QCPLineEnding &head);
void setTail(const QCPLineEnding &tail);
// non-property methods:
virtual double selectTest(const QPointF &pos) const;
QCPItemPosition * const start;
QCPItemPosition * const end;
protected:
QPen mPen, mSelectedPen;
QCPLineEnding mHead, mTail;
virtual void draw(QCPPainter *painter);
// helper functions:
QLineF getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const;
QPen mainPen() const;
};
class QCP_LIB_DECL QCPItemEllipse : public QCPAbstractItem
{
Q_OBJECT
public:
QCPItemEllipse(QCustomPlot *parentPlot);
virtual ~QCPItemEllipse();
// getters:
QPen pen() const { return mPen; }
QPen selectedPen() const { return mSelectedPen; }
QBrush brush() const { return mBrush; }
QBrush selectedBrush() const { return mSelectedBrush; }
// setters;
void setPen(const QPen &pen);
void setSelectedPen(const QPen &pen);
void setBrush(const QBrush &brush);
void setSelectedBrush(const QBrush &brush);
// non-property methods:
virtual double selectTest(const QPointF &pos) const;
QCPItemPosition * const topLeft;
QCPItemPosition * const bottomRight;
QCPItemAnchor * const topLeftRim;
QCPItemAnchor * const top;
QCPItemAnchor * const topRightRim;
QCPItemAnchor * const right;
QCPItemAnchor * const bottomRightRim;
QCPItemAnchor * const bottom;
QCPItemAnchor * const bottomLeftRim;