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 This property holds the direction of the \l{longitude} animation of the \l{coordinate}.
211
212 Possible values are:
213
214 \list
215 \li CoordinateAnimation.Shortest (default) - the longitude animation goes in the direction
216 that produces the shortest animation path.
217 \li CoordinateAnimation.West - the longitude animation always goes into western direction
218 and may cross the date line.
219 \li CoordinateAnimation.East - the longitude animation always goes into eastern direction
220 and may cross the date line.
221 \endlist
222 \since 5.5
223*/
224
225
226QQuickGeoCoordinateAnimation::Direction QQuickGeoCoordinateAnimation::direction() const
227{
228 Q_D(const QQuickGeoCoordinateAnimation);
229 return d->m_direction.value();
230}
231
232void QQuickGeoCoordinateAnimation::setDirection(QQuickGeoCoordinateAnimation::Direction direction)
233{
234 Q_D( QQuickGeoCoordinateAnimation);
235 d->m_direction.removeBindingUnlessInWrapper();
236 if (d->m_direction.valueBypassingBindings() == direction)
237 return;
238
239 d->m_direction.setValueBypassingBindings(direction);
240 switch (direction) {
241 case West:
242 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateWestInterpolator));
243 break;
244 case East:
245 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateEastInterpolator));
246 break;
247 case Shortest:
248 default:
249 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(reinterpret_cast<void *>(&q_coordinateShortestInterpolator));
250 break;
251 }
252 d->m_direction.notify();
253}
254
255QBindable<QQuickGeoCoordinateAnimation::Direction> QQuickGeoCoordinateAnimation::bindableDirection()
256{
257 Q_D(QQuickGeoCoordinateAnimation);
258 return QBindable<Direction>(&d->m_direction);
259}
260
261QT_END_NAMESPACE
262
263#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)