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