6#include "MarblePhysics.h"
8#include "GeoDataLineString.h"
9#include "GeoDataLookAt.h"
10#include "MarbleAbstractPresenter.h"
11#include "MarbleDebug.h"
12#include "Quaternion.h"
20class MarblePhysicsPrivate
23 MarbleAbstractPresenter *
const m_presenter;
25 GeoDataLookAt m_source;
27 GeoDataLookAt m_target;
35 explicit MarblePhysicsPrivate(MarbleAbstractPresenter *presenter)
36 : m_presenter(presenter)
38 , m_planetRadius(EARTH_RADIUS)
44 qreal suggestedRange(qreal t)
const
47 Q_ASSERT(0 <= t && t <= 1.0);
50 qreal in = m_source.range();
51 qreal out = m_target.range();
53 return in + t * (out - in);
54 }
else if (m_mode ==
Jump) {
55 qreal jumpDuration = m_timeline.
duration();
58 const qreal totalDistance = m_planetRadius * m_source.coordinates().sphericalDistanceTo(m_target.coordinates());
59 qreal g = qMin(m_source.range(), m_target.range());
60 qreal k = qMax(m_source.range(), m_target.range());
61 qreal d = t > 0.5 ? m_source.range() - g : m_target.range() - g;
62 qreal c = d * 2 * qAbs(t - 0.5);
63 qreal h = qMin(1000 * 3000.0, totalDistance / 2.0);
67 qreal a = -h / ((qreal)(0.25 * jumpDuration * jumpDuration));
68 qreal b = 2.0 * h / (qreal)(0.5 * jumpDuration);
70 qreal x = jumpDuration * t;
71 qreal y = (a * x + b) * x + k - c;
75 qWarning(
"Unhandled FlyTo mode, no camera distance interpolation.");
76 return m_target.range();
81MarblePhysics::MarblePhysics(MarbleAbstractPresenter *presenter)
83 , d(new MarblePhysicsPrivate(presenter))
89MarblePhysics::~MarblePhysics()
94void MarblePhysics::flyTo(
const GeoDataLookAt &target, FlyToMode mode)
97 d->m_source = d->m_presenter->lookAt();
99 const ViewportParams *viewport = d->m_presenter->viewport();
101 FlyToMode effectiveMode = mode;
103 bool globeHidesPoint(
false);
104 bool onScreen = viewport->screenCoordinates(target.coordinates(), x, y, globeHidesPoint);
105 bool invisible = globeHidesPoint || !onScreen;
107 if (effectiveMode == Automatic) {
108 bool zoom = qAbs(d->m_source.range() - target.range()) > 10;
110 if ((invisible || zoom)) {
111 effectiveMode =
Jump;
117 d->m_mode = effectiveMode;
119 switch (effectiveMode) {
121 d->m_presenter->flyTo(target, Instant);
124 d->m_timeline.setDuration(300);
128 qreal duration = invisible ? 2000 : 1000;
129 d->m_timeline.setDuration(duration);
137 d->m_timeline.start();
140void MarblePhysics::updateProgress(qreal progress)
142 Q_ASSERT(d->m_mode != Instant);
143 Q_ASSERT(d->m_mode != Automatic);
145 if (progress >= 1.0) {
146 d->m_presenter->flyTo(d->m_target, Instant);
151 Q_ASSERT(progress >= 0.0 && progress < 1.0);
152 const GeoDataCoordinates interpolated = d->m_source.coordinates().interpolate(d->m_target.coordinates(), progress);
153 qreal range = d->suggestedRange(progress);
155 GeoDataLookAt intermediate;
156 intermediate.setCoordinates(interpolated);
157 intermediate.setRange(range);
160 d->m_presenter->flyTo(intermediate, Instant);
163void MarblePhysics::startStillMode()
170#include "moc_MarblePhysics.cpp"
This file contains the headers for ViewportParams.
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
Binds a QML item to a specific geodetic location in screen coordinates.
@ Automatic
A sane value is chosen automatically depending on animation settings and the action.
@ Instant
Change camera position immediately (no interpolation)
@ Linear
Linear interpolation of lon, lat and distance to ground.
@ Jump
Linear interpolation of lon and lat, distance increases towards the middle point, then decreases.
@ Animation
animated view (e.g. while rotating the globe)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setDuration(int duration)
void setEasingCurve(const QEasingCurve &curve)
void valueChanged(qreal value)