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