6 #include "MarblePhysics.h"
8 #include "Quaternion.h"
9 #include "MarbleAbstractPresenter.h"
10 #include "GeoDataLookAt.h"
11 #include "MarbleDebug.h"
12 #include "GeoDataLineString.h"
20 class MarblePhysicsPrivate {
22 MarbleAbstractPresenter *
const m_presenter;
24 GeoDataLookAt m_source;
26 GeoDataLookAt m_target;
34 explicit MarblePhysicsPrivate( MarbleAbstractPresenter *presenter )
35 : m_presenter( presenter ),
37 m_planetRadius( EARTH_RADIUS )
43 qreal suggestedRange(qreal t)
const
46 Q_ASSERT( 0 <= t && t <= 1.0 );
49 qreal in = m_source.range();
50 qreal out = m_target.range();
52 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;
76 qWarning(
"Unhandled FlyTo mode, no camera distance interpolation.");
77 return m_target.range();
83 MarblePhysics::MarblePhysics( MarbleAbstractPresenter *presenter )
85 d( new MarblePhysicsPrivate( presenter ) )
87 connect( &d->m_timeline, SIGNAL(valueChanged(qreal)),
88 this, SLOT(updateProgress(qreal)) );
89 connect( &d->m_timeline, SIGNAL(finished()),
90 this, SLOT(startStillMode()) );
93 MarblePhysics::~MarblePhysics()
98 void MarblePhysics::flyTo(
const GeoDataLookAt &target,
FlyToMode mode )
100 d->m_timeline.stop();
101 d->m_source = d->m_presenter->lookAt();
102 d->m_target = target;
103 const ViewportParams *viewport = d->m_presenter->viewport();
107 bool globeHidesPoint(
false);
108 bool onScreen = viewport->screenCoordinates( target.coordinates(), x, y,
110 bool invisible = globeHidesPoint || !onScreen;
114 bool zoom = qAbs(d->m_source.range()-target.range()) > 10;
116 if ( (invisible || zoom) ) {
117 effectiveMode =
Jump;
123 d->m_mode = effectiveMode;
125 switch(effectiveMode)
128 d->m_presenter->flyTo( target,
Instant );
131 d->m_timeline.setDuration(300);
136 qreal duration = invisible ? 2000 : 1000;
137 d->m_timeline.setDuration(duration);
146 d->m_timeline.start();
149 void MarblePhysics::updateProgress(qreal progress)
151 Q_ASSERT(d->m_mode !=
Instant);
156 d->m_presenter->flyTo( d->m_target,
Instant );
161 Q_ASSERT(progress >= 0.0 && progress < 1.0);
162 const GeoDataCoordinates interpolated = d->m_source.coordinates().interpolate(d->m_target.coordinates(), progress);
163 qreal range = d->suggestedRange(progress);
165 GeoDataLookAt intermediate;
166 intermediate.setCoordinates(interpolated);
167 intermediate.setRange(range);
170 d->m_presenter->flyTo( intermediate,
Instant );
173 void MarblePhysics::startStillMode()
180 #include "moc_MarblePhysics.cpp"