1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <private/xlogypolardomain_p.h>
5#include <private/qabstractaxis_p.h>
6#include <QtCharts/QLogValueAxis>
7#include <QtCore/QtMath>
8#include <cmath>
9
10QT_BEGIN_NAMESPACE
11
12XLogYPolarDomain::XLogYPolarDomain(QObject *parent)
13 : PolarDomain(parent),
14 m_logInnerY(0),
15 m_logOuterY(1),
16 m_logBaseY(10)
17{
18}
19
20XLogYPolarDomain::~XLogYPolarDomain()
21{
22}
23
24void XLogYPolarDomain::setRange(qreal minX, qreal maxX, qreal minY, qreal maxY)
25{
26 bool axisXChanged = false;
27 bool axisYChanged = false;
28
29 adjustLogDomainRanges(min&: minY, max&: maxY);
30
31 if (!qFuzzyIsNull(d: m_minX - minX) || !qFuzzyIsNull(d: m_maxX - maxX)) {
32 m_minX = minX;
33 m_maxX = maxX;
34 axisXChanged = true;
35 if (!m_signalsBlocked)
36 emit rangeHorizontalChanged(min: m_minX, max: m_maxX);
37 }
38
39 if (!qFuzzyIsNull(d: m_minY - minY) || !qFuzzyIsNull(d: m_maxY - maxY)) {
40 m_minY = minY;
41 m_maxY = maxY;
42 axisYChanged = true;
43 qreal logMinY = qLn(v: m_minY) / qLn(v: m_logBaseY);
44 qreal logMaxY = qLn(v: m_maxY) / qLn(v: m_logBaseY);
45 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
46 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
47 if (!m_signalsBlocked)
48 emit rangeVerticalChanged(min: m_minY, max: m_maxY);
49 }
50
51 if (axisXChanged || axisYChanged)
52 emit updated();
53}
54
55void XLogYPolarDomain::zoomIn(const QRectF &rect)
56{
57 storeZoomReset();
58 qreal dx = spanX() / m_size.width();
59 qreal maxX = m_maxX;
60 qreal minX = m_minX;
61
62 maxX = minX + dx * rect.right();
63 minX = minX + dx * rect.left();
64
65 qreal logLeftY = m_logOuterY - rect.bottom() * (m_logOuterY - m_logInnerY) / m_size.height();
66 qreal logRightY = m_logOuterY - rect.top() * (m_logOuterY - m_logInnerY) / m_size.height();
67 qreal leftY = qPow(x: m_logBaseY, y: logLeftY);
68 qreal rightY = qPow(x: m_logBaseY, y: logRightY);
69 qreal minY = leftY < rightY ? leftY : rightY;
70 qreal maxY = leftY > rightY ? leftY : rightY;
71
72 setRange(minX, maxX, minY, maxY);
73}
74
75void XLogYPolarDomain::zoomOut(const QRectF &rect)
76{
77 storeZoomReset();
78 qreal dx = spanX() / rect.width();
79 qreal maxX = m_maxX;
80 qreal minX = m_minX;
81
82 minX = maxX - dx * rect.right();
83 maxX = minX + dx * m_size.width();
84
85 const qreal factorY = m_size.height() / rect.height();
86 qreal newLogMinY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 - factorY);
87 qreal newLogMaxY = m_logInnerY + (m_logOuterY - m_logInnerY) / 2.0 * (1.0 + factorY);
88 qreal leftY = qPow(x: m_logBaseY, y: newLogMinY);
89 qreal rightY = qPow(x: m_logBaseY, y: newLogMaxY);
90 qreal minY = leftY < rightY ? leftY : rightY;
91 qreal maxY = leftY > rightY ? leftY : rightY;
92
93 setRange(minX, maxX, minY, maxY);
94}
95
96void XLogYPolarDomain::move(qreal dx, qreal dy)
97{
98 qreal x = spanX() / 360.0;
99
100 qreal maxX = m_maxX;
101 qreal minX = m_minX;
102
103 if (dx != 0) {
104 minX = minX + x * dx;
105 maxX = maxX + x * dx;
106 }
107
108 qreal stepY = dy * (m_logOuterY - m_logInnerY) / m_radius;
109 qreal leftY = qPow(x: m_logBaseY, y: m_logInnerY + stepY);
110 qreal rightY = qPow(x: m_logBaseY, y: m_logOuterY + stepY);
111 qreal minY = leftY < rightY ? leftY : rightY;
112 qreal maxY = leftY > rightY ? leftY : rightY;
113
114 setRange(minX, maxX, minY, maxY);
115}
116
117qreal XLogYPolarDomain::toAngularCoordinate(qreal value, bool &ok) const
118{
119 ok = true;
120 qreal f = (value - m_minX) / (m_maxX - m_minX);
121 return f * 360.0;
122}
123
124qreal XLogYPolarDomain::toRadialCoordinate(qreal value, bool &ok) const
125{
126 qreal retVal;
127 if (value <= 0) {
128 ok = false;
129 retVal = 0.0;
130 } else {
131 ok = true;
132 const qreal tickSpan = m_radius / qAbs(t: m_logOuterY - m_logInnerY);
133 const qreal logValue = qLn(v: value) / qLn(v: m_logBaseY);
134 const qreal valueDelta = logValue - m_logInnerY;
135
136 retVal = valueDelta * tickSpan;
137
138 if (retVal < 0.0)
139 retVal = 0.0;
140 }
141 return retVal;
142}
143
144QPointF XLogYPolarDomain::calculateDomainPoint(const QPointF &point) const
145{
146 if (point == m_center)
147 return QPointF(0.0, m_minY);
148
149 QLineF line(m_center, point);
150 qreal a = 90.0 - line.angle();
151 if (a < 0.0)
152 a += 360.0;
153 a = ((a / 360.0) * (m_maxX - m_minX)) + m_minX;
154
155 const qreal deltaY = m_radius / qAbs(t: m_logOuterY - m_logInnerY);
156 qreal r = qPow(x: m_logBaseY, y: m_logInnerY + (line.length() / deltaY));
157
158 return QPointF(a, r);
159}
160
161bool XLogYPolarDomain::attachAxis(QAbstractAxis *axis)
162{
163 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(object: axis);
164
165 if (logAxis && logAxis->orientation() == Qt::Vertical) {
166 QObject::connect(sender: logAxis, SIGNAL(baseChanged(qreal)), receiver: this, SLOT(handleVerticalAxisBaseChanged(qreal)));
167 handleVerticalAxisBaseChanged(baseY: logAxis->base());
168 }
169 return AbstractDomain::attachAxis(axis);
170}
171
172bool XLogYPolarDomain::detachAxis(QAbstractAxis *axis)
173{
174 QLogValueAxis *logAxis = qobject_cast<QLogValueAxis *>(object: axis);
175
176 if (logAxis && logAxis->orientation() == Qt::Vertical)
177 QObject::disconnect(sender: logAxis, SIGNAL(baseChanged(qreal)), receiver: this, SLOT(handleVerticalAxisBaseChanged(qreal)));
178
179 return AbstractDomain::detachAxis(axis);
180}
181
182void XLogYPolarDomain::handleVerticalAxisBaseChanged(qreal baseY)
183{
184 m_logBaseY = baseY;
185 qreal logMinY = qLn(v: m_minY) / qLn(v: m_logBaseY);
186 qreal logMaxY = qLn(v: m_maxY) / qLn(v: m_logBaseY);
187 m_logInnerY = logMinY < logMaxY ? logMinY : logMaxY;
188 m_logOuterY = logMinY > logMaxY ? logMinY : logMaxY;
189 emit updated();
190}
191
192// operators
193
194bool Q_AUTOTEST_EXPORT operator== (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
195{
196 return (qFuzzyIsNull(d: domain1.m_maxX - domain2.m_maxX)
197 && qFuzzyIsNull(d: domain1.m_maxY - domain2.m_maxY)
198 && qFuzzyIsNull(d: domain1.m_minX - domain2.m_minX)
199 && qFuzzyIsNull(d: domain1.m_minY - domain2.m_minY));
200}
201
202
203bool Q_AUTOTEST_EXPORT operator!= (const XLogYPolarDomain &domain1, const XLogYPolarDomain &domain2)
204{
205 return !(domain1 == domain2);
206}
207
208
209QDebug Q_AUTOTEST_EXPORT operator<<(QDebug dbg, const XLogYPolarDomain &domain)
210{
211#ifdef QT_NO_TEXTSTREAM
212 Q_UNUSED(domain);
213#else
214 dbg.nospace() << "AbstractDomain(" << domain.m_minX << ',' << domain.m_maxX << ',' << domain.m_minY << ',' << domain.m_maxY << ')' << domain.m_size;
215#endif
216 return dbg.maybeSpace();
217}
218
219QT_END_NAMESPACE
220
221#include "moc_xlogypolardomain_p.cpp"
222

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