Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickgeocoordinateanimation.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7#include <QtQuick/private/qquickanimation_p_p.h>
8#include <QtPositioning/private/qdoublevector2d_p.h>
9#include <QtPositioning/private/qwebmercator_p.h>
10#include <QtPositioning/private/qgeocoordinate_p.h>
11
13
14/*!
15 \qmltype CoordinateAnimation
16 \inherits PropertyAnimation
17 \inqmlmodule QtPositioning
18 \since 5.3
19
20 \brief A PropertyAnimation for geo coordinate properties.
21
22 A specialized \l{PropertyAnimation} that defines an animation
23 between two \l{geoCoordinate}{coordinates}.
24
25 By default, a \l{geoCoordinate::latitude}{latitude} of the
26 \l geoCoordinate is animated in the direction of shortest
27 (geodesic) distance between those coordinates. Since CoordinateAnimation uses Mercator
28 map projection, the \l{geoCoordinate::latitude}{latitude} animation
29 is always between -90 and 90 degrees.
30 The \l{geoCoordinate::longitude}{longitude} animation path is not
31 limited and can go over 180 degrees in both west and east directions.
32
33 The \l{direction} property can be set to specify the direction in which the
34 \l{geoCoordinate::longitude}{longitude} animation should occur.
35
36 \sa {Animation and Transitions in Qt Quick}
37*/
38
39QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
40{
41 if (from == to) {
42 if (progress < 0.5) {
43 return QVariant::fromValue(from);
44 } else {
45 return QVariant::fromValue(to);
46 }
47 }
48
49 QGeoCoordinate result = QWebMercator::coordinateInterpolation(from, to, progress);
50
51 return QVariant::fromValue(result);
52}
53
54QVariant q_coordinateShortestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
55{
56 const QGeoMercatorCoordinatePrivate* fromMercator =
57 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from));
58 const QGeoMercatorCoordinatePrivate* toMercator =
59 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to));
60
61 double toX = toMercator->m_mercatorX;
62 double toY = toMercator->m_mercatorY;
63 double fromX = fromMercator->m_mercatorX;
64 double fromY = fromMercator->m_mercatorY;
65 double x;
66 if (0.5 < qAbs(toX - fromX)) {
67 // handle dateline crossing
68 double ex = toX;
69 double sx = fromX;
70 if (ex < sx)
71 sx -= 1.0;
72 else if (sx < ex)
73 ex -= 1.0;
74
75 x = sx + (ex - sx) * progress;
76
77 if (x < 0.0)
78 x += 1.0;
79
80 } else {
81 x = fromX + (toX - fromX) * progress;
82 }
83
84 double y = fromY + (toY - fromY) * progress;
85
86 QGeoCoordinate result = QWebMercator::mercatorToCoord(QDoubleVector2D(x, y));
87 result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress);
88 return QVariant::fromValue(result);
89}
90
91QVariant q_coordinateEastInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
92{
93 const QGeoMercatorCoordinatePrivate* fromMercator =
94 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from));
95 const QGeoMercatorCoordinatePrivate* toMercator =
96 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to));
97
98 double toX = toMercator->m_mercatorX;
99 double toY = toMercator->m_mercatorY;
100 double fromX = fromMercator->m_mercatorX;
101 double fromY = fromMercator->m_mercatorY;
102 double diff = toX - fromX;
103
104 while (diff < 0.0) {
105 toX += 1.0;
106 diff += 1.0;
107 }
108
109 double x = fromX + (toX - fromX) * progress;
110 double y = fromY + (toY - fromY) * progress;
111
112 while (x > 1.0)
113 x -= 1.0;
114
115 QGeoCoordinate result = QWebMercator::mercatorToCoord(QDoubleVector2D(x, y));
116 result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress);
117
118 return QVariant::fromValue(result);
119}
120
121QVariant q_coordinateWestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
122{
123 const QGeoMercatorCoordinatePrivate* fromMercator =
124 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&from));
125 const QGeoMercatorCoordinatePrivate* toMercator =
126 static_cast<const QGeoMercatorCoordinatePrivate*>(QGeoCoordinatePrivate::get(&to));
127
128 double toX = toMercator->m_mercatorX;
129 double toY = toMercator->m_mercatorY;
130 double fromX = fromMercator->m_mercatorX;
131 double fromY = fromMercator->m_mercatorY;
132 double diff = toX - fromX;
133
134 while (diff > 0.0) {
135 toX -= 1.0;
136 diff -= 1.0;
137 }
138
139 double x = fromX + (toX - fromX) * progress;
140 double y = fromY + (toY - fromY) * progress;
141
142 while (x < 0.0)
143 x += 1.0;
144
145 QGeoCoordinate result = QWebMercator::mercatorToCoord(QDoubleVector2D(x, y));
146 result.setAltitude(from.altitude() + (to.altitude() - from.altitude()) * progress);
147
148 return QVariant::fromValue(result);
149}
150
151QQuickGeoCoordinateAnimation::QQuickGeoCoordinateAnimation(QObject *parent)
152 : QQuickPropertyAnimation(*(new QQuickGeoCoordinateAnimationPrivate), parent)
153
154{
155 Q_D(QQuickGeoCoordinateAnimation);
156 d->interpolatorType = qMetaTypeId<QGeoCoordinate>();
157 d->defaultToInterpolatorType = true;
158 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
159}
160
161QQuickGeoCoordinateAnimation::~QQuickGeoCoordinateAnimation()
162{
163}
164
165/*!
166 \qmlproperty coordinate CoordinateAnimation::from
167 This property holds the coordinate where the animation should begin.
168*/
169QGeoCoordinate QQuickGeoCoordinateAnimation::from() const
170{
171 Q_D(const QQuickGeoCoordinateAnimation);
172 return d->from.value<QGeoCoordinate>();
173}
174
175void QQuickGeoCoordinateAnimation::setFrom(const QGeoCoordinate &f)
176{
177 QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate();
178 QDoubleVector2D fromVector = QWebMercator::coordToMercator(f);
179 mercator->lat = f.latitude();
180 mercator->lng = f.longitude();
181 mercator->alt = f.altitude();
182 mercator->m_mercatorX = fromVector.x();
183 mercator->m_mercatorY = fromVector.y();
184 QGeoCoordinate from(*mercator);
185 QQuickPropertyAnimation::setFrom(QVariant::fromValue(from));
186}
187
188/*!
189 \qmlproperty coordinate CoordinateAnimation::to
190 This property holds the coordinate where the animation should end.
191*/
192QGeoCoordinate QQuickGeoCoordinateAnimation::to() const
193{
194 Q_D(const QQuickGeoCoordinateAnimation);
195 return d->to.value<QGeoCoordinate>();
196}
197
198void QQuickGeoCoordinateAnimation::setTo(const QGeoCoordinate &t)
199{
200 QGeoMercatorCoordinatePrivate *mercator = new QGeoMercatorCoordinatePrivate();
201 QDoubleVector2D toVector = QWebMercator::coordToMercator(t);
202 mercator->lat = t.latitude();
203 mercator->lng = t.longitude();
204 mercator->alt = t.altitude();
205 mercator->m_mercatorX = toVector.x();
206 mercator->m_mercatorY = toVector.y();
207 QGeoCoordinate to(*mercator);
208 QQuickPropertyAnimation::setTo(QVariant::fromValue(to));
209}
210
211/*!
212 \qmlproperty enumeration CoordinateAnimation::direction
213
214 This property holds the direction of the
215 \l{geoCoordinate::longitude}{longitude} animation of the
216 \l geoCoordinate.
217
218 \value CoordinateAnimation.Shortest
219 The longitude animation goes in the direction
220 that produces the shortest animation path. This is the default.
221 \value CoordinateAnimation.West
222 The longitude animation always goes into western direction
223 and may cross the date line.
224 \value CoordinateAnimation.East
225 The longitude animation always goes into eastern direction
226 and may cross the date line.
227
228 \since 5.5
229*/
230
231
232QQuickGeoCoordinateAnimation::Direction QQuickGeoCoordinateAnimation::direction() const
233{
234 Q_D(const QQuickGeoCoordinateAnimation);
235 return d->m_direction.value();
236}
237
238void QQuickGeoCoordinateAnimation::setDirection(QQuickGeoCoordinateAnimation::Direction direction)
239{
240 Q_D( QQuickGeoCoordinateAnimation);
241 d->m_direction.removeBindingUnlessInWrapper();
242 if (d->m_direction.valueBypassingBindings() == direction)
243 return;
244
245 d->m_direction.setValueBypassingBindings(direction);
246 switch (direction) {
247 case West:
248 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateWestInterpolator));
249 break;
250 case East:
251 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateEastInterpolator));
252 break;
253 case Shortest:
254 default:
255 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateShortestInterpolator));
256 break;
257 }
258 d->m_direction.notify();
259}
260
261QBindable<QQuickGeoCoordinateAnimation::Direction> QQuickGeoCoordinateAnimation::bindableDirection()
262{
263 Q_D(QQuickGeoCoordinateAnimation);
264 return QBindable<Direction>(&d->m_direction);
265}
266
267QT_END_NAMESPACE
268
269#include "moc_qquickgeocoordinateanimation_p.cpp"
Combined button and popup list for selecting options.
QVariant q_coordinateShortestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
QVariant q_coordinateWestInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)
QVariant q_coordinateEastInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress)