1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Charts module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include <private/xlogypolardomain_p.h>
31#include <private/qabstractaxis_p.h>
32#include <QtCharts/QLogValueAxis>
33#include <QtCore/QtMath>
34#include <cmath>
35
36QT_CHARTS_BEGIN_NAMESPACE
37
38XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
39 : PolarDomain(parent),
40 m_logInnerY(0),
41 m_logOuterY(1),
42 m_logBaseY(10)
43{
44}
45
46XLogYPolarDomain::~XLogYPolarDomain()
47{
48}
49
50void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
51{
52 bool axisXChanged = false;
53 bool axisYChanged = false;
54
55 adjustLogDomainRanges(min&: minY, max&: maxY);
56
57 if (!qFuzzyIsNull(d: m_minX - minX) || !qFuzzyIsNull(d: m_maxX - maxX)) {
58 m_minX = minX;
59 m_maxX = maxX;
60 axisXChanged = true;
61 if (!m_signalsBlocked)
62 emit rangeHorizontalChanged(min: m_minX, max: m_maxX);
63 }
64
65 if (!qFuzzyIsNull(d: m_minY - minY) || !qFuzzyIsNull(d: m_maxY - maxY)) {
66 m_minY = minY;
67 m_maxY = maxY;
68 axisYChanged = true;
69 qreal logMinY = std::log10(x: m_minY) / std::log10(x: m_logBaseY);
70 qreal logMaxY = std::log10(x: m_maxY) / std::log10(x: m_logBaseY);
71 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
72 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
73 if (!m_signalsBlocked)
74 emit rangeVerticalChanged(min: m_minY, max: m_maxY);
75 }
76
77 if (axisXChanged || axisYChanged)
78 emit updated();
79}
80
81void XLogYPolarDomain::zoomIn(const QRectF &rect)
82{
83 storeZoomReset();
84 qreal dx = spanX() / m_size.width();
85 qreal maxX = m_maxX;
86 qreal minX = m_minX;
87
88 maxX = minX + dx * rect.right();
89 minX = minX + dx * rect.left();
90
91 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
92 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
93 qreal leftY = qPow(x: m_logBaseY, y: logLeftY);
94 qreal rightY = qPow(x: m_logBaseY, y: logRightY);
95 qreal minY = leftY < rightY ? leftY : rightY;
96 qreal maxY = leftY > rightY ? leftY : rightY;
97
98 setRange(minX, maxX, minY, maxY);
99}
100
101void XLogYPolarDomain::zoomOut(const QRectF &rect)
102{
103 storeZoomReset();
104 qreal dx = spanX() / rect.width();
105 qreal maxX = m_maxX;
106 qreal minX = m_minX;
107
108 minX = maxX - dx * rect.right();
109 maxX = minX + dx * m_size.width();
110
111 const qreal factorY = m_size.height() / rect.height();
112 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
113 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
114 qreal leftY = qPow(x: m_logBaseY, y: newLogMinY);
115 qreal rightY = qPow(x: m_logBaseY, y: newLogMaxY);
116 qreal minY = leftY < rightY ? leftY : rightY;
117 qreal maxY = leftY > rightY ? leftY : rightY;
118
119 setRange(minX, maxX, minY, maxY);
120}
121
122void XLogYPolarDomain::move(qreal dx, qreal dy)
123{
124 qreal x = spanX() / 360.0;
125
126 qreal maxX = m_maxX;
127 qreal minX = m_minX;
128
129 if (dx != 0) {
130 minX = minX + x * dx;
131 maxX = maxX + x * dx;
132 }
133
134 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
135 qreal leftY = qPow(x: m_logBaseY, y: m_logInnerY + stepY);
136 qreal rightY = qPow(x: m_logBaseY, y: m_logOuterY + stepY);
137 qreal minY = leftY < rightY ? leftY : rightY;
138 qreal maxY = leftY > rightY ? leftY : rightY;
139
140 setRange(minX, maxX, minY, maxY);
141}
142
143qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
144{
145 ok = true;
146 qreal f = (value - m_minX) / (m_maxX - m_minX);
147 return f * 360.0;
148}
149
150qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
151{
152 qreal retVal;
153 if (value <= 0) {
154 ok = false;
155 retVal = 0.0;
156 } else {
157 ok = true;
158 const qreal tickSpan = m_radius / qAbs(t: m_logOuterY - m_logInnerY);
159 const qreal logValue = std::log10(x: value) / std::log10(x: m_logBaseY);
160 const qreal valueDelta = logValue - m_logInnerY;
161
162 retVal = valueDelta * tickSpan;
163
164 if (retVal < 0.0)
165 retVal = 0.0;
166 }
167 return retVal;
168}
169
170QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
171{
172 if (point == m_center)
173 return QPointF(0.0, m_minY);
174
175 QLineF line(m_center, point);
176 qreal a = 90.0 - line.angle();
177 if (a < 0.0)
178 a += 360.0;
179 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
180
181 const qreal deltaY = m_radius / qAbs(t: m_logOuterY - m_logInnerY);
182 qreal r = qPow(x: m_logBaseY, y: m_logInnerY + (line.length() / deltaY));
183
184 return QPointF(a, r);
185}
186
187bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
188{
189 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(object: axis);
190
191 if (logAxis && logAxis->orientation() == Qt::Vertical) {
192 QObject::connect(sender: logAxis, SIGNAL(baseChanged(qreal)), receiver: this, SLOT(handleVerticalAxisBaseChanged(qreal)));
193 handleVerticalAxisBaseChanged(baseY: logAxis->base());
194 }
195 return AbstractDomain::attachAxis(axis);
196}
197
198bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
199{
200 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(object: axis);
201
202 if (logAxis && logAxis->orientation() == Qt::Vertical)
203 QObject::disconnect(sender: logAxis, SIGNAL(baseChanged(qreal)), receiver: this, SLOT(handleVerticalAxisBaseChanged(qreal)));
204
205 return AbstractDomain::detachAxis(axis);
206}
207
208void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
209{
210 m_logBaseY = baseY;
211 qreal logMinY = std::log10(x: m_minY) / std::log10(x: m_logBaseY);
212 qreal logMaxY = std::log10(x: m_maxY) / std::log10(x: m_logBaseY);
213 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
214 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
215 emit updated();
216}
217
218// operators
219
220bool Q_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
221{
222 return (qFuzzyIsNull(d: domain1.m_maxX - domain2.m_maxX)
223 && qFuzzyIsNull(d: domain1.m_maxY - domain2.m_maxY)
224 && qFuzzyIsNull(d: domain1.m_minX - domain2.m_minX)
225 && qFuzzyIsNull(d: domain1.m_minY - domain2.m_minY));
226}
227
228
229bool Q_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
230{
231 return !(domain1 == domain2);
232}
233
234
235QDebug Q_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
236{
237#ifdef QT_NO_TEXTSTREAM
238 Q_UNUSED(domain)
239#else
240 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
241#endif
242 return dbg.maybeSpace();
243}
244
245QT_CHARTS_END_NAMESPACE
246
247#include "moc_xlogypolardomain_p.cpp"
248

source code of qtcharts/src/charts/domain/xlogypolardomain.cpp