@@ -42,6 +42,9 | |||
|
42 | 42 | |
|
43 | 43 | #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) |
|
44 | 44 | #define QCP_DEVICEPIXELRATIO_SUPPORTED |
|
45 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) | |
|
46 | #define QCP_DEVICEPIXELRATIO_FLOAT | |
|
47 | #endif | |
|
45 | 48 | #endif |
|
46 | 49 | |
|
47 | 50 | #include <QtCore/QCache> |
@@ -109,8 +112,8 class QCPColorMap; | |||
|
109 | 112 | class QCPColorScale; |
|
110 | 113 | class QCPBars; |
|
111 | 114 | |
|
112 |
/* including file 'src/global.h', size 16 |
|
|
113 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
115 | /* including file 'src/global.h', size 16225 */ | |
|
116 | /* commit e7c6a5540d344a96d107dce53f9d4414a09a7320 2017-07-25 00:52:29 +0200 */ | |
|
114 | 117 | |
|
115 | 118 | // decl definitions for shared library compilation/usage: |
|
116 | 119 | #if defined(QCUSTOMPLOT_COMPILE_LIBRARY) |
@@ -1794,8 +1797,8 protected: | |||
|
1794 | 1797 | /* end of 'src/axis/axistickerdatetime.h' */ |
|
1795 | 1798 | |
|
1796 | 1799 | |
|
1797 |
/* including file 'src/axis/axistickertime.h', size 32 |
|
|
1798 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
1800 | /* including file 'src/axis/axistickertime.h', size 3542 */ | |
|
1801 | /* commit c38adb94d83c6a752597a5d43d45c0561fbe1d4d 2017-08-13 17:37:53 +0200 */ | |
|
1799 | 1802 | |
|
1800 | 1803 | class QCP_LIB_DECL QCPAxisTickerTime : public QCPAxisTicker { |
|
1801 | 1804 | Q_GADGET |
@@ -1805,7 +1808,17 public: | |||
|
1805 | 1808 | |
|
1806 | 1809 | \see setFieldWidth, setTimeFormat |
|
1807 | 1810 | */ |
|
1808 | enum TimeUnit { tuMilliseconds, tuSeconds, tuMinutes, tuHours, tuDays }; | |
|
1811 | enum TimeUnit { | |
|
1812 | tuMilliseconds ///< Milliseconds, one thousandth of a second (%%z in \ref setTimeFormat) | |
|
1813 | , | |
|
1814 | tuSeconds ///< Seconds (%%s in \ref setTimeFormat) | |
|
1815 | , | |
|
1816 | tuMinutes ///< Minutes (%%m in \ref setTimeFormat) | |
|
1817 | , | |
|
1818 | tuHours ///< Hours (%%h in \ref setTimeFormat) | |
|
1819 | , | |
|
1820 | tuDays ///< Days (%%d in \ref setTimeFormat) | |
|
1821 | }; | |
|
1809 | 1822 | Q_ENUMS(TimeUnit) |
|
1810 | 1823 | |
|
1811 | 1824 | QCPAxisTickerTime(); |
@@ -2026,8 +2039,8 protected: | |||
|
2026 | 2039 | /* end of 'src/axis/axistickerlog.h' */ |
|
2027 | 2040 | |
|
2028 | 2041 | |
|
2029 |
/* including file 'src/axis/axis.h', size 20 |
|
|
2030 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
2042 | /* including file 'src/axis/axis.h', size 20634 */ | |
|
2043 | /* commit 0cc4d9f61f7bf45321a88fec89d909b020ffa26f 2017-08-14 00:43:29 +0200 */ | |
|
2031 | 2044 | |
|
2032 | 2045 | class QCP_LIB_DECL QCPGrid : public QCPLayerable { |
|
2033 | 2046 | Q_OBJECT |
@@ -2364,6 +2377,9 protected: | |||
|
2364 | 2377 | QVector<double> mSubTickVector; |
|
2365 | 2378 | bool mCachedMarginValid; |
|
2366 | 2379 | int mCachedMargin; |
|
2380 | bool mDragging; | |
|
2381 | QCPRange mDragStartRange; | |
|
2382 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; | |
|
2367 | 2383 | |
|
2368 | 2384 | // introduced virtual methods: |
|
2369 | 2385 | virtual int calculateMargin(); |
@@ -2376,6 +2392,11 protected: | |||
|
2376 | 2392 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, |
|
2377 | 2393 | bool *selectionStateChanged) Q_DECL_OVERRIDE; |
|
2378 | 2394 | virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; |
|
2395 | // mouse events: | |
|
2396 | virtual void mousePressEvent(QMouseEvent *event, const QVariant &details); | |
|
2397 | virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos); | |
|
2398 | virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos); | |
|
2399 | virtual void wheelEvent(QWheelEvent *event); | |
|
2379 | 2400 | |
|
2380 | 2401 | // non-virtual methods: |
|
2381 | 2402 | void setupTickVectors(); |
@@ -2612,8 +2633,8 Q_DECLARE_METATYPE(QCPScatterStyle::ScatterShape) | |||
|
2612 | 2633 | /* end of 'src/scatterstyle.h' */ |
|
2613 | 2634 | |
|
2614 | 2635 | |
|
2615 |
/* including file 'src/datacontainer.h', size 45 |
|
|
2616 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
2636 | /* including file 'src/datacontainer.h', size 4596 */ | |
|
2637 | /* commit bee82298bd87b91a50093fb0b81cd7c734724a6f 2017-08-13 16:10:24 +0200 */ | |
|
2617 | 2638 | |
|
2618 | 2639 | /*! \relates QCPDataContainer |
|
2619 | 2640 | Returns whether the sort key of \a a is less than the sort key of \a b. |
@@ -2627,7 +2648,8 inline bool qcpLessThanSortKey(const DataType &a, const DataType &b) | |||
|
2627 | 2648 | } |
|
2628 | 2649 | |
|
2629 | 2650 | template <class DataType> |
|
2630 | class QCP_LIB_DECL QCPDataContainer { | |
|
2651 | class QCPDataContainer // no QCP_LIB_DECL, template class ends up in header (cpp included below) | |
|
2652 | { | |
|
2631 | 2653 | public: |
|
2632 | 2654 | typedef typename QVector<DataType>::const_iterator const_iterator; |
|
2633 | 2655 | typedef typename QVector<DataType>::iterator iterator; |
@@ -2686,8 +2708,8 protected: | |||
|
2686 | 2708 | |
|
2687 | 2709 | // include implementation in header since it is a class template: |
|
2688 | 2710 | |
|
2689 |
/* including file 'src/datacontainer.cpp', size 31 |
|
|
2690 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
2711 | /* including file 'src/datacontainer.cpp', size 31349 */ | |
|
2712 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ | |
|
2691 | 2713 | |
|
2692 | 2714 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2693 | 2715 | //////////////////// QCPDataContainer |
@@ -3403,7 +3425,8 QCPRange QCPDataContainer<DataType>::valueRange(bool &foundRange, QCP::SignDomai | |||
|
3403 | 3425 | |
|
3404 | 3426 | /*! |
|
3405 | 3427 | Makes sure \a begin and \a end mark a data range that is both within the bounds of this data |
|
3406 | container's data, as well as within the specified \a dataRange. | |
|
3428 | container's data, as well as within the specified \a dataRange. The initial range described by | |
|
3429 | the passed iterators \a begin and \a end is never expanded, only contracted if necessary. | |
|
3407 | 3430 | |
|
3408 | 3431 | This function doesn't require for \a dataRange to be within the bounds of this data container's |
|
3409 | 3432 | valid range. |
@@ -3660,8 +3683,8 private: | |||
|
3660 | 3683 | /* end of 'src/plottable.h' */ |
|
3661 | 3684 | |
|
3662 | 3685 | |
|
3663 |
/* including file 'src/item.h', size 93 |
|
|
3664 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
3686 | /* including file 'src/item.h', size 9384 */ | |
|
3687 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ | |
|
3665 | 3688 | |
|
3666 | 3689 | class QCP_LIB_DECL QCPItemAnchor { |
|
3667 | 3690 | Q_GADGET |
@@ -3750,7 +3773,7 public: | |||
|
3750 | 3773 | QCPAxis *keyAxis() const { return mKeyAxis.data(); } |
|
3751 | 3774 | QCPAxis *valueAxis() const { return mValueAxis.data(); } |
|
3752 | 3775 | QCPAxisRect *axisRect() const; |
|
3753 | virtual QPointF pixelPosition() const; | |
|
3776 | virtual QPointF pixelPosition() const Q_DECL_OVERRIDE; | |
|
3754 | 3777 | |
|
3755 | 3778 | // setters: |
|
3756 | 3779 | void setType(PositionType type); |
@@ -3857,8 +3880,8 private: | |||
|
3857 | 3880 | /* end of 'src/item.h' */ |
|
3858 | 3881 | |
|
3859 | 3882 | |
|
3860 |
/* including file 'src/core.h', size 14 |
|
|
3861 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
3883 | /* including file 'src/core.h', size 14886 */ | |
|
3884 | /* commit 29aafbce469a36d175d4fb32cbfd1f50a6072890 2016-10-12 19:21:24 +0200 */ | |
|
3862 | 3885 | |
|
3863 | 3886 | class QCP_LIB_DECL QCustomPlot : public QWidget { |
|
3864 | 3887 | Q_OBJECT |
@@ -4091,7 +4114,9 protected: | |||
|
4091 | 4114 | QPoint mMousePressPos; |
|
4092 | 4115 | bool mMouseHasMoved; |
|
4093 | 4116 | QPointer<QCPLayerable> mMouseEventLayerable; |
|
4117 | QPointer<QCPLayerable> mMouseSignalLayerable; | |
|
4094 | 4118 | QVariant mMouseEventLayerableDetails; |
|
4119 | QVariant mMouseSignalLayerableDetails; | |
|
4095 | 4120 | bool mReplotting; |
|
4096 | 4121 | bool mReplotQueued; |
|
4097 | 4122 | int mOpenGlMultisamples; |
@@ -4153,11 +4178,12 Q_DECLARE_METATYPE(QCustomPlot::RefreshPriority) | |||
|
4153 | 4178 | /* end of 'src/core.h' */ |
|
4154 | 4179 | |
|
4155 | 4180 | |
|
4156 |
/* including file 'src/plottable1d.h', size 4 |
|
|
4157 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
4181 | /* including file 'src/plottable1d.h', size 4544 */ | |
|
4182 | /* commit bee82298bd87b91a50093fb0b81cd7c734724a6f 2017-08-13 16:10:24 +0200 */ | |
|
4158 | 4183 | |
|
4159 |
class |
|
|
4184 | class QCPPlottableInterface1D { | |
|
4160 | 4185 | public: |
|
4186 | virtual ~QCPPlottableInterface1D() {} | |
|
4161 | 4187 | // introduced pure virtual methods: |
|
4162 | 4188 | virtual int dataCount() const = 0; |
|
4163 | 4189 | virtual double dataMainKey(int index) const = 0; |
@@ -4172,8 +4198,11 public: | |||
|
4172 | 4198 | }; |
|
4173 | 4199 | |
|
4174 | 4200 | template <class DataType> |
|
4175 |
class |
|
|
4176 |
|
|
|
4201 | class QCPAbstractPlottable1D : public QCPAbstractPlottable, | |
|
4202 | public QCPPlottableInterface1D // no QCP_LIB_DECL, template class | |
|
4203 | // ends up in header (cpp included | |
|
4204 | // below) | |
|
4205 | { | |
|
4177 | 4206 | // No Q_OBJECT macro due to template class |
|
4178 | 4207 | |
|
4179 | 4208 | public: |
@@ -4181,20 +4210,22 public: | |||
|
4181 | 4210 | virtual ~QCPAbstractPlottable1D(); |
|
4182 | 4211 | |
|
4183 | 4212 | // virtual methods of 1d plottable interface: |
|
4184 | virtual int dataCount() const; | |
|
4185 | virtual double dataMainKey(int index) const; | |
|
4186 | virtual double dataSortKey(int index) const; | |
|
4187 | virtual double dataMainValue(int index) const; | |
|
4188 | virtual QCPRange dataValueRange(int index) const; | |
|
4189 | virtual QPointF dataPixelPosition(int index) const; | |
|
4190 | virtual bool sortKeyIsMainKey() const; | |
|
4191 |
virtual QCPDataSelection selectTestRect(const QRectF &rect, |
|
|
4192 | virtual int findBegin(double sortKey, bool expandedRange = true) const; | |
|
4193 |
virtual int find |
|
|
4213 | virtual int dataCount() const Q_DECL_OVERRIDE; | |
|
4214 | virtual double dataMainKey(int index) const Q_DECL_OVERRIDE; | |
|
4215 | virtual double dataSortKey(int index) const Q_DECL_OVERRIDE; | |
|
4216 | virtual double dataMainValue(int index) const Q_DECL_OVERRIDE; | |
|
4217 | virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE; | |
|
4218 | virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE; | |
|
4219 | virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE; | |
|
4220 | virtual QCPDataSelection selectTestRect(const QRectF &rect, | |
|
4221 | bool onlySelectable) const Q_DECL_OVERRIDE; | |
|
4222 | virtual int findBegin(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; | |
|
4223 | virtual int findEnd(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; | |
|
4194 | 4224 | |
|
4195 | // virtual methods: | |
|
4196 |
virtual double selectTest(const QPointF &pos, bool onlySelectable, |
|
|
4197 | virtual QCPPlottableInterface1D *interface1D() { return this; } | |
|
4225 | // reimplemented virtual methods: | |
|
4226 | virtual double selectTest(const QPointF &pos, bool onlySelectable, | |
|
4227 | QVariant *details = 0) const Q_DECL_OVERRIDE; | |
|
4228 | virtual QCPPlottableInterface1D *interface1D() Q_DECL_OVERRIDE { return this; } | |
|
4198 | 4229 | |
|
4199 | 4230 | protected: |
|
4200 | 4231 | // property members: |
@@ -4863,8 +4894,8 Q_DECLARE_METATYPE(QCPColorGradient::GradientPreset) | |||
|
4863 | 4894 | /* end of 'src/colorgradient.h' */ |
|
4864 | 4895 | |
|
4865 | 4896 | |
|
4866 |
/* including file 'src/selectiondecorator-bracket.h', size 442 |
|
|
4867 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
4897 | /* including file 'src/selectiondecorator-bracket.h', size 4442 */ | |
|
4898 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ | |
|
4868 | 4899 | |
|
4869 | 4900 | class QCP_LIB_DECL QCPSelectionDecoratorBracket : public QCPSelectionDecorator { |
|
4870 | 4901 | Q_GADGET |
@@ -4916,7 +4947,7 public: | |||
|
4916 | 4947 | virtual void drawBracket(QCPPainter *painter, int direction) const; |
|
4917 | 4948 | |
|
4918 | 4949 | // virtual methods: |
|
4919 | virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection); | |
|
4950 | virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection) Q_DECL_OVERRIDE; | |
|
4920 | 4951 | |
|
4921 | 4952 | protected: |
|
4922 | 4953 | // property members: |
@@ -4938,8 +4969,8 Q_DECLARE_METATYPE(QCPSelectionDecoratorBracket::BracketStyle) | |||
|
4938 | 4969 | /* end of 'src/selectiondecorator-bracket.h' */ |
|
4939 | 4970 | |
|
4940 | 4971 | |
|
4941 |
/* including file 'src/layoutelements/layoutelement-axisrect.h', size 75 |
|
|
4942 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
4972 | /* including file 'src/layoutelements/layoutelement-axisrect.h', size 7507 */ | |
|
4973 | /* commit 77ba168312f935543fc31d1ae9b4cdcf34aae4f9 2017-08-13 18:29:48 +0200 */ | |
|
4943 | 4974 | |
|
4944 | 4975 | class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement { |
|
4945 | 4976 | Q_OBJECT |
@@ -5037,7 +5068,6 protected: | |||
|
5037 | 5068 | // non-property members: |
|
5038 | 5069 | QList<QCPRange> mDragStartHorzRange, mDragStartVertRange; |
|
5039 | 5070 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; |
|
5040 | QPoint mDragStart; | |
|
5041 | 5071 | bool mDragging; |
|
5042 | 5072 | QHash<QCPAxis::AxisType, QList<QCPAxis *> > mAxes; |
|
5043 | 5073 | |
@@ -5378,8 +5408,8 private: | |||
|
5378 | 5408 | /* end of 'src/layoutelements/layoutelement-textelement.h' */ |
|
5379 | 5409 | |
|
5380 | 5410 | |
|
5381 |
/* including file 'src/layoutelements/layoutelement-colorscale.h', size 59 |
|
|
5382 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
5411 | /* including file 'src/layoutelements/layoutelement-colorscale.h', size 5923 */ | |
|
5412 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ | |
|
5383 | 5413 | |
|
5384 | 5414 | |
|
5385 | 5415 | class QCPColorScaleAxisRectPrivate : public QCPAxisRect { |
@@ -5398,7 +5428,7 protected: | |||
|
5398 | 5428 | using QCPAxisRect::mouseReleaseEvent; |
|
5399 | 5429 | using QCPAxisRect::wheelEvent; |
|
5400 | 5430 | using QCPAxisRect::update; |
|
5401 | virtual void draw(QCPPainter *painter); | |
|
5431 | virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; | |
|
5402 | 5432 | void updateGradientImage(); |
|
5403 | 5433 | Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts); |
|
5404 | 5434 | Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts); |
@@ -5486,8 +5516,8 private: | |||
|
5486 | 5516 | /* end of 'src/layoutelements/layoutelement-colorscale.h' */ |
|
5487 | 5517 | |
|
5488 | 5518 | |
|
5489 |
/* including file 'src/plottables/plottable-graph.h', size |
|
|
5490 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
5519 | /* including file 'src/plottables/plottable-graph.h', size 9294 */ | |
|
5520 | /* commit f3881770eaf7366171012ad01cad2aaf5f61dd27 2017-06-23 02:48:21 +0200 */ | |
|
5491 | 5521 | |
|
5492 | 5522 | class QCP_LIB_DECL QCPGraphData { |
|
5493 | 5523 | public: |
@@ -5624,11 +5654,20 protected: | |||
|
5624 | 5654 | QVector<QPointF> dataToStepRightLines(const QVector<QCPGraphData> &data) const; |
|
5625 | 5655 | QVector<QPointF> dataToStepCenterLines(const QVector<QCPGraphData> &data) const; |
|
5626 | 5656 | QVector<QPointF> dataToImpulseLines(const QVector<QCPGraphData> &data) const; |
|
5627 | void addFillBasePoints(QVector<QPointF> *lines) const; | |
|
5628 | void removeFillBasePoints(QVector<QPointF> *lines) const; | |
|
5629 | QPointF lowerFillBasePoint(double lowerKey) const; | |
|
5630 | QPointF upperFillBasePoint(double upperKey) const; | |
|
5631 | const QPolygonF getChannelFillPolygon(const QVector<QPointF> *lines) const; | |
|
5657 | QVector<QCPDataRange> getNonNanSegments(const QVector<QPointF> *lineData, | |
|
5658 | Qt::Orientation keyOrientation) const; | |
|
5659 | QVector<QPair<QCPDataRange, QCPDataRange> > | |
|
5660 | getOverlappingSegments(QVector<QCPDataRange> thisSegments, const QVector<QPointF> *thisData, | |
|
5661 | QVector<QCPDataRange> otherSegments, | |
|
5662 | const QVector<QPointF> *otherData) const; | |
|
5663 | bool segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, | |
|
5664 | int &bPrecedence) const; | |
|
5665 | QPointF getFillBasePoint(QPointF matchingDataPoint) const; | |
|
5666 | const QPolygonF getFillPolygon(const QVector<QPointF> *lineData, QCPDataRange segment) const; | |
|
5667 | const QPolygonF getChannelFillPolygon(const QVector<QPointF> *lineData, | |
|
5668 | QCPDataRange thisSegment, | |
|
5669 | const QVector<QPointF> *otherData, | |
|
5670 | QCPDataRange otherSegment) const; | |
|
5632 | 5671 | int findIndexBelowX(const QVector<QPointF> *data, double x) const; |
|
5633 | 5672 | int findIndexAboveX(const QVector<QPointF> *data, double x) const; |
|
5634 | 5673 | int findIndexBelowY(const QVector<QPointF> *data, double y) const; |
@@ -6425,8 +6464,8 Q_DECLARE_METATYPE(QCPFinancial::ChartStyle) | |||
|
6425 | 6464 | /* end of 'src/plottables/plottable-financial.h' */ |
|
6426 | 6465 | |
|
6427 | 6466 | |
|
6428 |
/* including file 'src/plottables/plottable-errorbar.h', size 7 |
|
|
6429 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
6467 | /* including file 'src/plottables/plottable-errorbar.h', size 7727 */ | |
|
6468 | /* commit 681a87c5e5365a5c7187d20b4077031003c48449 2017-07-23 23:46:48 +0200 */ | |
|
6430 | 6469 | |
|
6431 | 6470 | class QCP_LIB_DECL QCPErrorBarsData { |
|
6432 | 6471 | public: |
@@ -6505,16 +6544,17 public: | |||
|
6505 | 6544 | void addData(double errorMinus, double errorPlus); |
|
6506 | 6545 | |
|
6507 | 6546 | // virtual methods of 1d plottable interface: |
|
6508 | virtual int dataCount() const; | |
|
6509 | virtual double dataMainKey(int index) const; | |
|
6510 | virtual double dataSortKey(int index) const; | |
|
6511 | virtual double dataMainValue(int index) const; | |
|
6512 | virtual QCPRange dataValueRange(int index) const; | |
|
6513 | virtual QPointF dataPixelPosition(int index) const; | |
|
6514 | virtual bool sortKeyIsMainKey() const; | |
|
6515 |
virtual QCPDataSelection selectTestRect(const QRectF &rect, |
|
|
6516 | virtual int findBegin(double sortKey, bool expandedRange = true) const; | |
|
6517 |
virtual int find |
|
|
6547 | virtual int dataCount() const Q_DECL_OVERRIDE; | |
|
6548 | virtual double dataMainKey(int index) const Q_DECL_OVERRIDE; | |
|
6549 | virtual double dataSortKey(int index) const Q_DECL_OVERRIDE; | |
|
6550 | virtual double dataMainValue(int index) const Q_DECL_OVERRIDE; | |
|
6551 | virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE; | |
|
6552 | virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE; | |
|
6553 | virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE; | |
|
6554 | virtual QCPDataSelection selectTestRect(const QRectF &rect, | |
|
6555 | bool onlySelectable) const Q_DECL_OVERRIDE; | |
|
6556 | virtual int findBegin(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; | |
|
6557 | virtual int findEnd(double sortKey, bool expandedRange = true) const Q_DECL_OVERRIDE; | |
|
6518 | 6558 | |
|
6519 | 6559 | // reimplemented virtual methods: |
|
6520 | 6560 | virtual double selectTest(const QPointF &pos, bool onlySelectable, |
This diff has been collapsed as it changes many lines, (1395 lines changed) Show them Hide them | |||
@@ -1574,10 +1574,7 void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialia | |||
|
1574 | 1574 | |
|
1575 | 1575 | \see initializeParentPlot |
|
1576 | 1576 | */ |
|
1577 | void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot) | |
|
1578 | { | |
|
1579 | Q_UNUSED(parentPlot) | |
|
1580 | } | |
|
1577 | void QCPLayerable::parentPlotInitialized(QCustomPlot *parentPlot){Q_UNUSED(parentPlot)} | |
|
1581 | 1578 | |
|
1582 | 1579 | /*! \internal |
|
1583 | 1580 | |
@@ -2102,8 +2099,8 bool QCPRange::validRange(const QCPRange &range) | |||
|
2102 | 2099 | /* end of 'src/axis/range.cpp' */ |
|
2103 | 2100 | |
|
2104 | 2101 | |
|
2105 |
/* including file 'src/selection.cpp', size 21 |
|
|
2106 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
2102 | /* including file 'src/selection.cpp', size 21906 */ | |
|
2103 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ | |
|
2107 | 2104 | |
|
2108 | 2105 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2109 | 2106 | //////////////////// QCPDataRange |
@@ -2406,7 +2403,7 QCPDataSelection &QCPDataSelection::operator+=(const QCPDataRange &other) | |||
|
2406 | 2403 | } |
|
2407 | 2404 | |
|
2408 | 2405 | /*! |
|
2409 |
Removes all data point indices that are described by \a other from this data |
|
|
2406 | Removes all data point indices that are described by \a other from this data selection. | |
|
2410 | 2407 | */ |
|
2411 | 2408 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataSelection &other) |
|
2412 | 2409 | { |
@@ -2417,7 +2414,7 QCPDataSelection &QCPDataSelection::operator-=(const QCPDataSelection &other) | |||
|
2417 | 2414 | } |
|
2418 | 2415 | |
|
2419 | 2416 | /*! |
|
2420 |
Removes all data point indices that are described by \a other from this data |
|
|
2417 | Removes all data point indices that are described by \a other from this data selection. | |
|
2421 | 2418 | */ |
|
2422 | 2419 | QCPDataSelection &QCPDataSelection::operator-=(const QCPDataRange &other) |
|
2423 | 2420 | { |
@@ -2930,8 +2927,8 void QCPSelectionRect::draw(QCPPainter *painter) | |||
|
2930 | 2927 | /* end of 'src/selectionrect.cpp' */ |
|
2931 | 2928 | |
|
2932 | 2929 | |
|
2933 |
/* including file 'src/layout.cpp', size 743 |
|
|
2934 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
2930 | /* including file 'src/layout.cpp', size 74663 */ | |
|
2931 | /* commit a872eb91ec087561efd83dd9cb041a26ab95ce55 2017-07-31 00:21:41 +0200 */ | |
|
2935 | 2932 | |
|
2936 | 2933 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2937 | 2934 | //////////////////// QCPMarginGroup |
@@ -3572,12 +3569,13 QCPLayout::QCPLayout() | |||
|
3572 | 3569 | } |
|
3573 | 3570 | |
|
3574 | 3571 | /*! |
|
3575 | First calls the QCPLayoutElement::update base class implementation to update the margins on this | |
|
3576 | layout. | |
|
3572 | If \a phase is \ref upLayout, calls \ref updateLayout, which subclasses may reimplement to | |
|
3573 | reposition and resize their cells. | |
|
3577 | 3574 | |
|
3578 | Then calls \ref updateLayout which subclasses reimplement to reposition and resize their cells. | |
|
3575 | Finally, the call is propagated down to all child \ref QCPLayoutElement "QCPLayoutElements". | |
|
3579 | 3576 | |
|
3580 | Finally, \ref update is called on all child elements. | |
|
3577 | For details about this method and the update phases, see the documentation of \ref | |
|
3578 | QCPLayoutElement::update. | |
|
3581 | 3579 | */ |
|
3582 | 3580 | void QCPLayout::update(UpdatePhase phase) |
|
3583 | 3581 | { |
@@ -4242,7 +4240,7 void QCPLayoutGrid::setWrap(int count) | |||
|
4242 | 4240 | |
|
4243 | 4241 | If you want to have all current elements arranged in the new order, set \a rearrange to true. The |
|
4244 | 4242 | elements will be rearranged in a way that tries to preserve their linear index. However, empty |
|
4245 | cells are skipped during build-up of the new cell order, which shifts the succeding element's | |
|
4243 | cells are skipped during build-up of the new cell order, which shifts the succeeding element's | |
|
4246 | 4244 | index. The rearranging is performed even if the specified \a order is already the current fill |
|
4247 | 4245 | order. Thus this method can be used to re-wrap the current elements. |
|
4248 | 4246 | |
@@ -4337,7 +4335,8 void QCPLayoutGrid::insertRow(int newIndex) | |||
|
4337 | 4335 | |
|
4338 | 4336 | /*! |
|
4339 | 4337 | Inserts a new column with empty cells at the column index \a newIndex. Valid values for \a |
|
4340 |
newIndex range from 0 (inserts a |
|
|
4338 | newIndex range from 0 (inserts a column at the left) to \a columnCount (appends a column at the | |
|
4339 | right). | |
|
4341 | 4340 | |
|
4342 | 4341 | \see insertRow |
|
4343 | 4342 | */ |
@@ -4411,7 +4410,9 void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const | |||
|
4411 | 4410 | { |
|
4412 | 4411 | row = -1; |
|
4413 | 4412 | column = -1; |
|
4414 | if (columnCount() == 0 || rowCount() == 0) | |
|
4413 | const int nCols = columnCount(); | |
|
4414 | const int nRows = rowCount(); | |
|
4415 | if (nCols == 0 || nRows == 0) | |
|
4415 | 4416 | return; |
|
4416 | 4417 | if (index < 0 || index >= elementCount()) { |
|
4417 | 4418 | qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; |
@@ -4420,13 +4421,13 void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const | |||
|
4420 | 4421 | |
|
4421 | 4422 | switch (mFillOrder) { |
|
4422 | 4423 | case foRowsFirst: { |
|
4423 |
column = index / |
|
|
4424 |
row = index % |
|
|
4424 | column = index / nRows; | |
|
4425 | row = index % nRows; | |
|
4425 | 4426 | break; |
|
4426 | 4427 | } |
|
4427 | 4428 | case foColumnsFirst: { |
|
4428 |
row = index / |
|
|
4429 |
column = index % |
|
|
4429 | row = index / nCols; | |
|
4430 | column = index % nCols; | |
|
4430 | 4431 | break; |
|
4431 | 4432 | } |
|
4432 | 4433 | } |
@@ -4592,9 +4593,8 QSize QCPLayoutGrid::minimumSizeHint() const | |||
|
4592 | 4593 | result.rwidth() += minColWidths.at(i); |
|
4593 | 4594 | for (int i = 0; i < minRowHeights.size(); ++i) |
|
4594 | 4595 | result.rheight() += minRowHeights.at(i); |
|
4595 | result.rwidth() | |
|
4596 | += qMax(0, columnCount() - 1) * mColumnSpacing + mMargins.left() + mMargins.right(); | |
|
4597 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing + mMargins.top() + mMargins.bottom(); | |
|
4596 | result.rwidth() += qMax(0, columnCount() - 1) * mColumnSpacing; | |
|
4597 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing; | |
|
4598 | 4598 | return result; |
|
4599 | 4599 | } |
|
4600 | 4600 | |
@@ -4609,9 +4609,8 QSize QCPLayoutGrid::maximumSizeHint() const | |||
|
4609 | 4609 | result.setWidth(qMin(result.width() + maxColWidths.at(i), QWIDGETSIZE_MAX)); |
|
4610 | 4610 | for (int i = 0; i < maxRowHeights.size(); ++i) |
|
4611 | 4611 | result.setHeight(qMin(result.height() + maxRowHeights.at(i), QWIDGETSIZE_MAX)); |
|
4612 | result.rwidth() | |
|
4613 | += qMax(0, columnCount() - 1) * mColumnSpacing + mMargins.left() + mMargins.right(); | |
|
4614 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing + mMargins.top() + mMargins.bottom(); | |
|
4612 | result.rwidth() += qMax(0, columnCount() - 1) * mColumnSpacing; | |
|
4613 | result.rheight() += qMax(0, rowCount() - 1) * mRowSpacing; | |
|
4615 | 4614 | return result; |
|
4616 | 4615 | } |
|
4617 | 4616 | |
@@ -4620,8 +4619,9 QSize QCPLayoutGrid::maximumSizeHint() const | |||
|
4620 | 4619 | Places the minimum column widths and row heights into \a minColWidths and \a minRowHeights |
|
4621 | 4620 | respectively. |
|
4622 | 4621 | |
|
4623 |
The minimum height of a row is the largest minimum height of any element in that |
|
|
4624 |
width of a column is the largest minimum width of any element in |
|
|
4622 | The minimum height of a row is the largest minimum height of any element's outer rect in that | |
|
4623 | row. The minimum width of a column is the largest minimum width of any element's outer rect in | |
|
4624 | that column. | |
|
4625 | 4625 | |
|
4626 | 4626 | This is a helper function for \ref updateLayout. |
|
4627 | 4627 | |
@@ -4634,11 +4634,13 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, | |||
|
4634 | 4634 | *minRowHeights = QVector<int>(rowCount(), 0); |
|
4635 | 4635 | for (int row = 0; row < rowCount(); ++row) { |
|
4636 | 4636 | for (int col = 0; col < columnCount(); ++col) { |
|
4637 | if (mElements.at(row).at(col)) { | |
|
4638 |
QSize minHint = |
|
|
4639 |
QSize min = |
|
|
4637 | if (QCPLayoutElement *el = mElements.at(row).at(col)) { | |
|
4638 | QSize minHint = el->minimumSizeHint(); | |
|
4639 | QSize min = el->minimumSize(); | |
|
4640 | 4640 | QSize final(min.width() > 0 ? min.width() : minHint.width(), |
|
4641 | 4641 | min.height() > 0 ? min.height() : minHint.height()); |
|
4642 | final += QSize(el->margins().left() + el->margins().right(), | |
|
4643 | el->margins().top() + el->margins().bottom()); | |
|
4642 | 4644 | if (minColWidths->at(col) < final.width()) |
|
4643 | 4645 | (*minColWidths)[col] = final.width(); |
|
4644 | 4646 | if (minRowHeights->at(row) < final.height()) |
@@ -4653,8 +4655,9 void QCPLayoutGrid::getMinimumRowColSizes(QVector<int> *minColWidths, | |||
|
4653 | 4655 | Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights |
|
4654 | 4656 | respectively. |
|
4655 | 4657 | |
|
4656 |
The maximum height of a row is the smallest maximum height of any element in that |
|
|
4657 |
maximum width of a column is the smallest maximum width of any element in |
|
|
4658 | The maximum height of a row is the smallest maximum height of any element's outer rect in that | |
|
4659 | row. The maximum width of a column is the smallest maximum width of any element's outer rect in | |
|
4660 | that column. | |
|
4658 | 4661 | |
|
4659 | 4662 | This is a helper function for \ref updateLayout. |
|
4660 | 4663 | |
@@ -4667,11 +4670,13 void QCPLayoutGrid::getMaximumRowColSizes(QVector<int> *maxColWidths, | |||
|
4667 | 4670 | *maxRowHeights = QVector<int>(rowCount(), QWIDGETSIZE_MAX); |
|
4668 | 4671 | for (int row = 0; row < rowCount(); ++row) { |
|
4669 | 4672 | for (int col = 0; col < columnCount(); ++col) { |
|
4670 | if (mElements.at(row).at(col)) { | |
|
4671 |
QSize maxHint = |
|
|
4672 |
QSize max = |
|
|
4673 | if (QCPLayoutElement *el = mElements.at(row).at(col)) { | |
|
4674 | QSize maxHint = el->maximumSizeHint(); | |
|
4675 | QSize max = el->maximumSize(); | |
|
4673 | 4676 | QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), |
|
4674 | 4677 | max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); |
|
4678 | final += QSize(el->margins().left() + el->margins().right(), | |
|
4679 | el->margins().top() + el->margins().bottom()); | |
|
4675 | 4680 | if (maxColWidths->at(col) > final.width()) |
|
4676 | 4681 | (*maxColWidths)[col] = final.width(); |
|
4677 | 4682 | if (maxRowHeights->at(row) > final.height()) |
@@ -4820,22 +4825,25 void QCPLayoutInset::setInsetRect(int index, const QRectF &rect) | |||
|
4820 | 4825 | void QCPLayoutInset::updateLayout() |
|
4821 | 4826 | { |
|
4822 | 4827 | for (int i = 0; i < mElements.size(); ++i) { |
|
4828 | QCPLayoutElement *el = mElements.at(i); | |
|
4823 | 4829 | QRect insetRect; |
|
4824 | 4830 | QSize finalMinSize, finalMaxSize; |
|
4825 |
QSize minSizeHint = |
|
|
4826 |
QSize maxSizeHint = |
|
|
4827 |
finalMinSize.setWidth( |
|
|
4828 |
|
|
|
4829 | : minSizeHint.width()); | |
|
4830 | finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 | |
|
4831 | ? mElements.at(i)->minimumSize().height() | |
|
4832 |
|
|
|
4833 | finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX | |
|
4834 | ? mElements.at(i)->maximumSize().width() | |
|
4831 | QSize minSizeHint = el->minimumSizeHint(); | |
|
4832 | QSize maxSizeHint = el->maximumSizeHint(); | |
|
4833 | finalMinSize.setWidth(el->minimumSize().width() > 0 ? el->minimumSize().width() | |
|
4834 | : minSizeHint.width()); | |
|
4835 | finalMinSize.setHeight(el->minimumSize().height() > 0 ? el->minimumSize().height() | |
|
4836 | : minSizeHint.height()); | |
|
4837 | finalMaxSize.setWidth(el->maximumSize().width() < QWIDGETSIZE_MAX | |
|
4838 | ? el->maximumSize().width() | |
|
4835 | 4839 | : maxSizeHint.width()); |
|
4836 |
finalMaxSize.setHeight( |
|
|
4837 |
? |
|
|
4840 | finalMaxSize.setHeight(el->maximumSize().height() < QWIDGETSIZE_MAX | |
|
4841 | ? el->maximumSize().height() | |
|
4838 | 4842 | : maxSizeHint.height()); |
|
4843 | finalMinSize += QSize(el->margins().left() + el->margins().right(), | |
|
4844 | el->margins().top() + el->margins().bottom()); | |
|
4845 | finalMaxSize += QSize(el->margins().left() + el->margins().right(), | |
|
4846 | el->margins().top() + el->margins().bottom()); | |
|
4839 | 4847 | if (mInsetPlacement.at(i) == ipFree) { |
|
4840 | 4848 | insetRect = QRect(rect().x() + rect().width() * mInsetRect.at(i).x(), |
|
4841 | 4849 | rect().y() + rect().height() * mInsetRect.at(i).y(), |
@@ -7150,8 +7158,8 QVector<double> QCPAxisTickerLog::createTickVector(double tickStep, const QCPRan | |||
|
7150 | 7158 | /* end of 'src/axis/axistickerlog.cpp' */ |
|
7151 | 7159 | |
|
7152 | 7160 | |
|
7153 |
/* including file 'src/axis/axis.cpp', size 9 |
|
|
7154 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
7161 | /* including file 'src/axis/axis.cpp', size 99397 */ | |
|
7162 | /* commit 0cc4d9f61f7bf45321a88fec89d909b020ffa26f 2017-08-14 00:43:29 +0200 */ | |
|
7155 | 7163 | |
|
7156 | 7164 | |
|
7157 | 7165 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
@@ -8643,11 +8651,11 double QCPAxis::coordToPixel(double value) const | |||
|
8643 | 8651 | } |
|
8644 | 8652 | else // mScaleType == stLogarithmic |
|
8645 | 8653 | { |
|
8646 |
if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just |
|
|
8647 | // outside visible range | |
|
8654 | if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just | |
|
8655 | // draw it outside visible range | |
|
8648 | 8656 | return !mRangeReversed ? mAxisRect->right() + 200 : mAxisRect->left() - 200; |
|
8649 |
else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, |
|
|
8650 | // draw it outside visible range | |
|
8657 | else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, | |
|
8658 | // just draw it outside visible range | |
|
8651 | 8659 | return !mRangeReversed ? mAxisRect->left() - 200 : mAxisRect->right() + 200; |
|
8652 | 8660 | else { |
|
8653 | 8661 | if (!mRangeReversed) |
@@ -8673,11 +8681,11 double QCPAxis::coordToPixel(double value) const | |||
|
8673 | 8681 | } |
|
8674 | 8682 | else // mScaleType == stLogarithmic |
|
8675 | 8683 | { |
|
8676 |
if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just |
|
|
8677 | // outside visible range | |
|
8684 | if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just | |
|
8685 | // draw it outside visible range | |
|
8678 | 8686 | return !mRangeReversed ? mAxisRect->top() - 200 : mAxisRect->bottom() + 200; |
|
8679 |
else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, |
|
|
8680 | // draw it outside visible range | |
|
8687 | else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, | |
|
8688 | // just draw it outside visible range | |
|
8681 | 8689 | return !mRangeReversed ? mAxisRect->bottom() + 200 : mAxisRect->top() - 200; |
|
8682 | 8690 | else { |
|
8683 | 8691 | if (!mRangeReversed) |
@@ -8868,6 +8876,132 void QCPAxis::deselectEvent(bool *selectionStateChanged) | |||
|
8868 | 8876 | |
|
8869 | 8877 | /*! \internal |
|
8870 | 8878 | |
|
8879 | This mouse event reimplementation provides the functionality to let the user drag individual axes | |
|
8880 | exclusively, by startig the drag on top of the axis. | |
|
8881 | ||
|
8882 | For the axis to accept this event and perform the single axis drag, the parent \ref QCPAxisRect | |
|
8883 | must be configured accordingly, i.e. it must allow range dragging in the orientation of this axis | |
|
8884 | (\ref QCPAxisRect::setRangeDrag) and this axis must be a draggable axis (\ref | |
|
8885 | QCPAxisRect::setRangeDragAxes) | |
|
8886 | ||
|
8887 | \seebaseclassmethod | |
|
8888 | ||
|
8889 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis | |
|
8890 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. | |
|
8891 | */ | |
|
8892 | void QCPAxis::mousePressEvent(QMouseEvent *event, const QVariant &details) | |
|
8893 | { | |
|
8894 | Q_UNUSED(details) | |
|
8895 | if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag) | |
|
8896 | || !mAxisRect->rangeDrag().testFlag(orientation()) | |
|
8897 | || !mAxisRect->rangeDragAxes(orientation()).contains(this)) { | |
|
8898 | event->ignore(); | |
|
8899 | return; | |
|
8900 | } | |
|
8901 | ||
|
8902 | if (event->buttons() & Qt::LeftButton) { | |
|
8903 | mDragging = true; | |
|
8904 | // initialize antialiasing backup in case we start dragging: | |
|
8905 | if (mParentPlot->noAntialiasingOnDrag()) { | |
|
8906 | mAADragBackup = mParentPlot->antialiasedElements(); | |
|
8907 | mNotAADragBackup = mParentPlot->notAntialiasedElements(); | |
|
8908 | } | |
|
8909 | // Mouse range dragging interaction: | |
|
8910 | if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) | |
|
8911 | mDragStartRange = mRange; | |
|
8912 | } | |
|
8913 | } | |
|
8914 | ||
|
8915 | /*! \internal | |
|
8916 | ||
|
8917 | This mouse event reimplementation provides the functionality to let the user drag individual axes | |
|
8918 | exclusively, by startig the drag on top of the axis. | |
|
8919 | ||
|
8920 | \seebaseclassmethod | |
|
8921 | ||
|
8922 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis | |
|
8923 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. | |
|
8924 | ||
|
8925 | \see QCPAxis::mousePressEvent | |
|
8926 | */ | |
|
8927 | void QCPAxis::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |
|
8928 | { | |
|
8929 | if (mDragging) { | |
|
8930 | const double startPixel = orientation() == Qt::Horizontal ? startPos.x() : startPos.y(); | |
|
8931 | const double currentPixel | |
|
8932 | = orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y(); | |
|
8933 | if (mScaleType == QCPAxis::stLinear) { | |
|
8934 | const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel); | |
|
8935 | setRange(mDragStartRange.lower + diff, mDragStartRange.upper + diff); | |
|
8936 | } | |
|
8937 | else if (mScaleType == QCPAxis::stLogarithmic) { | |
|
8938 | const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel); | |
|
8939 | setRange(mDragStartRange.lower * diff, mDragStartRange.upper * diff); | |
|
8940 | } | |
|
8941 | ||
|
8942 | if (mParentPlot->noAntialiasingOnDrag()) | |
|
8943 | mParentPlot->setNotAntialiasedElements(QCP::aeAll); | |
|
8944 | mParentPlot->replot(QCustomPlot::rpQueuedReplot); | |
|
8945 | } | |
|
8946 | } | |
|
8947 | ||
|
8948 | /*! \internal | |
|
8949 | ||
|
8950 | This mouse event reimplementation provides the functionality to let the user drag individual axes | |
|
8951 | exclusively, by startig the drag on top of the axis. | |
|
8952 | ||
|
8953 | \seebaseclassmethod | |
|
8954 | ||
|
8955 | \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis | |
|
8956 | rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. | |
|
8957 | ||
|
8958 | \see QCPAxis::mousePressEvent | |
|
8959 | */ | |
|
8960 | void QCPAxis::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) | |
|
8961 | { | |
|
8962 | Q_UNUSED(event) | |
|
8963 | Q_UNUSED(startPos) | |
|
8964 | mDragging = false; | |
|
8965 | if (mParentPlot->noAntialiasingOnDrag()) { | |
|
8966 | mParentPlot->setAntialiasedElements(mAADragBackup); | |
|
8967 | mParentPlot->setNotAntialiasedElements(mNotAADragBackup); | |
|
8968 | } | |
|
8969 | } | |
|
8970 | ||
|
8971 | /*! \internal | |
|
8972 | ||
|
8973 | This mouse event reimplementation provides the functionality to let the user zoom individual axes | |
|
8974 | exclusively, by performing the wheel event on top of the axis. | |
|
8975 | ||
|
8976 | For the axis to accept this event and perform the single axis zoom, the parent \ref QCPAxisRect | |
|
8977 | must be configured accordingly, i.e. it must allow range zooming in the orientation of this axis | |
|
8978 | (\ref QCPAxisRect::setRangeZoom) and this axis must be a zoomable axis (\ref | |
|
8979 | QCPAxisRect::setRangeZoomAxes) | |
|
8980 | ||
|
8981 | \seebaseclassmethod | |
|
8982 | ||
|
8983 | \note The zooming of possibly multiple axes at once by performing the wheel event anywhere in the | |
|
8984 | axis rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::wheelEvent. | |
|
8985 | */ | |
|
8986 | void QCPAxis::wheelEvent(QWheelEvent *event) | |
|
8987 | { | |
|
8988 | // Mouse range zooming interaction: | |
|
8989 | if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom) | |
|
8990 | || !mAxisRect->rangeZoom().testFlag(orientation()) | |
|
8991 | || !mAxisRect->rangeZoomAxes(orientation()).contains(this)) { | |
|
8992 | event->ignore(); | |
|
8993 | return; | |
|
8994 | } | |
|
8995 | ||
|
8996 | const double wheelSteps = event->delta() / 120.0; // a single step delta is +/-120 usually | |
|
8997 | const double factor = qPow(mAxisRect->rangeZoomFactor(orientation()), wheelSteps); | |
|
8998 | scaleRange(factor, | |
|
8999 | pixelToCoord(orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y())); | |
|
9000 | mParentPlot->replot(); | |
|
9001 | } | |
|
9002 | ||
|
9003 | /*! \internal | |
|
9004 | ||
|
8871 | 9005 | A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter |
|
8872 | 9006 | before drawing axis lines. |
|
8873 | 9007 | |
@@ -9257,14 +9391,16 void QCPAxisPainterPrivate::draw(QCPPainter *painter) | |||
|
9257 | 9391 | painter->setBrush(QBrush(basePen.color())); |
|
9258 | 9392 | QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy()); |
|
9259 | 9393 | if (lowerEnding.style() != QCPLineEnding::esNone) |
|
9260 |
lowerEnding.draw(painter, |
|
|
9261 | - baseLineVector.normalized() * lowerEnding.realLength() | |
|
9262 | * (lowerEnding.inverted() ? -1 : 1), | |
|
9394 | lowerEnding.draw(painter, | |
|
9395 | QCPVector2D(baseLine.p1()) | |
|
9396 | - baseLineVector.normalized() * lowerEnding.realLength() | |
|
9397 | * (lowerEnding.inverted() ? -1 : 1), | |
|
9263 | 9398 | -baseLineVector); |
|
9264 | 9399 | if (upperEnding.style() != QCPLineEnding::esNone) |
|
9265 |
upperEnding.draw(painter, |
|
|
9266 | + baseLineVector.normalized() * upperEnding.realLength() | |
|
9267 | * (upperEnding.inverted() ? -1 : 1), | |
|
9400 | upperEnding.draw(painter, | |
|
9401 | QCPVector2D(baseLine.p2()) | |
|
9402 | + baseLineVector.normalized() * upperEnding.realLength() | |
|
9403 | * (upperEnding.inverted() ? -1 : 1), | |
|
9268 | 9404 | baseLineVector); |
|
9269 | 9405 | painter->setAntialiasing(antialiasingBackup); |
|
9270 | 9406 | |
@@ -9524,12 +9660,15 void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, | |||
|
9524 | 9660 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size() |
|
9525 | 9661 | * mParentPlot->bufferDevicePixelRatio()); |
|
9526 | 9662 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED |
|
9663 | #ifdef QCP_DEVICEPIXELRATIO_FLOAT | |
|
9664 | cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF()); | |
|
9665 | #else | |
|
9527 | 9666 | cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio()); |
|
9528 | 9667 | #endif |
|
9668 | #endif | |
|
9529 | 9669 | } |
|
9530 | 9670 | else |
|
9531 | 9671 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); |
|
9532 | cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); | |
|
9533 | 9672 | cachedLabel->pixmap.fill(Qt::transparent); |
|
9534 | 9673 | QCPPainter cachePainter(&cachedLabel->pixmap); |
|
9535 | 9674 | cachePainter.setPen(painter->pen()); |
@@ -9894,8 +10033,8 void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString | |||
|
9894 | 10033 | /* end of 'src/axis/axis.cpp' */ |
|
9895 | 10034 | |
|
9896 | 10035 | |
|
9897 |
/* including file 'src/scatterstyle.cpp', size 174 |
|
|
9898 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
10036 | /* including file 'src/scatterstyle.cpp', size 17450 */ | |
|
10037 | /* commit 820d2282db70144c358c13433cd74b4175f9252b 2017-07-24 00:24:17 +0200 */ | |
|
9899 | 10038 | |
|
9900 | 10039 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
9901 | 10040 | //////////////////// QCPScatterStyle |
@@ -10065,8 +10204,8 QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) | |||
|
10065 | 10204 | |
|
10066 | 10205 | The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly |
|
10067 | 10206 | different meaning than for built-in scatter points: The custom path will be drawn scaled by a |
|
10068 |
factor of \a size/6.0. Since the default \a size is 6, the custom path will appear |
|
|
10069 |
n |
|
|
10207 | factor of \a size/6.0. Since the default \a size is 6, the custom path will appear in its | |
|
10208 | original size by default. To for example double the size of the path, set \a size to 12. | |
|
10070 | 10209 | */ |
|
10071 | 10210 | QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, |
|
10072 | 10211 | const QBrush &brush, double size) |
@@ -10253,10 +10392,9 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||
|
10253 | 10392 | break; |
|
10254 | 10393 | } |
|
10255 | 10394 | case ssDiamond: { |
|
10256 | painter->drawLine(QLineF(x - w, y, x, y - w)); | |
|
10257 | painter->drawLine(QLineF(x, y - w, x + w, y)); | |
|
10258 |
painter->draw |
|
|
10259 | painter->drawLine(QLineF(x, y + w, x - w, y)); | |
|
10395 | QPointF lineArray[4] | |
|
10396 | = {QPointF(x - w, y), QPointF(x, y - w), QPointF(x + w, y), QPointF(x, y + w)}; | |
|
10397 | painter->drawPolygon(lineArray, 4); | |
|
10260 | 10398 | break; |
|
10261 | 10399 | } |
|
10262 | 10400 | case ssStar: { |
@@ -10267,46 +10405,46 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||
|
10267 | 10405 | break; |
|
10268 | 10406 | } |
|
10269 | 10407 | case ssTriangle: { |
|
10270 |
|
|
|
10271 | painter->drawLine(QLineF(x + w, y + 0.755 * w, x, y - 0.977 * w)); | |
|
10272 | painter->drawLine(QLineF(x, y - 0.977 * w, x - w, y + 0.755 * w)); | |
|
10408 | QPointF lineArray[3] = {QPointF(x - w, y + 0.755 * w), QPointF(x + w, y + 0.755 * w), | |
|
10409 | QPointF(x, y - 0.977 * w)}; | |
|
10410 | painter->drawPolygon(lineArray, 3); | |
|
10273 | 10411 | break; |
|
10274 | 10412 | } |
|
10275 | 10413 | case ssTriangleInverted: { |
|
10276 |
|
|
|
10277 | painter->drawLine(QLineF(x + w, y - 0.755 * w, x, y + 0.977 * w)); | |
|
10278 | painter->drawLine(QLineF(x, y + 0.977 * w, x - w, y - 0.755 * w)); | |
|
10414 | QPointF lineArray[3] = {QPointF(x - w, y - 0.755 * w), QPointF(x + w, y - 0.755 * w), | |
|
10415 | QPointF(x, y + 0.977 * w)}; | |
|
10416 | painter->drawPolygon(lineArray, 3); | |
|
10279 | 10417 | break; |
|
10280 | 10418 | } |
|
10281 | 10419 | case ssCrossSquare: { |
|
10420 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |
|
10282 | 10421 | painter->drawLine(QLineF(x - w, y - w, x + w * 0.95, y + w * 0.95)); |
|
10283 | 10422 | painter->drawLine(QLineF(x - w, y + w * 0.95, x + w * 0.95, y - w)); |
|
10284 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |
|
10285 | 10423 | break; |
|
10286 | 10424 | } |
|
10287 | 10425 | case ssPlusSquare: { |
|
10426 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |
|
10288 | 10427 | painter->drawLine(QLineF(x - w, y, x + w * 0.95, y)); |
|
10289 | 10428 | painter->drawLine(QLineF(x, y + w, x, y - w)); |
|
10290 | painter->drawRect(QRectF(x - w, y - w, mSize, mSize)); | |
|
10291 | 10429 | break; |
|
10292 | 10430 | } |
|
10293 | 10431 | case ssCrossCircle: { |
|
10432 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10294 | 10433 | painter->drawLine(QLineF(x - w * 0.707, y - w * 0.707, x + w * 0.670, y + w * 0.670)); |
|
10295 | 10434 | painter->drawLine(QLineF(x - w * 0.707, y + w * 0.670, x + w * 0.670, y - w * 0.707)); |
|
10296 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10297 | 10435 | break; |
|
10298 | 10436 | } |
|
10299 | 10437 | case ssPlusCircle: { |
|
10438 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10300 | 10439 | painter->drawLine(QLineF(x - w, y, x + w, y)); |
|
10301 | 10440 | painter->drawLine(QLineF(x, y + w, x, y - w)); |
|
10302 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10303 | 10441 | break; |
|
10304 | 10442 | } |
|
10305 | 10443 | case ssPeace: { |
|
10444 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10306 | 10445 | painter->drawLine(QLineF(x, y - w, x, y + w)); |
|
10307 | 10446 | painter->drawLine(QLineF(x, y, x - w * 0.707, y + w * 0.707)); |
|
10308 | 10447 | painter->drawLine(QLineF(x, y, x + w * 0.707, y + w * 0.707)); |
|
10309 | painter->drawEllipse(QPointF(x, y), w, w); | |
|
10310 | 10448 | break; |
|
10311 | 10449 | } |
|
10312 | 10450 | case ssPixmap: { |
@@ -10337,8 +10475,8 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||
|
10337 | 10475 | |
|
10338 | 10476 | // amalgamation: add datacontainer.cpp |
|
10339 | 10477 | |
|
10340 |
/* including file 'src/plottable.cpp', size 388 |
|
|
10341 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
10478 | /* including file 'src/plottable.cpp', size 38845 */ | |
|
10479 | /* commit b0bed12626f942821097f43091126b6fb7163122 2017-08-13 17:17:33 +0200 */ | |
|
10342 | 10480 | |
|
10343 | 10481 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
10344 | 10482 | //////////////////// QCPSelectionDecorator |
@@ -10376,8 +10514,8 void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const | |||
|
10376 | 10514 | QCPSelectionDecorator::QCPSelectionDecorator() |
|
10377 | 10515 | : mPen(QColor(80, 80, 255), 2.5), |
|
10378 | 10516 | mBrush(Qt::NoBrush), |
|
10379 | mScatterStyle(QCPScatterStyle::ssNone, QPen(Qt::blue, 2), Qt::NoBrush, 6.0), | |
|
10380 |
mUsedScatterProperties(QCPScatterStyle::sp |
|
|
10517 | mScatterStyle(), | |
|
10518 | mUsedScatterProperties(QCPScatterStyle::spNone), | |
|
10381 | 10519 | mPlottable(0) |
|
10382 | 10520 | { |
|
10383 | 10521 | } |
@@ -10420,6 +10558,8 void QCPSelectionDecorator::setScatterStyle(const QCPScatterStyle &scatterStyle, | |||
|
10420 | 10558 | Use this method to define which properties of the scatter style (set via \ref setScatterStyle) |
|
10421 | 10559 | will be used for selected data segments. All properties of the scatter style that are not |
|
10422 | 10560 | specified in \a properties will remain as specified in the plottable's original scatter style. |
|
10561 | ||
|
10562 | \see QCPScatterStyle::ScatterProperty | |
|
10423 | 10563 | */ |
|
10424 | 10564 | void QCPSelectionDecorator::setUsedScatterProperties( |
|
10425 | 10565 | const QCPScatterStyle::ScatterProperties &properties) |
@@ -12624,8 +12764,8 QCP::Interaction QCPAbstractItem::selectionCategory() const | |||
|
12624 | 12764 | /* end of 'src/item.cpp' */ |
|
12625 | 12765 | |
|
12626 | 12766 | |
|
12627 |
/* including file 'src/core.cpp', size 12 |
|
|
12628 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
12767 | /* including file 'src/core.cpp', size 125027 */ | |
|
12768 | /* commit 9ede7553208db59867d1ea9f1988cd90e3c7ffed 2017-08-13 17:25:24 +0200 */ | |
|
12629 | 12769 | |
|
12630 | 12770 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
12631 | 12771 | //////////////////// QCustomPlot |
@@ -12969,6 +13109,7 QCustomPlot::QCustomPlot(QWidget *parent) | |||
|
12969 | 13109 | mOpenGl(false), |
|
12970 | 13110 | mMouseHasMoved(false), |
|
12971 | 13111 | mMouseEventLayerable(0), |
|
13112 | mMouseSignalLayerable(0), | |
|
12972 | 13113 | mReplotting(false), |
|
12973 | 13114 | mReplotQueued(false), |
|
12974 | 13115 | mOpenGlMultisamples(16), |
@@ -12983,8 +13124,12 QCustomPlot::QCustomPlot(QWidget *parent) | |||
|
12983 | 13124 | currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); |
|
12984 | 13125 | setLocale(currentLocale); |
|
12985 | 13126 | #ifdef QCP_DEVICEPIXELRATIO_SUPPORTED |
|
13127 | #ifdef QCP_DEVICEPIXELRATIO_FLOAT | |
|
13128 | setBufferDevicePixelRatio(QWidget::devicePixelRatioF()); | |
|
13129 | #else | |
|
12986 | 13130 | setBufferDevicePixelRatio(QWidget::devicePixelRatio()); |
|
12987 | 13131 | #endif |
|
13132 | #endif | |
|
12988 | 13133 | |
|
12989 | 13134 | mOpenGlAntialiasedElementsBackup = mAntialiasedElements; |
|
12990 | 13135 | mOpenGlCacheLabelsBackup = mPlottingHints.testFlag(QCP::phCacheLabels); |
@@ -13386,6 +13531,10 void QCustomPlot::setSelectionRect(QCPSelectionRect *selectionRect) | |||
|
13386 | 13531 | } |
|
13387 | 13532 | |
|
13388 | 13533 | /*! |
|
13534 | \warning This is still an experimental feature and its performance depends on the system that it | |
|
13535 | runs on. Having multiple QCustomPlot widgets in one application with enabled OpenGL rendering | |
|
13536 | might cause context conflicts on some systems. | |
|
13537 | ||
|
13389 | 13538 | This method allows to enable OpenGL plot rendering, for increased plotting performance of |
|
13390 | 13539 | graphically demanding plots (thick lines, translucent fills, etc.). |
|
13391 | 13540 | |
@@ -14934,12 +15083,20 void QCustomPlot::mousePressEvent(QMouseEvent *event) | |||
|
14934 | 15083 | mSelectionRect->startSelection(event); |
|
14935 | 15084 | } |
|
14936 | 15085 | else { |
|
14937 |
// no selection rect interaction, so forward event to |
|
|
15086 | // no selection rect interaction, prepare for click signal emission and forward event to | |
|
15087 | // layerable under the cursor: | |
|
14938 | 15088 | QList<QVariant> details; |
|
14939 | 15089 | QList<QCPLayerable *> candidates = layerableListAt(mMousePressPos, false, &details); |
|
15090 | if (!candidates.isEmpty()) { | |
|
15091 | mMouseSignalLayerable = candidates.first(); // candidate for signal emission is always | |
|
15092 | // topmost hit layerable (signal emitted in | |
|
15093 | // release event) | |
|
15094 | mMouseSignalLayerableDetails = details.first(); | |
|
15095 | } | |
|
15096 | // forward event to topmost candidate which accepts the event: | |
|
14940 | 15097 | for (int i = 0; i < candidates.size(); ++i) { |
|
14941 |
event->accept(); // default impl of QCPLayerable's mouse events ignore the |
|
|
14942 | // that case propagate to next candidate in list | |
|
15098 | event->accept(); // default impl of QCPLayerable's mouse events call ignore() on the | |
|
15099 | // event, in that case propagate to next candidate in list | |
|
14943 | 15100 | candidates.at(i)->mousePressEvent(event, details.at(i)); |
|
14944 | 15101 | if (event->isAccepted()) { |
|
14945 | 15102 | mMouseEventLayerable = candidates.at(i); |
@@ -15010,22 +15167,25 void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) | |||
|
15010 | 15167 | processPointSelection(event); |
|
15011 | 15168 | |
|
15012 | 15169 | // emit specialized click signals of QCustomPlot instance: |
|
15013 | if (QCPAbstractPlottable *ap = qobject_cast<QCPAbstractPlottable *>(mMouseEventLayerable)) { | |
|
15170 | if (QCPAbstractPlottable *ap | |
|
15171 | = qobject_cast<QCPAbstractPlottable *>(mMouseSignalLayerable)) { | |
|
15014 | 15172 | int dataIndex = 0; |
|
15015 |
if (!mMouse |
|
|
15173 | if (!mMouseSignalLayerableDetails.value<QCPDataSelection>().isEmpty()) | |
|
15016 | 15174 | dataIndex |
|
15017 |
= mMouse |
|
|
15175 | = mMouseSignalLayerableDetails.value<QCPDataSelection>().dataRange().begin(); | |
|
15018 | 15176 | emit plottableClick(ap, dataIndex, event); |
|
15019 | 15177 | } |
|
15020 |
else if (QCPAxis *ax = qobject_cast<QCPAxis *>(mMouse |
|
|
15021 |
emit axisClick(ax, mMouse |
|
|
15022 | else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem *>(mMouseEventLayerable)) | |
|
15178 | else if (QCPAxis *ax = qobject_cast<QCPAxis *>(mMouseSignalLayerable)) | |
|
15179 | emit axisClick(ax, mMouseSignalLayerableDetails.value<QCPAxis::SelectablePart>(), | |
|
15180 | event); | |
|
15181 | else if (QCPAbstractItem *ai = qobject_cast<QCPAbstractItem *>(mMouseSignalLayerable)) | |
|
15023 | 15182 | emit itemClick(ai, event); |
|
15024 |
else if (QCPLegend *lg = qobject_cast<QCPLegend *>(mMouse |
|
|
15183 | else if (QCPLegend *lg = qobject_cast<QCPLegend *>(mMouseSignalLayerable)) | |
|
15025 | 15184 | emit legendClick(lg, 0, event); |
|
15026 | 15185 | else if (QCPAbstractLegendItem *li |
|
15027 |
= qobject_cast<QCPAbstractLegendItem *>(mMouse |
|
|
15186 | = qobject_cast<QCPAbstractLegendItem *>(mMouseSignalLayerable)) | |
|
15028 | 15187 | emit legendClick(li->parentLegend(), li, event); |
|
15188 | mMouseSignalLayerable = 0; | |
|
15029 | 15189 | } |
|
15030 | 15190 | |
|
15031 | 15191 | if (mSelectionRect && mSelectionRect->isActive()) // Note: if a click was detected above, the |
@@ -16469,8 +16629,9 void QCPColorGradient::updateColorBuffer() | |||
|
16469 | 16629 | hue -= 1.0; |
|
16470 | 16630 | if (useAlpha) { |
|
16471 | 16631 | const QRgb rgb |
|
16472 |
= QColor::fromHsvF(hue, |
|
|
16473 |
|
|
|
16632 | = QColor::fromHsvF(hue, | |
|
16633 | (1 - t) * lowHsv.saturationF() | |
|
16634 | + t * highHsv.saturationF(), | |
|
16474 | 16635 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) |
|
16475 | 16636 | .rgb(); |
|
16476 | 16637 | const float alpha = (1 - t) * lowHsv.alphaF() + t * highHsv.alphaF(); |
@@ -16479,8 +16640,9 void QCPColorGradient::updateColorBuffer() | |||
|
16479 | 16640 | } |
|
16480 | 16641 | else { |
|
16481 | 16642 | mColorBuffer[i] |
|
16482 |
= QColor::fromHsvF(hue, |
|
|
16483 |
|
|
|
16643 | = QColor::fromHsvF(hue, | |
|
16644 | (1 - t) * lowHsv.saturationF() | |
|
16645 | + t * highHsv.saturationF(), | |
|
16484 | 16646 | (1 - t) * lowHsv.valueF() + t * highHsv.valueF()) |
|
16485 | 16647 | .rgb(); |
|
16486 | 16648 | } |
@@ -16797,8 +16959,8 QCPSelectionDecoratorBracket::getPixelCoordinates(const QCPPlottableInterface1D | |||
|
16797 | 16959 | /* end of 'src/selectiondecorator-bracket.cpp' */ |
|
16798 | 16960 | |
|
16799 | 16961 | |
|
16800 |
/* including file 'src/layoutelements/layoutelement-axisrect.cpp', size 475 |
|
|
16801 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
16962 | /* including file 'src/layoutelements/layoutelement-axisrect.cpp', size 47584 */ | |
|
16963 | /* commit 77ba168312f935543fc31d1ae9b4cdcf34aae4f9 2017-08-13 18:29:48 +0200 */ | |
|
16802 | 16964 | |
|
16803 | 16965 | |
|
16804 | 16966 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
@@ -17052,7 +17214,7 QList<QCPAxis *> QCPAxisRect::axes() const | |||
|
17052 | 17214 | new QCPAxis instance is created internally. QCustomPlot owns the returned axis, so if you want to |
|
17053 | 17215 | remove an axis, use \ref removeAxis instead of deleting it manually. |
|
17054 | 17216 | |
|
17055 | You may inject QCPAxis instances (or sublasses of QCPAxis) by setting \a axis to an axis that was | |
|
17217 | You may inject QCPAxis instances (or subclasses of QCPAxis) by setting \a axis to an axis that was | |
|
17056 | 17218 | previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership |
|
17057 | 17219 | of the axis, so you may not delete it afterwards. Further, the \a axis must have been created |
|
17058 | 17220 | with this axis rect as parent and with the same axis type as specified in \a type. If this is not |
@@ -17165,6 +17327,12 bool QCPAxisRect::removeAxis(QCPAxis *axis) | |||
|
17165 | 17327 | while (it.hasNext()) { |
|
17166 | 17328 | it.next(); |
|
17167 | 17329 | if (it.value().contains(axis)) { |
|
17330 | if (it.value().first() == axis && it.value().size() > 1) // if removing first axis, | |
|
17331 | // transfer axis offset to the | |
|
17332 | // new first axis (which at | |
|
17333 | // this point is the second | |
|
17334 | // axis, if it exists) | |
|
17335 | it.value()[1]->setOffset(axis->offset()); | |
|
17168 | 17336 | mAxes[it.key()].removeOne(axis); |
|
17169 | 17337 | if (qobject_cast<QCustomPlot *>(parentPlot())) // make sure this isn't called from |
|
17170 | 17338 | // QObject dtor when QCustomPlot is |
@@ -17934,9 +18102,6 void QCPAxisRect::layoutChanged() | |||
|
17934 | 18102 | void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details) |
|
17935 | 18103 | { |
|
17936 | 18104 | Q_UNUSED(details) |
|
17937 | mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in | |
|
17938 | // releaseEvent whether it was a full click (no position change | |
|
17939 | // between press and release) | |
|
17940 | 18105 | if (event->buttons() & Qt::LeftButton) { |
|
17941 | 18106 | mDragging = true; |
|
17942 | 18107 | // initialize antialiasing backup in case we start dragging: |
@@ -17982,13 +18147,13 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||
|
17982 | 18147 | break; |
|
17983 | 18148 | if (ax->mScaleType == QCPAxis::stLinear) { |
|
17984 | 18149 | double diff |
|
17985 |
= ax->pixelToCoord( |
|
|
18150 | = ax->pixelToCoord(startPos.x()) - ax->pixelToCoord(event->pos().x()); | |
|
17986 | 18151 | ax->setRange(mDragStartHorzRange.at(i).lower + diff, |
|
17987 | 18152 | mDragStartHorzRange.at(i).upper + diff); |
|
17988 | 18153 | } |
|
17989 | 18154 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { |
|
17990 | 18155 | double diff |
|
17991 |
= ax->pixelToCoord( |
|
|
18156 | = ax->pixelToCoord(startPos.x()) / ax->pixelToCoord(event->pos().x()); | |
|
17992 | 18157 | ax->setRange(mDragStartHorzRange.at(i).lower * diff, |
|
17993 | 18158 | mDragStartHorzRange.at(i).upper * diff); |
|
17994 | 18159 | } |
@@ -18004,13 +18169,13 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||
|
18004 | 18169 | break; |
|
18005 | 18170 | if (ax->mScaleType == QCPAxis::stLinear) { |
|
18006 | 18171 | double diff |
|
18007 |
= ax->pixelToCoord( |
|
|
18172 | = ax->pixelToCoord(startPos.y()) - ax->pixelToCoord(event->pos().y()); | |
|
18008 | 18173 | ax->setRange(mDragStartVertRange.at(i).lower + diff, |
|
18009 | 18174 | mDragStartVertRange.at(i).upper + diff); |
|
18010 | 18175 | } |
|
18011 | 18176 | else if (ax->mScaleType == QCPAxis::stLogarithmic) { |
|
18012 | 18177 | double diff |
|
18013 |
= ax->pixelToCoord( |
|
|
18178 | = ax->pixelToCoord(startPos.y()) / ax->pixelToCoord(event->pos().y()); | |
|
18014 | 18179 | ax->setRange(mDragStartVertRange.at(i).lower * diff, |
|
18015 | 18180 | mDragStartVertRange.at(i).upper * diff); |
|
18016 | 18181 | } |
@@ -18021,7 +18186,7 void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) | |||
|
18021 | 18186 | { |
|
18022 | 18187 | if (mParentPlot->noAntialiasingOnDrag()) |
|
18023 | 18188 | mParentPlot->setNotAntialiasedElements(QCP::aeAll); |
|
18024 | mParentPlot->replot(); | |
|
18189 | mParentPlot->replot(QCustomPlot::rpQueuedReplot); | |
|
18025 | 18190 | } |
|
18026 | 18191 | } |
|
18027 | 18192 | } |
@@ -18082,8 +18247,8 void QCPAxisRect::wheelEvent(QWheelEvent *event) | |||
|
18082 | 18247 | /* end of 'src/layoutelements/layoutelement-axisrect.cpp' */ |
|
18083 | 18248 | |
|
18084 | 18249 | |
|
18085 |
/* including file 'src/layoutelements/layoutelement-legend.cpp', size 309 |
|
|
18086 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
18250 | /* including file 'src/layoutelements/layoutelement-legend.cpp', size 30971 */ | |
|
18251 | /* commit 305808813c9c6451dca8399c2fc66d68ebd24b5e 2017-08-15 23:03:07 +0200 */ | |
|
18087 | 18252 | |
|
18088 | 18253 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
18089 | 18254 | //////////////////// QCPAbstractLegendItem |
@@ -18286,9 +18451,7 void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged) | |||
|
18286 | 18451 | QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding. |
|
18287 | 18452 | |
|
18288 | 18453 | The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend |
|
18289 |
creates/removes legend items of this type |
|
|
18290 | may be reimplemented such that a different kind of legend item (e.g a direct subclass of | |
|
18291 | QCPAbstractLegendItem) is used for that plottable. | |
|
18454 | creates/removes legend items of this type. | |
|
18292 | 18455 | |
|
18293 | 18456 | Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of |
|
18294 | 18457 | QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout |
@@ -18395,10 +18558,8 QSize QCPPlottableLegendItem::minimumSizeHint() const | |||
|
18395 | 18558 | QSize iconSize = mParentLegend->iconSize(); |
|
18396 | 18559 | textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, |
|
18397 | 18560 | mPlottable->name()); |
|
18398 | result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() | |
|
18399 | + mMargins.left() + mMargins.right()); | |
|
18400 | result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() | |
|
18401 | + mMargins.bottom()); | |
|
18561 | result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width()); | |
|
18562 | result.setHeight(qMax(textRect.height(), iconSize.height())); | |
|
18402 | 18563 | return result; |
|
18403 | 18564 | } |
|
18404 | 18565 | |
@@ -18412,10 +18573,14 QSize QCPPlottableLegendItem::minimumSizeHint() const | |||
|
18412 | 18573 | |
|
18413 | 18574 | A legend is a small box somewhere in the plot which lists plottables with their name and icon. |
|
18414 | 18575 | |
|
18415 |
|
|
|
18416 | respective legend item can be removed with \ref QCPAbstractPlottable::removeFromLegend. However, | |
|
18417 | QCPLegend also offers an interface to add and manipulate legend items directly: \ref item, \ref | |
|
18418 | itemWithPlottable, \ref itemCount, \ref addItem, \ref removeItem, etc. | |
|
18576 | A legend is populated with legend items by calling \ref QCPAbstractPlottable::addToLegend on the | |
|
18577 | plottable, for which a legend item shall be created. In the case of the main legend (\ref | |
|
18578 | QCustomPlot::legend), simply adding plottables to the plot while \ref | |
|
18579 | QCustomPlot::setAutoAddPlottableToLegend is set to true (the default) creates corresponding | |
|
18580 | legend items. The legend item associated with a certain plottable can be removed with \ref | |
|
18581 | QCPAbstractPlottable::removeFromLegend. However, QCPLegend also offers an interface to add and | |
|
18582 | manipulate legend items directly: \ref item, \ref itemWithPlottable, \ref itemCount, \ref | |
|
18583 | addItem, \ref removeItem, etc. | |
|
18419 | 18584 | |
|
18420 | 18585 | Since \ref QCPLegend derives from \ref QCPLayoutGrid, it can be placed in any position a \ref |
|
18421 | 18586 | QCPLayoutElement may be positioned. The legend items are themselves \ref QCPLayoutElement |
@@ -18570,7 +18735,7 void QCPLegend::setIconSize(const QSize &size) | |||
|
18570 | 18735 | } |
|
18571 | 18736 | |
|
18572 | 18737 | /*! \overload |
|
18573 |
|
|
|
18738 | */ | |
|
18574 | 18739 | void QCPLegend::setIconSize(int width, int height) |
|
18575 | 18740 | { |
|
18576 | 18741 | mIconSize.setWidth(width); |
@@ -19012,8 +19177,8 void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot) | |||
|
19012 | 19177 | /* end of 'src/layoutelements/layoutelement-legend.cpp' */ |
|
19013 | 19178 | |
|
19014 | 19179 | |
|
19015 |
/* including file 'src/layoutelements/layoutelement-textelement.cpp', size 12 |
|
|
19016 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
19180 | /* including file 'src/layoutelements/layoutelement-textelement.cpp', size 12561 */ | |
|
19181 | /* commit a872eb91ec087561efd83dd9cb041a26ab95ce55 2017-07-31 00:21:41 +0200 */ | |
|
19017 | 19182 | |
|
19018 | 19183 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
19019 | 19184 | //////////////////// QCPTextElement |
@@ -19299,10 +19464,7 void QCPTextElement::draw(QCPPainter *painter) | |||
|
19299 | 19464 | QSize QCPTextElement::minimumSizeHint() const |
|
19300 | 19465 | { |
|
19301 | 19466 | QFontMetrics metrics(mFont); |
|
19302 |
|
|
|
19303 | result.rwidth() += mMargins.left() + mMargins.right(); | |
|
19304 | result.rheight() += mMargins.top() + mMargins.bottom(); | |
|
19305 | return result; | |
|
19467 | return metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); | |
|
19306 | 19468 | } |
|
19307 | 19469 | |
|
19308 | 19470 | /* inherits documentation from base class */ |
@@ -19310,7 +19472,6 QSize QCPTextElement::maximumSizeHint() const | |||
|
19310 | 19472 | { |
|
19311 | 19473 | QFontMetrics metrics(mFont); |
|
19312 | 19474 | QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); |
|
19313 | result.rheight() += mMargins.top() + mMargins.bottom(); | |
|
19314 | 19475 | result.setWidth(QWIDGETSIZE_MAX); |
|
19315 | 19476 | return result; |
|
19316 | 19477 | } |
@@ -19838,12 +19999,14 void QCPColorScale::update(UpdatePhase phase) | |||
|
19838 | 19999 | switch (phase) { |
|
19839 | 20000 | case upMargins: { |
|
19840 | 20001 | if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop) { |
|
19841 |
setMaximumSize(QWIDGETSIZE_MAX, |
|
|
19842 |
|
|
|
19843 |
|
|
|
19844 | setMinimumSize(0, mBarWidth + mAxisRect.data()->margins().top() | |
|
19845 | + mAxisRect.data()->margins().bottom() + margins().top() | |
|
19846 |
|
|
|
20002 | setMaximumSize(QWIDGETSIZE_MAX, | |
|
20003 | mBarWidth + mAxisRect.data()->margins().top() | |
|
20004 | + mAxisRect.data()->margins().bottom() + margins().top() | |
|
20005 | + margins().bottom()); | |
|
20006 | setMinimumSize(0, | |
|
20007 | mBarWidth + mAxisRect.data()->margins().top() | |
|
20008 | + mAxisRect.data()->margins().bottom() + margins().top() | |
|
20009 | + margins().bottom()); | |
|
19847 | 20010 | } |
|
19848 | 20011 | else { |
|
19849 | 20012 | setMaximumSize(mBarWidth + mAxisRect.data()->margins().left() |
@@ -20100,8 +20263,8 void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectablePart | |||
|
20100 | 20263 | /* end of 'src/layoutelements/layoutelement-colorscale.cpp' */ |
|
20101 | 20264 | |
|
20102 | 20265 | |
|
20103 |
/* including file 'src/plottables/plottable-graph.cpp', size 7 |
|
|
20104 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
20266 | /* including file 'src/plottables/plottable-graph.cpp', size 73960 */ | |
|
20267 | /* commit 7e7381ef4f218e004d72a218820634fff0959d1b 2017-08-02 00:02:36 +0200 */ | |
|
20105 | 20268 | |
|
20106 | 20269 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20107 | 20270 | //////////////////// QCPGraphData |
@@ -20649,6 +20812,12 void QCPGraph::getLines(QVector<QPointF> *lines, const QCPDataRange &dataRange) | |||
|
20649 | 20812 | if (mLineStyle != lsNone) |
|
20650 | 20813 | getOptimizedLineData(&lineData, begin, end); |
|
20651 | 20814 | |
|
20815 | if (mKeyAxis->rangeReversed() | |
|
20816 | != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending | |
|
20817 | // in lineData (significantly simplifies | |
|
20818 | // following processing) | |
|
20819 | std::reverse(lineData.begin(), lineData.end()); | |
|
20820 | ||
|
20652 | 20821 | switch (mLineStyle) { |
|
20653 | 20822 | case lsNone: |
|
20654 | 20823 | lines->clear(); |
@@ -20704,6 +20873,13 void QCPGraph::getScatters(QVector<QPointF> *scatters, const QCPDataRange &dataR | |||
|
20704 | 20873 | |
|
20705 | 20874 | QVector<QCPGraphData> data; |
|
20706 | 20875 | getOptimizedScatterData(&data, begin, end); |
|
20876 | ||
|
20877 | if (mKeyAxis->rangeReversed() | |
|
20878 | != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending | |
|
20879 | // in data (significantly simplifies following | |
|
20880 | // processing) | |
|
20881 | std::reverse(data.begin(), data.end()); | |
|
20882 | ||
|
20707 | 20883 | scatters->resize(data.size()); |
|
20708 | 20884 | if (keyAxis->orientation() == Qt::Vertical) { |
|
20709 | 20885 | for (int i = 0; i < data.size(); ++i) { |
@@ -20744,8 +20920,6 QVector<QPointF> QCPGraph::dataToLines(const QVector<QCPGraphData> &data) const | |||
|
20744 | 20920 | return result; |
|
20745 | 20921 | } |
|
20746 | 20922 | |
|
20747 | result.reserve(data.size() + 2); // added 2 to reserve memory for lower/upper fill base points | |
|
20748 | // that might be needed for fill | |
|
20749 | 20923 | result.resize(data.size()); |
|
20750 | 20924 | |
|
20751 | 20925 | // transform data points to pixels: |
@@ -20786,8 +20960,6 QVector<QPointF> QCPGraph::dataToStepLeftLines(const QVector<QCPGraphData> &data | |||
|
20786 | 20960 | return result; |
|
20787 | 20961 | } |
|
20788 | 20962 | |
|
20789 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |
|
20790 | // points that might be needed for fill | |
|
20791 | 20963 | result.resize(data.size() * 2); |
|
20792 | 20964 | |
|
20793 | 20965 | // calculate steps from data and transform to pixel coordinates: |
@@ -20838,8 +21010,6 QVector<QPointF> QCPGraph::dataToStepRightLines(const QVector<QCPGraphData> &dat | |||
|
20838 | 21010 | return result; |
|
20839 | 21011 | } |
|
20840 | 21012 | |
|
20841 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |
|
20842 | // points that might be needed for fill | |
|
20843 | 21013 | result.resize(data.size() * 2); |
|
20844 | 21014 | |
|
20845 | 21015 | // calculate steps from data and transform to pixel coordinates: |
@@ -20890,8 +21060,6 QVector<QPointF> QCPGraph::dataToStepCenterLines(const QVector<QCPGraphData> &da | |||
|
20890 | 21060 | return result; |
|
20891 | 21061 | } |
|
20892 | 21062 | |
|
20893 | result.reserve(data.size() * 2 + 2); // added 2 to reserve memory for lower/upper fill base | |
|
20894 | // points that might be needed for fill | |
|
20895 | 21063 | result.resize(data.size() * 2); |
|
20896 | 21064 | |
|
20897 | 21065 | // calculate steps from data and transform to pixel coordinates: |
@@ -20954,8 +21122,7 QVector<QPointF> QCPGraph::dataToImpulseLines(const QVector<QCPGraphData> &data) | |||
|
20954 | 21122 | return result; |
|
20955 | 21123 | } |
|
20956 | 21124 | |
|
20957 | result.resize(data.size() | |
|
20958 | * 2); // no need to reserve 2 extra points because impulse plot has no fill | |
|
21125 | result.resize(data.size() * 2); | |
|
20959 | 21126 | |
|
20960 | 21127 | // transform data points to pixels: |
|
20961 | 21128 | if (keyAxis->orientation() == Qt::Vertical) { |
@@ -20984,15 +21151,16 QVector<QPointF> QCPGraph::dataToImpulseLines(const QVector<QCPGraphData> &data) | |||
|
20984 | 21151 | |
|
20985 | 21152 | Draws the fill of the graph using the specified \a painter, with the currently set brush. |
|
20986 | 21153 | |
|
20987 | \a lines contains the points of the graph line, in pixel coordinates. | |
|
21154 | Depending on whether a normal fill or a channel fill (\ref setChannelFillGraph) is needed, \ref | |
|
21155 | getFillPolygon or \ref getChannelFillPolygon are used to find the according fill polygons. | |
|
20988 | 21156 | |
|
20989 | If the fill is a normal fill towards the zero-value-line, only the points in \a lines are | |
|
20990 | required and two extra points at the zero-value-line, which are added by \ref addFillBasePoints | |
|
20991 | and removed by \ref removeFillBasePoints after the fill drawing is done. | |
|
21157 | In order to handle NaN Data points correctly (the fill needs to be split into disjoint areas), | |
|
21158 | this method first determines a list of non-NaN segments with \ref getNonNanSegments, on which to | |
|
21159 | operate. In the channel fill case, \ref getOverlappingSegments is used to consolidate the non-NaN | |
|
21160 | segments of the two involved graphs, before passing the overlapping pairs to \ref | |
|
21161 | getChannelFillPolygon. | |
|
20992 | 21162 | |
|
20993 | On the other hand if the fill is a channel fill between this QCPGraph and another QCPGraph (\a | |
|
20994 | mChannelFillGraph), the more complex polygon is calculated with the \ref getChannelFillPolygon | |
|
20995 | function, and then drawn. | |
|
21163 | Pass the points of this graph's line as \a lines, in pixel coordinates. | |
|
20996 | 21164 | |
|
20997 | 21165 | \see drawLinePlot, drawImpulsePlot, drawScatterPlot |
|
20998 | 21166 | */ |
@@ -21004,15 +21172,25 void QCPGraph::drawFill(QCPPainter *painter, QVector<QPointF> *lines) const | |||
|
21004 | 21172 | return; |
|
21005 | 21173 | |
|
21006 | 21174 | applyFillAntialiasingHint(painter); |
|
21175 | QVector<QCPDataRange> segments = getNonNanSegments(lines, keyAxis()->orientation()); | |
|
21007 | 21176 | if (!mChannelFillGraph) { |
|
21008 | 21177 | // draw base fill under graph, fill goes all the way to the zero-value-line: |
|
21009 | addFillBasePoints(lines); | |
|
21010 |
painter->drawPolygon( |
|
|
21011 | removeFillBasePoints(lines); | |
|
21178 | for (int i = 0; i < segments.size(); ++i) | |
|
21179 | painter->drawPolygon(getFillPolygon(lines, segments.at(i))); | |
|
21012 | 21180 | } |
|
21013 | 21181 | else { |
|
21014 |
// draw |
|
|
21015 | painter->drawPolygon(getChannelFillPolygon(lines)); | |
|
21182 | // draw fill between this graph and mChannelFillGraph: | |
|
21183 | QVector<QPointF> otherLines; | |
|
21184 | mChannelFillGraph->getLines(&otherLines, QCPDataRange(0, mChannelFillGraph->dataCount())); | |
|
21185 | if (!otherLines.isEmpty()) { | |
|
21186 | QVector<QCPDataRange> otherSegments | |
|
21187 | = getNonNanSegments(&otherLines, mChannelFillGraph->keyAxis()->orientation()); | |
|
21188 | QVector<QPair<QCPDataRange, QCPDataRange> > segmentPairs | |
|
21189 | = getOverlappingSegments(segments, lines, otherSegments, &otherLines); | |
|
21190 | for (int i = 0; i < segmentPairs.size(); ++i) | |
|
21191 | painter->drawPolygon(getChannelFillPolygon(lines, segmentPairs.at(i).first, | |
|
21192 | &otherLines, segmentPairs.at(i).second)); | |
|
21193 | } | |
|
21016 | 21194 | } |
|
21017 | 21195 | } |
|
21018 | 21196 | |
@@ -21205,12 +21383,8 void QCPGraph::getOptimizedLineData(QVector<QCPGraphData> *lineData, | |||
|
21205 | 21383 | else // don't use adaptive sampling algorithm, transfer points one-to-one from the data |
|
21206 | 21384 | // container into the output |
|
21207 | 21385 | { |
|
21208 | QCPGraphDataContainer::const_iterator it = begin; | |
|
21209 | lineData->reserve(dataCount + 2); // +2 for possible fill end points | |
|
21210 | while (it != end) { | |
|
21211 | lineData->append(*it); | |
|
21212 | ++it; | |
|
21213 | } | |
|
21386 | lineData->resize(dataCount); | |
|
21387 | std::copy(begin, end, lineData->begin()); | |
|
21214 | 21388 | } |
|
21215 | 21389 | } |
|
21216 | 21390 | |
@@ -21479,151 +21653,177 void QCPGraph::getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin | |||
|
21479 | 21653 | } |
|
21480 | 21654 | } |
|
21481 | 21655 | |
|
21482 | /*! \internal | |
|
21656 | /*! \internal | |
|
21483 | 21657 | |
|
21484 | The line vector generated by e.g. \ref getLines describes only the line that connects the data | |
|
21485 | points. If the graph needs to be filled, two additional points need to be added at the | |
|
21486 | value-zero-line in the lower and upper key positions of the graph. This function calculates these | |
|
21487 | points and adds them to the end of \a lineData. Since the fill is typically drawn before the line | |
|
21488 | stroke, these added points need to be removed again after the fill is done, with the | |
|
21489 | removeFillBasePoints function. | |
|
21658 | This method goes through the passed points in \a lineData and returns a list of the segments | |
|
21659 | which don't contain NaN data points. | |
|
21490 | 21660 | |
|
21491 | The expanding of \a lines by two points will not cause unnecessary memory reallocations, because | |
|
21492 | the data vector generation functions (e.g. \ref getLines) reserve two extra points when they | |
|
21493 | allocate memory for \a lines. | |
|
21661 | \a keyOrientation defines whether the \a x or \a y member of the passed QPointF is used to check | |
|
21662 | for NaN. If \a keyOrientation is \c Qt::Horizontal, the \a y member is checked, if it is \c | |
|
21663 | Qt::Vertical, the \a x member is checked. | |
|
21494 | 21664 | |
|
21495 | \see removeFillBasePoints, lowerFillBasePoint, upperFillBasePoint | |
|
21665 | \see getOverlappingSegments, drawFill | |
|
21496 | 21666 | */ |
|
21497 | void QCPGraph::addFillBasePoints(QVector<QPointF> *lines) const | |
|
21667 | QVector<QCPDataRange> QCPGraph::getNonNanSegments(const QVector<QPointF> *lineData, | |
|
21668 | Qt::Orientation keyOrientation) const | |
|
21498 | 21669 | { |
|
21499 | if (!mKeyAxis) { | |
|
21500 | qDebug() << Q_FUNC_INFO << "invalid key axis"; | |
|
21501 | return; | |
|
21502 | } | |
|
21503 | if (!lines) { | |
|
21504 | qDebug() << Q_FUNC_INFO << "passed null as lineData"; | |
|
21505 | return; | |
|
21506 | } | |
|
21507 | if (lines->isEmpty()) | |
|
21508 | return; | |
|
21670 | QVector<QCPDataRange> result; | |
|
21671 | const int n = lineData->size(); | |
|
21672 | ||
|
21673 | QCPDataRange currentSegment(-1, -1); | |
|
21674 | int i = 0; | |
|
21509 | 21675 | |
|
21510 | // append points that close the polygon fill at the key axis: | |
|
21511 | if (mKeyAxis.data()->orientation() == Qt::Vertical) { | |
|
21512 | *lines << upperFillBasePoint(lines->last().y()); | |
|
21513 | *lines << lowerFillBasePoint(lines->first().y()); | |
|
21676 | if (keyOrientation == Qt::Horizontal) { | |
|
21677 | while (i < n) { | |
|
21678 | while (i < n && qIsNaN(lineData->at(i).y())) // seek next non-NaN data point | |
|
21679 | ++i; | |
|
21680 | if (i == n) | |
|
21681 | break; | |
|
21682 | currentSegment.setBegin(i++); | |
|
21683 | while (i < n && !qIsNaN(lineData->at(i).y())) // seek next NaN data point or end of data | |
|
21684 | ++i; | |
|
21685 | currentSegment.setEnd(i++); | |
|
21686 | result.append(currentSegment); | |
|
21687 | } | |
|
21514 | 21688 | } |
|
21515 | else { | |
|
21516 | *lines << upperFillBasePoint(lines->last().x()); | |
|
21517 | *lines << lowerFillBasePoint(lines->first().x()); | |
|
21689 | else // keyOrientation == Qt::Vertical | |
|
21690 | { | |
|
21691 | while (i < n) { | |
|
21692 | while (i < n && qIsNaN(lineData->at(i).x())) // seek next non-NaN data point | |
|
21693 | ++i; | |
|
21694 | if (i == n) | |
|
21695 | break; | |
|
21696 | currentSegment.setBegin(i++); | |
|
21697 | while (i < n && !qIsNaN(lineData->at(i).x())) // seek next NaN data point or end of data | |
|
21698 | ++i; | |
|
21699 | currentSegment.setEnd(i++); | |
|
21700 | result.append(currentSegment); | |
|
21701 | } | |
|
21518 | 21702 | } |
|
21703 | return result; | |
|
21519 | 21704 | } |
|
21520 | 21705 | |
|
21521 | /*! \internal | |
|
21706 | /*! \internal | |
|
21707 | ||
|
21708 | This method takes two segment lists (e.g. created by \ref getNonNanSegments) \a thisSegments and | |
|
21709 | \a otherSegments, and their associated point data \a thisData and \a otherData. | |
|
21710 | ||
|
21711 | It returns all pairs of segments (the first from \a thisSegments, the second from \a | |
|
21712 | otherSegments), which overlap in plot coordinates. | |
|
21713 | ||
|
21714 | This method is useful in the case of a channel fill between two graphs, when only those non-NaN | |
|
21715 | segments which actually overlap in their key coordinate shall be considered for drawing a channel | |
|
21716 | fill polygon. | |
|
21522 | 21717 | |
|
21523 | removes the two points from \a lines that were added by \ref addFillBasePoints. | |
|
21718 | It is assumed that the passed segments in \a thisSegments are ordered ascending by index, and | |
|
21719 | that the segments don't overlap themselves. The same is assumed for the segments in \a | |
|
21720 | otherSegments. This is fulfilled when the segments are obtained via \ref getNonNanSegments. | |
|
21524 | 21721 | |
|
21525 | \see addFillBasePoints, lowerFillBasePoint, upperFillBasePoint | |
|
21722 | \see getNonNanSegments, segmentsIntersect, drawFill, getChannelFillPolygon | |
|
21526 | 21723 | */ |
|
21527 | void QCPGraph::removeFillBasePoints(QVector<QPointF> *lines) const | |
|
21724 | QVector<QPair<QCPDataRange, QCPDataRange> > QCPGraph::getOverlappingSegments( | |
|
21725 | QVector<QCPDataRange> thisSegments, const QVector<QPointF> *thisData, | |
|
21726 | QVector<QCPDataRange> otherSegments, const QVector<QPointF> *otherData) const | |
|
21528 | 21727 | { |
|
21529 | if (!lines) { | |
|
21530 | qDebug() << Q_FUNC_INFO << "passed null as lineData"; | |
|
21531 | return; | |
|
21728 | QVector<QPair<QCPDataRange, QCPDataRange> > result; | |
|
21729 | if (thisData->isEmpty() || otherData->isEmpty() || thisSegments.isEmpty() | |
|
21730 | || otherSegments.isEmpty()) | |
|
21731 | return result; | |
|
21732 | ||
|
21733 | int thisIndex = 0; | |
|
21734 | int otherIndex = 0; | |
|
21735 | const bool verticalKey = mKeyAxis->orientation() == Qt::Vertical; | |
|
21736 | while (thisIndex < thisSegments.size() && otherIndex < otherSegments.size()) { | |
|
21737 | if (thisSegments.at(thisIndex).size() | |
|
21738 | < 2) // segments with fewer than two points won't have a fill anyhow | |
|
21739 | { | |
|
21740 | ++thisIndex; | |
|
21741 | continue; | |
|
21742 | } | |
|
21743 | if (otherSegments.at(otherIndex).size() | |
|
21744 | < 2) // segments with fewer than two points won't have a fill anyhow | |
|
21745 | { | |
|
21746 | ++otherIndex; | |
|
21747 | continue; | |
|
21748 | } | |
|
21749 | double thisLower, thisUpper, otherLower, otherUpper; | |
|
21750 | if (!verticalKey) { | |
|
21751 | thisLower = thisData->at(thisSegments.at(thisIndex).begin()).x(); | |
|
21752 | thisUpper = thisData->at(thisSegments.at(thisIndex).end() - 1).x(); | |
|
21753 | otherLower = otherData->at(otherSegments.at(otherIndex).begin()).x(); | |
|
21754 | otherUpper = otherData->at(otherSegments.at(otherIndex).end() - 1).x(); | |
|
21755 | } | |
|
21756 | else { | |
|
21757 | thisLower = thisData->at(thisSegments.at(thisIndex).begin()).y(); | |
|
21758 | thisUpper = thisData->at(thisSegments.at(thisIndex).end() - 1).y(); | |
|
21759 | otherLower = otherData->at(otherSegments.at(otherIndex).begin()).y(); | |
|
21760 | otherUpper = otherData->at(otherSegments.at(otherIndex).end() - 1).y(); | |
|
21761 | } | |
|
21762 | ||
|
21763 | int bPrecedence; | |
|
21764 | if (segmentsIntersect(thisLower, thisUpper, otherLower, otherUpper, bPrecedence)) | |
|
21765 | result.append(QPair<QCPDataRange, QCPDataRange>(thisSegments.at(thisIndex), | |
|
21766 | otherSegments.at(otherIndex))); | |
|
21767 | ||
|
21768 | if (bPrecedence <= 0) // otherSegment doesn't reach as far as thisSegment, so continue with | |
|
21769 | // next otherSegment, keeping current thisSegment | |
|
21770 | ++otherIndex; | |
|
21771 | else // otherSegment reaches further than thisSegment, so continue with next thisSegment, | |
|
21772 | // keeping current otherSegment | |
|
21773 | ++thisIndex; | |
|
21532 | 21774 | } |
|
21533 | if (lines->isEmpty()) | |
|
21534 | return; | |
|
21535 | 21775 | |
|
21536 | lines->remove(lines->size() - 2, 2); | |
|
21776 | return result; | |
|
21537 | 21777 | } |
|
21538 | 21778 | |
|
21539 | /*! \internal | |
|
21779 | /*! \internal | |
|
21780 | ||
|
21781 | Returns whether the segments defined by the coordinates (aLower, aUpper) and (bLower, bUpper) | |
|
21782 | have overlap. | |
|
21540 | 21783 | |
|
21541 | called by \ref addFillBasePoints to conveniently assign the point which closes the fill polygon | |
|
21542 | on the lower side of the zero-value-line parallel to the key axis. The logarithmic axis scale | |
|
21543 | case is a bit special, since the zero-value-line in pixel coordinates is in positive or negative | |
|
21544 | infinity. So this case is handled separately by just closing the fill polygon on the axis which | |
|
21545 | lies in the direction towards the zero value. | |
|
21784 | The output parameter \a bPrecedence indicates whether the \a b segment reaches farther than the | |
|
21785 | \a a segment or not. If \a bPrecedence returns 1, segment \a b reaches the farthest to higher | |
|
21786 | coordinates (i.e. bUpper > aUpper). If it returns -1, segment \a a reaches the farthest. Only if | |
|
21787 | both segment's upper bounds are identical, 0 is returned as \a bPrecedence. | |
|
21546 | 21788 | |
|
21547 | \a lowerKey will be the the key (in pixels) of the returned point. Depending on whether the key | |
|
21548 | axis is horizontal or vertical, \a lowerKey will end up as the x or y value of the returned | |
|
21549 | point, respectively. | |
|
21789 | It is assumed that the lower bounds always have smaller or equal values than the upper bounds. | |
|
21550 | 21790 | |
|
21551 | \see upperFillBasePoint, addFillBasePoints | |
|
21791 | \see getOverlappingSegments | |
|
21552 | 21792 | */ |
|
21553 | QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const | |
|
21793 | bool QCPGraph::segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, | |
|
21794 | int &bPrecedence) const | |
|
21554 | 21795 | { |
|
21555 | QCPAxis *keyAxis = mKeyAxis.data(); | |
|
21556 | QCPAxis *valueAxis = mValueAxis.data(); | |
|
21557 | if (!keyAxis || !valueAxis) { | |
|
21558 | qDebug() << Q_FUNC_INFO << "invalid key or value axis"; | |
|
21559 | return QPointF(); | |
|
21796 | bPrecedence = 0; | |
|
21797 | if (aLower > bUpper) { | |
|
21798 | bPrecedence = -1; | |
|
21799 | return false; | |
|
21560 | 21800 | } |
|
21561 | ||
|
21562 | QPointF point; | |
|
21563 | if (valueAxis->scaleType() == QCPAxis::stLinear) { | |
|
21564 | if (keyAxis->axisType() == QCPAxis::atLeft) { | |
|
21565 | point.setX(valueAxis->coordToPixel(0)); | |
|
21566 | point.setY(lowerKey); | |
|
21567 | } | |
|
21568 | else if (keyAxis->axisType() == QCPAxis::atRight) { | |
|
21569 | point.setX(valueAxis->coordToPixel(0)); | |
|
21570 | point.setY(lowerKey); | |
|
21571 | } | |
|
21572 | else if (keyAxis->axisType() == QCPAxis::atTop) { | |
|
21573 | point.setX(lowerKey); | |
|
21574 | point.setY(valueAxis->coordToPixel(0)); | |
|
21575 | } | |
|
21576 | else if (keyAxis->axisType() == QCPAxis::atBottom) { | |
|
21577 | point.setX(lowerKey); | |
|
21578 | point.setY(valueAxis->coordToPixel(0)); | |
|
21579 | } | |
|
21801 | else if (bLower > aUpper) { | |
|
21802 | bPrecedence = 1; | |
|
21803 | return false; | |
|
21580 | 21804 | } |
|
21581 | else // valueAxis->mScaleType == QCPAxis::stLogarithmic | |
|
21582 | { | |
|
21583 | // In logarithmic scaling we can't just draw to value zero so we just fill all the way | |
|
21584 | // to the axis which is in the direction towards zero | |
|
21585 | if (keyAxis->orientation() == Qt::Vertical) { | |
|
21586 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) | |
|
21587 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is | |
|
21588 | // negative, zero | |
|
21589 | // is on opposite | |
|
21590 | // side of key axis | |
|
21591 | point.setX(keyAxis->axisRect()->right()); | |
|
21592 | else | |
|
21593 | point.setX(keyAxis->axisRect()->left()); | |
|
21594 | point.setY(lowerKey); | |
|
21595 | } | |
|
21596 | else if (keyAxis->axisType() == QCPAxis::atTop | |
|
21597 | || keyAxis->axisType() == QCPAxis::atBottom) { | |
|
21598 | point.setX(lowerKey); | |
|
21599 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) | |
|
21600 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is | |
|
21601 | // negative, zero | |
|
21602 | // is on opposite | |
|
21603 | // side of key axis | |
|
21604 | point.setY(keyAxis->axisRect()->top()); | |
|
21605 | else | |
|
21606 | point.setY(keyAxis->axisRect()->bottom()); | |
|
21607 | } | |
|
21805 | else { | |
|
21806 | if (aUpper > bUpper) | |
|
21807 | bPrecedence = -1; | |
|
21808 | else if (aUpper < bUpper) | |
|
21809 | bPrecedence = 1; | |
|
21810 | ||
|
21811 | return true; | |
|
21608 | 21812 | } |
|
21609 | return point; | |
|
21610 | 21813 | } |
|
21611 | 21814 | |
|
21612 | 21815 | /*! \internal |
|
21613 | 21816 | |
|
21614 | called by \ref addFillBasePoints to conveniently assign the point which closes the fill | |
|
21615 | polygon on the upper side of the zero-value-line parallel to the key axis. The logarithmic axis | |
|
21616 | scale case is a bit special, since the zero-value-line in pixel coordinates is in positive or | |
|
21617 | negative infinity. So this case is handled separately by just closing the fill polygon on the | |
|
21618 | axis which lies in the direction towards the zero value. | |
|
21817 | Returns the point which closes the fill polygon on the zero-value-line parallel to the key axis. | |
|
21818 | The logarithmic axis scale case is a bit special, since the zero-value-line in pixel coordinates | |
|
21819 | is in positive or negative infinity. So this case is handled separately by just closing the fill | |
|
21820 | polygon on the axis which lies in the direction towards the zero value. | |
|
21619 | 21821 | |
|
21620 |
\a |
|
|
21621 | axis is horizontal or vertical, \a upperKey will end up as the x or y value of the returned | |
|
21622 | point, respectively. | |
|
21623 | ||
|
21624 | \see lowerFillBasePoint, addFillBasePoints | |
|
21822 | \a matchingDataPoint will provide the key (in pixels) of the returned point. Depending on whether | |
|
21823 | the key axis of this graph is horizontal or vertical, \a matchingDataPoint will provide the x or | |
|
21824 | y value of the returned point, respectively. | |
|
21625 | 21825 | */ |
|
21626 |
QPointF QCPGraph:: |
|
|
21826 | QPointF QCPGraph::getFillBasePoint(QPointF matchingDataPoint) const | |
|
21627 | 21827 | { |
|
21628 | 21828 | QCPAxis *keyAxis = mKeyAxis.data(); |
|
21629 | 21829 | QCPAxis *valueAxis = mValueAxis.data(); |
@@ -21632,23 +21832,16 QPointF QCPGraph::upperFillBasePoint(double upperKey) const | |||
|
21632 | 21832 | return QPointF(); |
|
21633 | 21833 | } |
|
21634 | 21834 | |
|
21635 |
QPointF |
|
|
21835 | QPointF result; | |
|
21636 | 21836 | if (valueAxis->scaleType() == QCPAxis::stLinear) { |
|
21637 |
if (keyAxis-> |
|
|
21638 | point.setX(valueAxis->coordToPixel(0)); | |
|
21639 | point.setY(upperKey); | |
|
21837 | if (keyAxis->orientation() == Qt::Horizontal) { | |
|
21838 | result.setX(matchingDataPoint.x()); | |
|
21839 | result.setY(valueAxis->coordToPixel(0)); | |
|
21640 | 21840 | } |
|
21641 |
else |
|
|
21642 | point.setX(valueAxis->coordToPixel(0)); | |
|
21643 | point.setY(upperKey); | |
|
21644 | } | |
|
21645 | else if (keyAxis->axisType() == QCPAxis::atTop) { | |
|
21646 | point.setX(upperKey); | |
|
21647 | point.setY(valueAxis->coordToPixel(0)); | |
|
21648 | } | |
|
21649 | else if (keyAxis->axisType() == QCPAxis::atBottom) { | |
|
21650 | point.setX(upperKey); | |
|
21651 | point.setY(valueAxis->coordToPixel(0)); | |
|
21841 | else // keyAxis->orientation() == Qt::Vertical | |
|
21842 | { | |
|
21843 | result.setX(valueAxis->coordToPixel(0)); | |
|
21844 | result.setY(matchingDataPoint.y()); | |
|
21652 | 21845 | } |
|
21653 | 21846 | } |
|
21654 | 21847 | else // valueAxis->mScaleType == QCPAxis::stLogarithmic |
@@ -21661,40 +21854,80 QPointF QCPGraph::upperFillBasePoint(double upperKey) const | |||
|
21661 | 21854 | // negative, zero |
|
21662 | 21855 | // is on opposite |
|
21663 | 21856 | // side of key axis |
|
21664 |
|
|
|
21857 | result.setX(keyAxis->axisRect()->right()); | |
|
21665 | 21858 | else |
|
21666 |
|
|
|
21667 | point.setY(upperKey); | |
|
21859 | result.setX(keyAxis->axisRect()->left()); | |
|
21860 | result.setY(matchingDataPoint.y()); | |
|
21668 | 21861 | } |
|
21669 | 21862 | else if (keyAxis->axisType() == QCPAxis::atTop |
|
21670 | 21863 | || keyAxis->axisType() == QCPAxis::atBottom) { |
|
21671 | point.setX(upperKey); | |
|
21864 | result.setX(matchingDataPoint.x()); | |
|
21672 | 21865 | if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) |
|
21673 | 21866 | || (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is |
|
21674 | 21867 | // negative, zero |
|
21675 | 21868 | // is on opposite |
|
21676 | 21869 | // side of key axis |
|
21677 |
|
|
|
21870 | result.setY(keyAxis->axisRect()->top()); | |
|
21678 | 21871 | else |
|
21679 |
|
|
|
21872 | result.setY(keyAxis->axisRect()->bottom()); | |
|
21680 | 21873 | } |
|
21681 | 21874 | } |
|
21682 |
return |
|
|
21875 | return result; | |
|
21683 | 21876 | } |
|
21684 | 21877 | |
|
21685 | 21878 | /*! \internal |
|
21686 | 21879 | |
|
21687 |
|
|
|
21688 | in \a mChannelFillGraph (see \ref setChannelFillGraph). The data points representing the line of | |
|
21689 | this graph in pixel coordinates must be passed in \a lines, the corresponding points of the other | |
|
21690 | graph are generated by calling its \ref getLines method. | |
|
21880 | Returns the polygon needed for drawing normal fills between this graph and the key axis. | |
|
21691 | 21881 | |
|
21692 | This method may return an empty polygon if the key ranges of the two graphs have no overlap of if | |
|
21693 | they don't have the same orientation (e.g. one key axis vertical, the other horizontal). For | |
|
21694 | increased performance (due to implicit sharing), it is recommended to keep the returned QPolygonF | |
|
21695 | const. | |
|
21882 | Pass the graph's data points (in pixel coordinates) as \a lineData, and specify the \a segment | |
|
21883 | which shall be used for the fill. The collection of \a lineData points described by \a segment | |
|
21884 | must not contain NaN data points (see \ref getNonNanSegments). | |
|
21885 | ||
|
21886 | The returned fill polygon will be closed at the key axis (the zero-value line) for linear value | |
|
21887 | axes. For logarithmic value axes the polygon will reach just beyond the corresponding axis rect | |
|
21888 | side (see \ref getFillBasePoint). | |
|
21889 | ||
|
21890 | For increased performance (due to implicit sharing), keep the returned QPolygonF const. | |
|
21891 | ||
|
21892 | \see drawFill, getNonNanSegments | |
|
21893 | */ | |
|
21894 | const QPolygonF QCPGraph::getFillPolygon(const QVector<QPointF> *lineData, | |
|
21895 | QCPDataRange segment) const | |
|
21896 | { | |
|
21897 | if (segment.size() < 2) | |
|
21898 | return QPolygonF(); | |
|
21899 | QPolygonF result(segment.size() + 2); | |
|
21900 | ||
|
21901 | result[0] = getFillBasePoint(lineData->at(segment.begin())); | |
|
21902 | std::copy(lineData->constBegin() + segment.begin(), lineData->constBegin() + segment.end(), | |
|
21903 | result.begin() + 1); | |
|
21904 | result[result.size() - 1] = getFillBasePoint(lineData->at(segment.end() - 1)); | |
|
21905 | ||
|
21906 | return result; | |
|
21907 | } | |
|
21908 | ||
|
21909 | /*! \internal | |
|
21910 | ||
|
21911 | Returns the polygon needed for drawing (partial) channel fills between this graph and the graph | |
|
21912 | specified by \ref setChannelFillGraph. | |
|
21913 | ||
|
21914 | The data points of this graph are passed as pixel coordinates via \a thisData, the data of the | |
|
21915 | other graph as \a otherData. The returned polygon will be calculated for the specified data | |
|
21916 | segments \a thisSegment and \a otherSegment, pertaining to the respective \a thisData and \a | |
|
21917 | otherData, respectively. | |
|
21918 | ||
|
21919 | The passed \a thisSegment and \a otherSegment should correspond to the segment pairs returned by | |
|
21920 | \ref getOverlappingSegments, to make sure only segments that actually have key coordinate overlap | |
|
21921 | need to be processed here. | |
|
21922 | ||
|
21923 | For increased performance due to implicit sharing, keep the returned QPolygonF const. | |
|
21924 | ||
|
21925 | \see drawFill, getOverlappingSegments, getNonNanSegments | |
|
21696 | 21926 | */ |
|
21697 |
const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> * |
|
|
21927 | const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *thisData, | |
|
21928 | QCPDataRange thisSegment, | |
|
21929 | const QVector<QPointF> *otherData, | |
|
21930 | QCPDataRange otherSegment) const | |
|
21698 | 21931 | { |
|
21699 | 21932 | if (!mChannelFillGraph) |
|
21700 | 21933 | return QPolygonF(); |
@@ -21715,55 +21948,35 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) c | |||
|
21715 | 21948 | // fits, valueAxis will fit too, because it's always orthogonal to |
|
21716 | 21949 | // keyAxis) |
|
21717 | 21950 | |
|
21718 |
if ( |
|
|
21951 | if (thisData->isEmpty()) | |
|
21719 | 21952 | return QPolygonF(); |
|
21720 |
QVector<QPointF> |
|
|
21721 | mChannelFillGraph.data()->getLines(&otherData, | |
|
21722 | QCPDataRange(0, mChannelFillGraph.data()->dataCount())); | |
|
21723 | if (otherData.isEmpty()) | |
|
21724 | return QPolygonF(); | |
|
21725 | QVector<QPointF> thisData; | |
|
21726 | thisData.reserve( | |
|
21727 | lines->size() | |
|
21728 | + otherData.size()); // because we will join both vectors at end of this function | |
|
21729 | for (int i = 0; i < lines->size(); ++i) // don't use the vector<<(vector), it squeezes | |
|
21730 | // internally, which ruins the performance tuning with | |
|
21731 | // reserve() | |
|
21732 | thisData << lines->at(i); | |
|
21733 | ||
|
21953 | QVector<QPointF> thisSegmentData(thisSegment.size()); | |
|
21954 | QVector<QPointF> otherSegmentData(otherSegment.size()); | |
|
21955 | std::copy(thisData->constBegin() + thisSegment.begin(), | |
|
21956 | thisData->constBegin() + thisSegment.end(), thisSegmentData.begin()); | |
|
21957 | std::copy(otherData->constBegin() + otherSegment.begin(), | |
|
21958 | otherData->constBegin() + otherSegment.end(), otherSegmentData.begin()); | |
|
21734 | 21959 | // pointers to be able to swap them, depending which data range needs cropping: |
|
21735 | QVector<QPointF> *staticData = &thisData; | |
|
21736 | QVector<QPointF> *croppedData = &otherData; | |
|
21960 | QVector<QPointF> *staticData = &thisSegmentData; | |
|
21961 | QVector<QPointF> *croppedData = &otherSegmentData; | |
|
21737 | 21962 | |
|
21738 | 21963 | // crop both vectors to ranges in which the keys overlap (which coord is key, depends on |
|
21739 | 21964 | // axisType): |
|
21740 | 21965 | if (keyAxis->orientation() == Qt::Horizontal) { |
|
21741 | 21966 | // x is key |
|
21742 | // if an axis range is reversed, the data point keys will be descending. Reverse them, since | |
|
21743 | // following algorithm assumes ascending keys: | |
|
21744 | if (staticData->first().x() > staticData->last().x()) { | |
|
21745 | int size = staticData->size(); | |
|
21746 | for (int i = 0; i < size / 2; ++i) | |
|
21747 | qSwap((*staticData)[i], (*staticData)[size - 1 - i]); | |
|
21748 | } | |
|
21749 | if (croppedData->first().x() > croppedData->last().x()) { | |
|
21750 | int size = croppedData->size(); | |
|
21751 | for (int i = 0; i < size / 2; ++i) | |
|
21752 | qSwap((*croppedData)[i], (*croppedData)[size - 1 - i]); | |
|
21753 | } | |
|
21754 | 21967 | // crop lower bound: |
|
21755 | 21968 | if (staticData->first().x() < croppedData->first().x()) // other one must be cropped |
|
21756 | 21969 | qSwap(staticData, croppedData); |
|
21757 | int lowBound = findIndexBelowX(croppedData, staticData->first().x()); | |
|
21970 | const int lowBound = findIndexBelowX(croppedData, staticData->first().x()); | |
|
21758 | 21971 | if (lowBound == -1) |
|
21759 | 21972 | return QPolygonF(); // key ranges have no overlap |
|
21760 | 21973 | croppedData->remove(0, lowBound); |
|
21761 | // set lowest point of cropped data to fit exactly key position of first static data | |
|
21762 |
// |
|
|
21974 | // set lowest point of cropped data to fit exactly key position of first static data point | |
|
21975 | // via linear interpolation: | |
|
21763 | 21976 | if (croppedData->size() < 2) |
|
21764 | 21977 | return QPolygonF(); // need at least two points for interpolation |
|
21765 | 21978 | double slope; |
|
21766 |
if (croppedData->at(1).x() |
|
|
21979 | if (!qFuzzyCompare(croppedData->at(1).x(), croppedData->at(0).x())) | |
|
21767 | 21980 | slope = (croppedData->at(1).y() - croppedData->at(0).y()) |
|
21768 | 21981 | / (croppedData->at(1).x() - croppedData->at(0).x()); |
|
21769 | 21982 | else |
@@ -21779,12 +21992,12 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) c | |||
|
21779 | 21992 | if (highBound == -1) |
|
21780 | 21993 | return QPolygonF(); // key ranges have no overlap |
|
21781 | 21994 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); |
|
21782 | // set highest point of cropped data to fit exactly key position of last static data | |
|
21783 |
// |
|
|
21995 | // set highest point of cropped data to fit exactly key position of last static data point | |
|
21996 | // via linear interpolation: | |
|
21784 | 21997 | if (croppedData->size() < 2) |
|
21785 | return QPolygonF(); // need at least two points for interpolation | |
|
21786 | int li = croppedData->size() - 1; // last index | |
|
21787 |
if (croppedData->at(li).x() |
|
|
21998 | return QPolygonF(); // need at least two points for interpolation | |
|
21999 | const int li = croppedData->size() - 1; // last index | |
|
22000 | if (!qFuzzyCompare(croppedData->at(li).x(), croppedData->at(li - 1).x())) | |
|
21788 | 22001 | slope = (croppedData->at(li).y() - croppedData->at(li - 1).y()) |
|
21789 | 22002 | / (croppedData->at(li).x() - croppedData->at(li - 1).x()); |
|
21790 | 22003 | else |
@@ -21796,36 +22009,20 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) c | |||
|
21796 | 22009 | else // mKeyAxis->orientation() == Qt::Vertical |
|
21797 | 22010 | { |
|
21798 | 22011 | // y is key |
|
21799 | // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared | |
|
21800 | // to x, | |
|
21801 | // because in pixel coordinates, y increases from top to bottom, not bottom to top like data | |
|
21802 | // coordinate. | |
|
21803 | // if an axis range is reversed, the data point keys will be descending. Reverse them, since | |
|
21804 | // following algorithm assumes ascending keys: | |
|
21805 | if (staticData->first().y() < staticData->last().y()) { | |
|
21806 | int size = staticData->size(); | |
|
21807 | for (int i = 0; i < size / 2; ++i) | |
|
21808 | qSwap((*staticData)[i], (*staticData)[size - 1 - i]); | |
|
21809 | } | |
|
21810 | if (croppedData->first().y() < croppedData->last().y()) { | |
|
21811 | int size = croppedData->size(); | |
|
21812 | for (int i = 0; i < size / 2; ++i) | |
|
21813 | qSwap((*croppedData)[i], (*croppedData)[size - 1 - i]); | |
|
21814 | } | |
|
21815 | 22012 | // crop lower bound: |
|
21816 |
if (staticData->first().y() |
|
|
22013 | if (staticData->first().y() < croppedData->first().y()) // other one must be cropped | |
|
21817 | 22014 | qSwap(staticData, croppedData); |
|
21818 |
int lowBound = findIndex |
|
|
22015 | int lowBound = findIndexBelowY(croppedData, staticData->first().y()); | |
|
21819 | 22016 | if (lowBound == -1) |
|
21820 | 22017 | return QPolygonF(); // key ranges have no overlap |
|
21821 | 22018 | croppedData->remove(0, lowBound); |
|
21822 | // set lowest point of cropped data to fit exactly key position of first static data | |
|
21823 |
// |
|
|
22019 | // set lowest point of cropped data to fit exactly key position of first static data point | |
|
22020 | // via linear interpolation: | |
|
21824 | 22021 | if (croppedData->size() < 2) |
|
21825 | 22022 | return QPolygonF(); // need at least two points for interpolation |
|
21826 | 22023 | double slope; |
|
21827 |
if (croppedData->at(1).y() |
|
|
21828 |
|
|
|
22024 | if (!qFuzzyCompare(croppedData->at(1).y(), | |
|
22025 | croppedData->at(0).y())) // avoid division by zero in step plots | |
|
21829 | 22026 | slope = (croppedData->at(1).x() - croppedData->at(0).x()) |
|
21830 | 22027 | / (croppedData->at(1).y() - croppedData->at(0).y()); |
|
21831 | 22028 | else |
@@ -21835,19 +22032,19 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) c | |||
|
21835 | 22032 | (*croppedData)[0].setY(staticData->first().y()); |
|
21836 | 22033 | |
|
21837 | 22034 | // crop upper bound: |
|
21838 |
if (staticData->last().y() |
|
|
22035 | if (staticData->last().y() > croppedData->last().y()) // other one must be cropped | |
|
21839 | 22036 | qSwap(staticData, croppedData); |
|
21840 |
int highBound = findIndex |
|
|
22037 | int highBound = findIndexAboveY(croppedData, staticData->last().y()); | |
|
21841 | 22038 | if (highBound == -1) |
|
21842 | 22039 | return QPolygonF(); // key ranges have no overlap |
|
21843 | 22040 | croppedData->remove(highBound + 1, croppedData->size() - (highBound + 1)); |
|
21844 | // set highest point of cropped data to fit exactly key position of last static data | |
|
21845 |
// |
|
|
22041 | // set highest point of cropped data to fit exactly key position of last static data point | |
|
22042 | // via linear interpolation: | |
|
21846 | 22043 | if (croppedData->size() < 2) |
|
21847 | 22044 | return QPolygonF(); // need at least two points for interpolation |
|
21848 | 22045 | int li = croppedData->size() - 1; // last index |
|
21849 |
if (croppedData->at(li).y() |
|
|
21850 |
|
|
|
22046 | if (!qFuzzyCompare(croppedData->at(li).y(), | |
|
22047 | croppedData->at(li - 1).y())) // avoid division by zero in step plots | |
|
21851 | 22048 | slope = (croppedData->at(li).x() - croppedData->at(li - 1).x()) |
|
21852 | 22049 | / (croppedData->at(li).y() - croppedData->at(li - 1).y()); |
|
21853 | 22050 | else |
@@ -21858,16 +22055,17 const QPolygonF QCPGraph::getChannelFillPolygon(const QVector<QPointF> *lines) c | |||
|
21858 | 22055 | } |
|
21859 | 22056 | |
|
21860 | 22057 | // return joined: |
|
21861 | for (int i = otherData.size() - 1; i >= 0; | |
|
22058 | for (int i = otherSegmentData.size() - 1; i >= 0; | |
|
21862 | 22059 | --i) // insert reversed, otherwise the polygon will be twisted |
|
21863 | thisData << otherData.at(i); | |
|
21864 | return QPolygonF(thisData); | |
|
22060 | thisSegmentData << otherSegmentData.at(i); | |
|
22061 | return QPolygonF(thisSegmentData); | |
|
21865 | 22062 | } |
|
21866 | 22063 | |
|
21867 | 22064 | /*! \internal |
|
21868 | 22065 | |
|
21869 | 22066 | Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in |
|
21870 | \a data points are ordered ascending, as is the case when plotting with horizontal key axis. | |
|
22067 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key | |
|
22068 | axis is horizontal. | |
|
21871 | 22069 | |
|
21872 | 22070 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21873 | 22071 | */ |
@@ -21887,7 +22085,8 int QCPGraph::findIndexAboveX(const QVector<QPointF> *data, double x) const | |||
|
21887 | 22085 | /*! \internal |
|
21888 | 22086 | |
|
21889 | 22087 | Finds the highest index of \a data, whose points x value is just below \a x. Assumes x values in |
|
21890 | \a data points are ordered ascending, as is the case when plotting with horizontal key axis. | |
|
22088 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key | |
|
22089 | axis is horizontal. | |
|
21891 | 22090 | |
|
21892 | 22091 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21893 | 22092 | */ |
@@ -21907,18 +22106,19 int QCPGraph::findIndexBelowX(const QVector<QPointF> *data, double x) const | |||
|
21907 | 22106 | /*! \internal |
|
21908 | 22107 | |
|
21909 | 22108 | Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in |
|
21910 | \a data points are ordered descending, as is the case when plotting with vertical key axis. | |
|
22109 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key | |
|
22110 | axis is vertical. | |
|
21911 | 22111 | |
|
21912 | 22112 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
21913 | 22113 | */ |
|
21914 | 22114 | int QCPGraph::findIndexAboveY(const QVector<QPointF> *data, double y) const |
|
21915 | 22115 | { |
|
21916 |
for (int i = |
|
|
22116 | for (int i = data->size() - 1; i >= 0; --i) { | |
|
21917 | 22117 | if (data->at(i).y() < y) { |
|
21918 |
if (i > |
|
|
21919 |
return i |
|
|
22118 | if (i < data->size() - 1) | |
|
22119 | return i + 1; | |
|
21920 | 22120 | else |
|
21921 |
return |
|
|
22121 | return data->size() - 1; | |
|
21922 | 22122 | } |
|
21923 | 22123 | } |
|
21924 | 22124 | return -1; |
@@ -21994,19 +22194,19 double QCPGraph::pointDistance(const QPointF &pixelPoint, | |||
|
21994 | 22194 | /*! \internal |
|
21995 | 22195 | |
|
21996 | 22196 | Finds the highest index of \a data, whose points y value is just below \a y. Assumes y values in |
|
21997 | \a data points are ordered descending, as is the case when plotting with vertical key axis (since | |
|
21998 | keys are ordered ascending). | |
|
22197 | \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key | |
|
22198 | axis is vertical. | |
|
21999 | 22199 | |
|
22000 | 22200 | Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. |
|
22001 | 22201 | */ |
|
22002 | 22202 | int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const |
|
22003 | 22203 | { |
|
22004 |
for (int i = data->size() |
|
|
22204 | for (int i = 0; i < data->size(); ++i) { | |
|
22005 | 22205 | if (data->at(i).y() > y) { |
|
22006 |
if (i |
|
|
22007 |
return i |
|
|
22206 | if (i > 0) | |
|
22207 | return i - 1; | |
|
22008 | 22208 | else |
|
22009 |
return |
|
|
22209 | return 0; | |
|
22010 | 22210 | } |
|
22011 | 22211 | } |
|
22012 | 22212 | return -1; |
@@ -22014,8 +22214,8 int QCPGraph::findIndexBelowY(const QVector<QPointF> *data, double y) const | |||
|
22014 | 22214 | /* end of 'src/plottables/plottable-graph.cpp' */ |
|
22015 | 22215 | |
|
22016 | 22216 | |
|
22017 |
/* including file 'src/plottables/plottable-curve.cpp', size 6 |
|
|
22018 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
22217 | /* including file 'src/plottables/plottable-curve.cpp', size 63527 */ | |
|
22218 | /* commit 63bcca79007f7f56dce5dd035560f2e871d1dfc1 2017-07-20 18:02:21 +0200 */ | |
|
22019 | 22219 | |
|
22020 | 22220 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
22021 | 22221 | //////////////////// QCPCurveData |
@@ -22179,6 +22379,7 QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) | |||
|
22179 | 22379 | |
|
22180 | 22380 | setScatterStyle(QCPScatterStyle()); |
|
22181 | 22381 | setLineStyle(lsLine); |
|
22382 | setScatterSkip(0); | |
|
22182 | 22383 | } |
|
22183 | 22384 | |
|
22184 | 22385 | QCPCurve::~QCPCurve() |
@@ -22881,54 +23082,74 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double oth | |||
|
22881 | 23082 | double value, double keyMin, double valueMax, double keyMax, |
|
22882 | 23083 | double valueMin) const |
|
22883 | 23084 | { |
|
22884 | double intersectKey = keyMin; // initial value is just fail-safe | |
|
22885 | double intersectValue = valueMax; // initial value is just fail-safe | |
|
23085 | // The intersection point interpolation here is done in pixel coordinates, so we don't need to | |
|
23086 | // differentiate between different axis scale types. Note that the nomenclature | |
|
23087 | // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be | |
|
23088 | // different in pixel coordinates (horz/vert key axes, reversed ranges) | |
|
23089 | ||
|
23090 | const double keyMinPx = mKeyAxis->coordToPixel(keyMin); | |
|
23091 | const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); | |
|
23092 | const double valueMinPx = mValueAxis->coordToPixel(valueMin); | |
|
23093 | const double valueMaxPx = mValueAxis->coordToPixel(valueMax); | |
|
23094 | const double otherValuePx = mValueAxis->coordToPixel(otherValue); | |
|
23095 | const double valuePx = mValueAxis->coordToPixel(value); | |
|
23096 | const double otherKeyPx = mKeyAxis->coordToPixel(otherKey); | |
|
23097 | const double keyPx = mKeyAxis->coordToPixel(key); | |
|
23098 | double intersectKeyPx = keyMinPx; // initial key just a fail-safe | |
|
23099 | double intersectValuePx = valueMinPx; // initial value just a fail-safe | |
|
22886 | 23100 | switch (otherRegion) { |
|
22887 | 23101 | case 1: // top and left edge |
|
22888 | 23102 | { |
|
22889 | intersectValue = valueMax; | |
|
22890 | intersectKey | |
|
22891 | = otherKey | |
|
22892 |
|
|
|
22893 | if (intersectKey < keyMin | |
|
22894 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
|
23103 | intersectValuePx = valueMaxPx; | |
|
23104 | intersectKeyPx = otherKeyPx | |
|
23105 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23106 | * (intersectValuePx - otherValuePx); | |
|
23107 | if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) | |
|
23108 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not | |
|
23109 | // intersected, then it must be left | |
|
23110 | // edge (qMin/qMax necessary since | |
|
23111 | // axes may be reversed) | |
|
22895 | 23112 | { |
|
22896 | intersectKey = keyMin; | |
|
22897 | intersectValue | |
|
22898 | = otherValue | |
|
22899 |
|
|
|
23113 | intersectKeyPx = keyMinPx; | |
|
23114 | intersectValuePx = otherValuePx | |
|
23115 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) | |
|
23116 | * (intersectKeyPx - otherKeyPx); | |
|
22900 | 23117 | } |
|
22901 | 23118 | break; |
|
22902 | 23119 | } |
|
22903 | 23120 | case 2: // left edge |
|
22904 | 23121 | { |
|
22905 | intersectKey = keyMin; | |
|
22906 | intersectValue | |
|
22907 | = otherValue + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
|
23122 | intersectKeyPx = keyMinPx; | |
|
23123 | intersectValuePx | |
|
23124 | = otherValuePx | |
|
23125 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) * (intersectKeyPx - otherKeyPx); | |
|
22908 | 23126 | break; |
|
22909 | 23127 | } |
|
22910 | 23128 | case 3: // bottom and left edge |
|
22911 | 23129 | { |
|
22912 | intersectValue = valueMin; | |
|
22913 | intersectKey | |
|
22914 | = otherKey | |
|
22915 |
|
|
|
22916 | if (intersectKey < keyMin | |
|
22917 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
|
23130 | intersectValuePx = valueMinPx; | |
|
23131 | intersectKeyPx = otherKeyPx | |
|
23132 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23133 | * (intersectValuePx - otherValuePx); | |
|
23134 | if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) | |
|
23135 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not | |
|
23136 | // intersected, then it must be left | |
|
23137 | // edge (qMin/qMax necessary since | |
|
23138 | // axes may be reversed) | |
|
22918 | 23139 | { |
|
22919 | intersectKey = keyMin; | |
|
22920 | intersectValue | |
|
22921 | = otherValue | |
|
22922 |
|
|
|
23140 | intersectKeyPx = keyMinPx; | |
|
23141 | intersectValuePx = otherValuePx | |
|
23142 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) | |
|
23143 | * (intersectKeyPx - otherKeyPx); | |
|
22923 | 23144 | } |
|
22924 | 23145 | break; |
|
22925 | 23146 | } |
|
22926 | 23147 | case 4: // top edge |
|
22927 | 23148 | { |
|
22928 | intersectValue = valueMax; | |
|
22929 | intersectKey | |
|
22930 | = otherKey | |
|
22931 |
|
|
|
23149 | intersectValuePx = valueMaxPx; | |
|
23150 | intersectKeyPx = otherKeyPx | |
|
23151 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23152 | * (intersectValuePx - otherValuePx); | |
|
22932 | 23153 | break; |
|
22933 | 23154 | } |
|
22934 | 23155 | case 5: { |
@@ -22937,53 +23158,63 QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double oth | |||
|
22937 | 23158 | } |
|
22938 | 23159 | case 6: // bottom edge |
|
22939 | 23160 | { |
|
22940 | intersectValue = valueMin; | |
|
22941 | intersectKey | |
|
22942 | = otherKey | |
|
22943 |
|
|
|
23161 | intersectValuePx = valueMinPx; | |
|
23162 | intersectKeyPx = otherKeyPx | |
|
23163 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23164 | * (intersectValuePx - otherValuePx); | |
|
22944 | 23165 | break; |
|
22945 | 23166 | } |
|
22946 | 23167 | case 7: // top and right edge |
|
22947 | 23168 | { |
|
22948 | intersectValue = valueMax; | |
|
22949 | intersectKey | |
|
22950 | = otherKey | |
|
22951 |
|
|
|
22952 | if (intersectKey < keyMin | |
|
22953 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
|
23169 | intersectValuePx = valueMaxPx; | |
|
23170 | intersectKeyPx = otherKeyPx | |
|
23171 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23172 | * (intersectValuePx - otherValuePx); | |
|
23173 | if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) | |
|
23174 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not | |
|
23175 | // intersected, then it must be right | |
|
23176 | // edge (qMin/qMax necessary since | |
|
23177 | // axes may be reversed) | |
|
22954 | 23178 | { |
|
22955 | intersectKey = keyMax; | |
|
22956 | intersectValue | |
|
22957 | = otherValue | |
|
22958 |
|
|
|
23179 | intersectKeyPx = keyMaxPx; | |
|
23180 | intersectValuePx = otherValuePx | |
|
23181 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) | |
|
23182 | * (intersectKeyPx - otherKeyPx); | |
|
22959 | 23183 | } |
|
22960 | 23184 | break; |
|
22961 | 23185 | } |
|
22962 | 23186 | case 8: // right edge |
|
22963 | 23187 | { |
|
22964 | intersectKey = keyMax; | |
|
22965 | intersectValue | |
|
22966 | = otherValue + (value - otherValue) / (key - otherKey) * (intersectKey - otherKey); | |
|
23188 | intersectKeyPx = keyMaxPx; | |
|
23189 | intersectValuePx | |
|
23190 | = otherValuePx | |
|
23191 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) * (intersectKeyPx - otherKeyPx); | |
|
22967 | 23192 | break; |
|
22968 | 23193 | } |
|
22969 | 23194 | case 9: // bottom and right edge |
|
22970 | 23195 | { |
|
22971 | intersectValue = valueMin; | |
|
22972 | intersectKey | |
|
22973 | = otherKey | |
|
22974 |
|
|
|
22975 | if (intersectKey < keyMin | |
|
22976 | || intersectKey > keyMax) // doesn't intersect, so must intersect other: | |
|
23196 | intersectValuePx = valueMinPx; | |
|
23197 | intersectKeyPx = otherKeyPx | |
|
23198 | + (keyPx - otherKeyPx) / (valuePx - otherValuePx) | |
|
23199 | * (intersectValuePx - otherValuePx); | |
|
23200 | if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) | |
|
23201 | || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not | |
|
23202 | // intersected, then it must be right | |
|
23203 | // edge (qMin/qMax necessary since | |
|
23204 | // axes may be reversed) | |
|
22977 | 23205 | { |
|
22978 | intersectKey = keyMax; | |
|
22979 | intersectValue | |
|
22980 | = otherValue | |
|
22981 |
|
|
|
23206 | intersectKeyPx = keyMaxPx; | |
|
23207 | intersectValuePx = otherValuePx | |
|
23208 | + (valuePx - otherValuePx) / (keyPx - otherKeyPx) | |
|
23209 | * (intersectKeyPx - otherKeyPx); | |
|
22982 | 23210 | } |
|
22983 | 23211 | break; |
|
22984 | 23212 | } |
|
22985 | 23213 | } |
|
22986 | return coordsToPixels(intersectKey, intersectValue); | |
|
23214 | if (mKeyAxis->orientation() == Qt::Horizontal) | |
|
23215 | return QPointF(intersectKeyPx, intersectValuePx); | |
|
23216 | else | |
|
23217 | return QPointF(intersectValuePx, intersectKeyPx); | |
|
22987 | 23218 | } |
|
22988 | 23219 | |
|
22989 | 23220 | /*! \internal |
@@ -23496,44 +23727,79 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double | |||
|
23496 | 23727 | double keyMin, double valueMax, double keyMax, double valueMin, |
|
23497 | 23728 | QPointF &crossA, QPointF &crossB) const |
|
23498 | 23729 | { |
|
23499 | QList<QPointF> intersections; // x of QPointF corresponds to key and y to value | |
|
23730 | // The intersection point interpolation here is done in pixel coordinates, so we don't need to | |
|
23731 | // differentiate between different axis scale types. Note that the nomenclature | |
|
23732 | // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be | |
|
23733 | // different in pixel coordinates (horz/vert key axes, reversed ranges) | |
|
23734 | ||
|
23735 | QList<QPointF> intersections; | |
|
23736 | const double valueMinPx = mValueAxis->coordToPixel(valueMin); | |
|
23737 | const double valueMaxPx = mValueAxis->coordToPixel(valueMax); | |
|
23738 | const double keyMinPx = mKeyAxis->coordToPixel(keyMin); | |
|
23739 | const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); | |
|
23740 | const double keyPx = mKeyAxis->coordToPixel(key); | |
|
23741 | const double valuePx = mValueAxis->coordToPixel(value); | |
|
23742 | const double prevKeyPx = mKeyAxis->coordToPixel(prevKey); | |
|
23743 | const double prevValuePx = mValueAxis->coordToPixel(prevValue); | |
|
23500 | 23744 | if (qFuzzyIsNull(key - prevKey)) // line is parallel to value axis |
|
23501 | 23745 | { |
|
23502 |
// due to region filter in mayTraverse |
|
|
23503 | // traversed here | |
|
23746 | // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 | |
|
23747 | // is traversed here | |
|
23504 | 23748 | intersections.append( |
|
23505 | QPointF(key, valueMin)); // direction will be taken care of at end of method | |
|
23506 |
|
|
|
23749 | mKeyAxis->orientation() == Qt::Horizontal | |
|
23750 | ? QPointF(keyPx, valueMinPx) | |
|
23751 | : QPointF(valueMinPx, keyPx)); // direction will be taken care of at end of method | |
|
23752 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23753 | ? QPointF(keyPx, valueMaxPx) | |
|
23754 | : QPointF(valueMaxPx, keyPx)); | |
|
23507 | 23755 | } |
|
23508 | 23756 | else if (qFuzzyIsNull(value - prevValue)) // line is parallel to key axis |
|
23509 | 23757 | { |
|
23510 |
// due to region filter in mayTraverse |
|
|
23511 | // traversed here | |
|
23758 | // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 | |
|
23759 | // is traversed here | |
|
23512 | 23760 | intersections.append( |
|
23513 | QPointF(keyMin, value)); // direction will be taken care of at end of method | |
|
23514 |
|
|
|
23761 | mKeyAxis->orientation() == Qt::Horizontal | |
|
23762 | ? QPointF(keyMinPx, valuePx) | |
|
23763 | : QPointF(valuePx, keyMinPx)); // direction will be taken care of at end of method | |
|
23764 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23765 | ? QPointF(keyMaxPx, valuePx) | |
|
23766 | : QPointF(valuePx, keyMaxPx)); | |
|
23515 | 23767 | } |
|
23516 | 23768 | else // line is skewed |
|
23517 | 23769 | { |
|
23518 | 23770 | double gamma; |
|
23519 | double keyPerValue = (key - prevKey) / (value - prevValue); | |
|
23771 | double keyPerValuePx = (keyPx - prevKeyPx) / (valuePx - prevValuePx); | |
|
23520 | 23772 | // check top of rect: |
|
23521 | gamma = prevKey + (valueMax - prevValue) * keyPerValue; | |
|
23522 |
if (gamma >= keyMin |
|
|
23523 | intersections.append(QPointF(gamma, valueMax)); | |
|
23773 | gamma = prevKeyPx + (valueMaxPx - prevValuePx) * keyPerValuePx; | |
|
23774 | if (gamma >= qMin(keyMinPx, keyMaxPx) | |
|
23775 | && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed | |
|
23776 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23777 | ? QPointF(gamma, valueMaxPx) | |
|
23778 | : QPointF(valueMaxPx, gamma)); | |
|
23524 | 23779 | // check bottom of rect: |
|
23525 | gamma = prevKey + (valueMin - prevValue) * keyPerValue; | |
|
23526 |
if (gamma >= keyMin |
|
|
23527 | intersections.append(QPointF(gamma, valueMin)); | |
|
23528 | double valuePerKey = 1.0 / keyPerValue; | |
|
23780 | gamma = prevKeyPx + (valueMinPx - prevValuePx) * keyPerValuePx; | |
|
23781 | if (gamma >= qMin(keyMinPx, keyMaxPx) | |
|
23782 | && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed | |
|
23783 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23784 | ? QPointF(gamma, valueMinPx) | |
|
23785 | : QPointF(valueMinPx, gamma)); | |
|
23786 | const double valuePerKeyPx = 1.0 / keyPerValuePx; | |
|
23529 | 23787 | // check left of rect: |
|
23530 | gamma = prevValue + (keyMin - prevKey) * valuePerKey; | |
|
23531 |
if (gamma >= valueMin |
|
|
23532 | intersections.append(QPointF(keyMin, gamma)); | |
|
23788 | gamma = prevValuePx + (keyMinPx - prevKeyPx) * valuePerKeyPx; | |
|
23789 | if (gamma >= qMin(valueMinPx, valueMaxPx) | |
|
23790 | && gamma <= qMax(valueMinPx, | |
|
23791 | valueMaxPx)) // qMin/qMax necessary since axes may be reversed | |
|
23792 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23793 | ? QPointF(keyMinPx, gamma) | |
|
23794 | : QPointF(gamma, keyMinPx)); | |
|
23533 | 23795 | // check right of rect: |
|
23534 | gamma = prevValue + (keyMax - prevKey) * valuePerKey; | |
|
23535 |
if (gamma >= valueMin |
|
|
23536 | intersections.append(QPointF(keyMax, gamma)); | |
|
23796 | gamma = prevValuePx + (keyMaxPx - prevKeyPx) * valuePerKeyPx; | |
|
23797 | if (gamma >= qMin(valueMinPx, valueMaxPx) | |
|
23798 | && gamma <= qMax(valueMinPx, | |
|
23799 | valueMaxPx)) // qMin/qMax necessary since axes may be reversed | |
|
23800 | intersections.append(mKeyAxis->orientation() == Qt::Horizontal | |
|
23801 | ? QPointF(keyMaxPx, gamma) | |
|
23802 | : QPointF(gamma, keyMaxPx)); | |
|
23537 | 23803 | } |
|
23538 | 23804 | |
|
23539 | 23805 | // handle cases where found points isn't exactly 2: |
@@ -23562,12 +23828,16 bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double | |||
|
23562 | 23828 | } |
|
23563 | 23829 | |
|
23564 | 23830 | // possibly re-sort points so optimized point segment has same direction as original segment: |
|
23565 | if ((key - prevKey) * (intersections.at(1).x() - intersections.at(0).x()) | |
|
23566 | + (value - prevValue) * (intersections.at(1).y() - intersections.at(0).y()) | |
|
23831 | double xDelta = keyPx - prevKeyPx; | |
|
23832 | double yDelta = valuePx - prevValuePx; | |
|
23833 | if (mKeyAxis->orientation() != Qt::Horizontal) | |
|
23834 | qSwap(xDelta, yDelta); | |
|
23835 | if (xDelta * (intersections.at(1).x() - intersections.at(0).x()) | |
|
23836 | + yDelta * (intersections.at(1).y() - intersections.at(0).y()) | |
|
23567 | 23837 | < 0) // scalar product of both segments < 0 -> opposite direction |
|
23568 | 23838 | intersections.move(0, 1); |
|
23569 |
crossA = |
|
|
23570 |
crossB = |
|
|
23839 | crossA = intersections.at(0); | |
|
23840 | crossB = intersections.at(1); | |
|
23571 | 23841 | return true; |
|
23572 | 23842 | } |
|
23573 | 23843 | |
@@ -25678,8 +25948,8 QCPStatisticalBox::getWhiskerBarLines(QCPStatisticalBoxDataContainer::const_iter | |||
|
25678 | 25948 | /* end of 'src/plottables/plottable-statisticalbox.cpp' */ |
|
25679 | 25949 | |
|
25680 | 25950 | |
|
25681 |
/* including file 'src/plottables/plottable-colormap.cpp', size 47 |
|
|
25682 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
25951 | /* including file 'src/plottables/plottable-colormap.cpp', size 47881 */ | |
|
25952 | /* commit 83a770151292397b3ba4984108d7ed167a9aec65 2017-08-13 16:22:21 +0200 */ | |
|
25683 | 25953 | |
|
25684 | 25954 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
25685 | 25955 | //////////////////// QCPColorMapData |
@@ -26350,6 +26620,7 QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) | |||
|
26350 | 26620 | : QCPAbstractPlottable(keyAxis, valueAxis), |
|
26351 | 26621 | mDataScaleType(QCPAxis::stLinear), |
|
26352 | 26622 | mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))), |
|
26623 | mGradient(QCPColorGradient::gpCold), | |
|
26353 | 26624 | mInterpolate(true), |
|
26354 | 26625 | mTightBoundary(false), |
|
26355 | 26626 | mMapImageInvalidated(true) |
@@ -26709,73 +26980,81 void QCPColorMap::updateMapImage() | |||
|
26709 | 26980 | mMapImage = QImage( |
|
26710 | 26981 | QSize(valueSize * valueOversamplingFactor, keySize * keyOversamplingFactor), format); |
|
26711 | 26982 | |
|
26712 | QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. | |
|
26713 | // Either the final mMapImage, or if we need oversampling, | |
|
26714 | // mUndersampledMapImage | |
|
26715 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |
|
26716 | // resize undersampled map image to actual key/value cell sizes: | |
|
26717 | if (keyAxis->orientation() == Qt::Horizontal | |
|
26718 | && (mUndersampledMapImage.width() != keySize | |
|
26719 | || mUndersampledMapImage.height() != valueSize)) | |
|
26720 | mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); | |
|
26721 | else if (keyAxis->orientation() == Qt::Vertical | |
|
26722 | && (mUndersampledMapImage.width() != valueSize | |
|
26723 | || mUndersampledMapImage.height() != keySize)) | |
|
26724 | mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); | |
|
26725 | localMapImage | |
|
26726 | = &mUndersampledMapImage; // make the colorization run on the undersampled image | |
|
26727 | } | |
|
26728 | else if (!mUndersampledMapImage.isNull()) | |
|
26729 | mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has | |
|
26730 | // changed) but mUndersampledMapImage still has nonzero | |
|
26731 | // size, free it | |
|
26732 | ||
|
26733 | const double *rawData = mMapData->mData; | |
|
26734 | const unsigned char *rawAlpha = mMapData->mAlpha; | |
|
26735 | if (keyAxis->orientation() == Qt::Horizontal) { | |
|
26736 | const int lineCount = valueSize; | |
|
26737 | const int rowCount = keySize; | |
|
26738 | for (int line = 0; line < lineCount; ++line) { | |
|
26739 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |
|
26740 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |
|
26741 | // from top, but our vertical index counts from bottom | |
|
26742 | // (mathematical coordinate system) | |
|
26743 | if (rawAlpha) | |
|
26744 | mGradient.colorize(rawData + line * rowCount, rawAlpha + line * rowCount, | |
|
26745 | mDataRange, pixels, rowCount, 1, | |
|
26746 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
26747 | else | |
|
26748 | mGradient.colorize(rawData + line * rowCount, mDataRange, pixels, rowCount, 1, | |
|
26749 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
26750 | } | |
|
26983 | if (mMapImage.isNull()) { | |
|
26984 | qDebug() << Q_FUNC_INFO << "Couldn't create map image (possibly too large for memory)"; | |
|
26985 | mMapImage = QImage(QSize(10, 10), format); | |
|
26986 | mMapImage.fill(Qt::black); | |
|
26751 | 26987 | } |
|
26752 | else // keyAxis->orientation() == Qt::Vertical | |
|
26753 | { | |
|
26754 | const int lineCount = keySize; | |
|
26755 | const int rowCount = valueSize; | |
|
26756 | for (int line = 0; line < lineCount; ++line) { | |
|
26757 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |
|
26758 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |
|
26759 | // from top, but our vertical index counts from bottom | |
|
26760 | // (mathematical coordinate system) | |
|
26761 | if (rawAlpha) | |
|
26762 | mGradient.colorize(rawData + line, rawAlpha + line, mDataRange, pixels, rowCount, | |
|
26763 | lineCount, mDataScaleType == QCPAxis::stLogarithmic); | |
|
26764 | else | |
|
26765 | mGradient.colorize(rawData + line, mDataRange, pixels, rowCount, lineCount, | |
|
26766 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
26988 | else { | |
|
26989 | QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. | |
|
26990 | // Either the final mMapImage, or if we need | |
|
26991 | // oversampling, mUndersampledMapImage | |
|
26992 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |
|
26993 | // resize undersampled map image to actual key/value cell sizes: | |
|
26994 | if (keyAxis->orientation() == Qt::Horizontal | |
|
26995 | && (mUndersampledMapImage.width() != keySize | |
|
26996 | || mUndersampledMapImage.height() != valueSize)) | |
|
26997 | mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); | |
|
26998 | else if (keyAxis->orientation() == Qt::Vertical | |
|
26999 | && (mUndersampledMapImage.width() != valueSize | |
|
27000 | || mUndersampledMapImage.height() != keySize)) | |
|
27001 | mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); | |
|
27002 | localMapImage | |
|
27003 | = &mUndersampledMapImage; // make the colorization run on the undersampled image | |
|
27004 | } | |
|
27005 | else if (!mUndersampledMapImage.isNull()) | |
|
27006 | mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size | |
|
27007 | // has changed) but mUndersampledMapImage still has | |
|
27008 | // nonzero size, free it | |
|
27009 | ||
|
27010 | const double *rawData = mMapData->mData; | |
|
27011 | const unsigned char *rawAlpha = mMapData->mAlpha; | |
|
27012 | if (keyAxis->orientation() == Qt::Horizontal) { | |
|
27013 | const int lineCount = valueSize; | |
|
27014 | const int rowCount = keySize; | |
|
27015 | for (int line = 0; line < lineCount; ++line) { | |
|
27016 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |
|
27017 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |
|
27018 | // from top, but our vertical index counts from bottom | |
|
27019 | // (mathematical coordinate system) | |
|
27020 | if (rawAlpha) | |
|
27021 | mGradient.colorize(rawData + line * rowCount, rawAlpha + line * rowCount, | |
|
27022 | mDataRange, pixels, rowCount, 1, | |
|
27023 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
27024 | else | |
|
27025 | mGradient.colorize(rawData + line * rowCount, mDataRange, pixels, rowCount, 1, | |
|
27026 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
27027 | } | |
|
27028 | } | |
|
27029 | else // keyAxis->orientation() == Qt::Vertical | |
|
27030 | { | |
|
27031 | const int lineCount = keySize; | |
|
27032 | const int rowCount = valueSize; | |
|
27033 | for (int line = 0; line < lineCount; ++line) { | |
|
27034 | QRgb *pixels = reinterpret_cast<QRgb *>(localMapImage->scanLine( | |
|
27035 | lineCount - 1 - line)); // invert scanline index because QImage counts scanlines | |
|
27036 | // from top, but our vertical index counts from bottom | |
|
27037 | // (mathematical coordinate system) | |
|
27038 | if (rawAlpha) | |
|
27039 | mGradient.colorize(rawData + line, rawAlpha + line, mDataRange, pixels, | |
|
27040 | rowCount, lineCount, | |
|
27041 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
27042 | else | |
|
27043 | mGradient.colorize(rawData + line, mDataRange, pixels, rowCount, lineCount, | |
|
27044 | mDataScaleType == QCPAxis::stLogarithmic); | |
|
27045 | } | |
|
26767 | 27046 | } |
|
26768 | } | |
|
26769 | 27047 | |
|
26770 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |
|
26771 | if (keyAxis->orientation() == Qt::Horizontal) | |
|
26772 |
mMapImage = mUndersampledMapImage.scaled( |
|
|
26773 |
|
|
|
26774 |
|
|
|
26775 | else | |
|
26776 |
mMapImage = mUndersampledMapImage.scaled( |
|
|
26777 |
|
|
|
26778 |
|
|
|
27048 | if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) { | |
|
27049 | if (keyAxis->orientation() == Qt::Horizontal) | |
|
27050 | mMapImage = mUndersampledMapImage.scaled( | |
|
27051 | keySize * keyOversamplingFactor, valueSize * valueOversamplingFactor, | |
|
27052 | Qt::IgnoreAspectRatio, Qt::FastTransformation); | |
|
27053 | else | |
|
27054 | mMapImage = mUndersampledMapImage.scaled( | |
|
27055 | valueSize * valueOversamplingFactor, keySize * keyOversamplingFactor, | |
|
27056 | Qt::IgnoreAspectRatio, Qt::FastTransformation); | |
|
27057 | } | |
|
26779 | 27058 | } |
|
26780 | 27059 | mMapData->mDataModified = false; |
|
26781 | 27060 | mMapImageInvalidated = false; |
@@ -27939,8 +28218,8 QRectF QCPFinancial::selectionHitBox(QCPFinancialDataContainer::const_iterator i | |||
|
27939 | 28218 | /* end of 'src/plottables/plottable-financial.cpp' */ |
|
27940 | 28219 | |
|
27941 | 28220 | |
|
27942 |
/* including file 'src/plottables/plottable-errorbar.cpp', size 37 |
|
|
27943 | /* commit 633339dadc92cb10c58ef3556b55570685fafb99 2016-09-13 23:54:56 +0200 */ | |
|
28221 | /* including file 'src/plottables/plottable-errorbar.cpp', size 37355 */ | |
|
28222 | /* commit 6f159843e9ec9ea6431b26591937aea13a9f2751 2017-07-25 11:13:32 +0200 */ | |
|
27944 | 28223 | |
|
27945 | 28224 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|
27946 | 28225 | //////////////////// QCPErrorBarsData |
@@ -28671,8 +28950,8 void QCPErrorBars::getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it | |||
|
28671 | 28950 | QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index); |
|
28672 | 28951 | if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y())) |
|
28673 | 28952 | return; |
|
28674 | QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis : mKeyAxis; | |
|
28675 | QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis : mValueAxis; | |
|
28953 | QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis.data() : mKeyAxis.data(); | |
|
28954 | QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis.data() : mValueAxis.data(); | |
|
28676 | 28955 | const double centerErrorAxisPixel |
|
28677 | 28956 | = errorAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); |
|
28678 | 28957 | const double centerOrthoAxisPixel |
@@ -28806,6 +29085,10 double QCPErrorBars::pointDistance(const QPointF &pixelPoint, | |||
|
28806 | 29085 | closestData = mDataContainer->constEnd(); |
|
28807 | 29086 | if (!mDataPlottable || mDataContainer->isEmpty()) |
|
28808 | 29087 | return -1.0; |
|
29088 | if (!mKeyAxis || !mValueAxis) { | |
|
29089 | qDebug() << Q_FUNC_INFO << "invalid key or value axis"; | |
|
29090 | return -1.0; | |
|
29091 | } | |
|
28809 | 29092 | |
|
28810 | 29093 | QCPErrorBarsDataContainer::const_iterator begin, end; |
|
28811 | 29094 | getVisibleDataBounds(begin, end, QCPDataRange(0, dataCount())); |
General Comments 0
You need to be logged in to leave comments.
Login now