• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
MarblePhysics.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2008 Torsten Rahn <rahn@kde.org>
9 //
10 
11 #include "MarblePhysics.h"
12 
13 #include "Quaternion.h"
14 #include "MarbleAbstractPresenter.h"
15 #include "MarbleDebug.h"
16 #include "GeoDataLineString.h"
17 #include "ViewportParams.h"
18 
19 #include <QTimeLine>
20 
21 namespace Marble
22 {
23 
24 class MarblePhysicsPrivate {
25 public:
26  MarbleAbstractPresenter *const m_presenter;
27 
28  GeoDataLookAt m_source;
29 
30  GeoDataLookAt m_target;
31 
32  FlyToMode m_mode;
33 
34  QTimeLine m_timeline;
35 
36  qreal m_planetRadius;
37 
38  MarblePhysicsPrivate( MarbleAbstractPresenter *presenter )
39  : m_presenter( presenter ),
40  m_mode( Instant ),
41  m_planetRadius( EARTH_RADIUS )
42  {
43  m_timeline.setDuration(2000);
44  m_timeline.setCurveShape( QTimeLine::EaseInOutCurve );
45  }
46 
47  void suggestedPos(qreal t, qreal &lon, qreal &lat) const
48  {
49  Q_ASSERT( 0 <= t && t <= 1.0 );
50 
51  GeoDataCoordinates sourcePosition(m_source.longitude(), m_source.latitude());
52  GeoDataCoordinates targetPosition(m_target.longitude(), m_target.latitude());
53 
54  // Spherical interpolation for current position between source position
55  // and target position. We can't use Nlerp here, as the "t-velocity" needs to be constant.
56  const Quaternion itpos = Quaternion::slerp( sourcePosition.quaternion(), targetPosition.quaternion(), t );
57  itpos.getSpherical( lon, lat );
58  }
59 
60  qreal totalDistance() const
61  {
62  GeoDataLineString measure;
63  GeoDataCoordinates sourcePosition(m_source.longitude(), m_source.latitude());
64  GeoDataCoordinates targetPosition(m_target.longitude(), m_target.latitude());
65  measure << sourcePosition << targetPosition;
66  return measure.length(m_planetRadius);
67  }
68 
69  qreal suggestedRange(qreal t) const
70  {
71  Q_ASSERT( m_mode == Linear || m_mode == Jump);
72  Q_ASSERT( 0 <= t && t <= 1.0 );
73 
74  if (m_mode == Linear) {
75  qreal in = m_source.range();
76  qreal out = m_target.range();
77 
78  return in + t * (out-in);
79  }
80  else if (m_mode == Jump) {
81  qreal jumpDuration = m_timeline.duration();
82 
83  // Purely cinematic approach to calculate the jump path
84  qreal g = qMin(m_source.range(), m_target.range()); // Min altitude
85  qreal k = qMax(m_source.range(), m_target.range()); // Base altitude
86  qreal d = t > 0.5 ? m_source.range() - g : m_target.range() - g; // Base difference
87  qreal c = d * 2 * qAbs(t - 0.5); // Correction factor
88  qreal h = qMin(1000*3000.0, totalDistance() / 2.0); // Jump height
89 
90  // Parameters for the parabolic function that has the maximum at
91  // the point H ( 0.5 * m_jumpDuration, g + h )
92  qreal a = - h / ( (qreal)( 0.25 * jumpDuration * jumpDuration ) );
93  qreal b = 2.0 * h / (qreal)( 0.5 * jumpDuration );
94 
95  qreal x = jumpDuration * t;
96  qreal y = ( a * x + b ) * x + k - c; // Parabolic function
97 
98  return y;
99  }
100  else {
101  qWarning("Unhandled FlyTo mode, no camera distance interpolation.");
102  return m_target.range();
103  }
104  }
105 };
106 
107 
108 MarblePhysics::MarblePhysics( MarbleAbstractPresenter *presenter )
109  : QObject( presenter ),
110  d( new MarblePhysicsPrivate( presenter ) )
111 {
112  connect( &d->m_timeline, SIGNAL(valueChanged(qreal)),
113  this, SLOT(updateProgress(qreal)) );
114  connect( &d->m_timeline, SIGNAL(finished()),
115  this, SLOT(startStillMode()) );
116 }
117 
118 MarblePhysics::~MarblePhysics()
119 {
120  delete d;
121 }
122 
123 void MarblePhysics::flyTo( const GeoDataLookAt &target, FlyToMode mode )
124 {
125  d->m_timeline.stop();
126  d->m_source = d->m_presenter->lookAt();
127  d->m_target = target;
128  const ViewportParams *viewport = d->m_presenter->viewport();
129 
130  FlyToMode effectiveMode = mode;
131  qreal x(0), y(0);
132  bool globeHidesPoint(false);
133  bool onScreen = viewport->screenCoordinates( target.coordinates(), x, y,
134  globeHidesPoint );
135  bool invisible = globeHidesPoint || !onScreen;
136 
137  if (effectiveMode == Automatic)
138  {
139  bool zoom = qAbs(d->m_source.range()-target.range()) > 10;
140 
141  if ( (invisible || zoom) ) {
142  effectiveMode = Jump;
143  } else {
144  effectiveMode = Linear;
145  }
146  }
147 
148  d->m_mode = effectiveMode;
149 
150  switch(effectiveMode)
151  {
152  case Instant:
153  d->m_presenter->flyTo( target, Instant );
154  return;
155  break;
156  case Linear:
157  d->m_timeline.setDuration(300);
158  d->m_timeline.setCurveShape( QTimeLine::EaseOutCurve );
159  break;
160  case Jump:
161  {
162  qreal duration = invisible ? 2000 : 1000;
163  d->m_timeline.setDuration(duration);
164  d->m_timeline.setCurveShape( QTimeLine::EaseInOutCurve );
165  }
166  break;
167  case Automatic:
168  Q_ASSERT(false);
169  break;
170  }
171 
172  d->m_timeline.start();
173 }
174 
175 void MarblePhysics::updateProgress(qreal progress)
176 {
177  Q_ASSERT(d->m_mode != Instant);
178  Q_ASSERT(d->m_mode != Automatic);
179 
180  if (progress >= 1.0)
181  {
182  d->m_presenter->flyTo( d->m_target, Instant );
183  d->m_presenter->setViewContext( Marble::Still );
184  return;
185  }
186 
187  Q_ASSERT(progress >= 0.0 && progress < 1.0);
188  qreal lon(0.0), lat(0.0);
189  d->suggestedPos(progress, lon, lat);
190  qreal range = d->suggestedRange(progress);
191 
192  GeoDataLookAt intermediate;
193  intermediate.setLongitude(lon, GeoDataCoordinates::Radian);
194  intermediate.setLatitude(lat, GeoDataCoordinates::Radian);
195  intermediate.setAltitude(0.0);
196  intermediate.setRange(range);
197 
198  d->m_presenter->setViewContext( Marble::Animation );
199  d->m_presenter->flyTo( intermediate, Instant );
200 }
201 
202 void MarblePhysics::startStillMode()
203 {
204  d->m_presenter->setViewContext( Marble::Still );
205 }
206 
207 }
208 
209 #include "MarblePhysics.moc"
Quaternion.h
Marble::Automatic
A sane value is chosen automatically depending on animation settings and the action.
Definition: MarbleGlobal.h:174
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
Marble::MarblePhysics::flyTo
void flyTo(const GeoDataLookAt &target, FlyToMode mode=Instant)
Initiate an animation to the target according to the given mode.
Definition: MarblePhysics.cpp:123
Marble::Jump
Linear interpolation of lon and lat, distance increases towards the middle point, then decreases...
Definition: MarbleGlobal.h:177
MarbleDebug.h
Marble::GeoDataLookAt::range
qreal range() const
Retrieve the distance (in meters) between the camera and the object looked at.
Definition: GeoDataLookAt.cpp:120
Marble::MarblePhysics::~MarblePhysics
~MarblePhysics()
Destructor.
Definition: MarblePhysics.cpp:118
Marble::Animation
animated view (e.g. while rotating the globe)
Definition: MarbleGlobal.h:76
Marble::EARTH_RADIUS
const qreal EARTH_RADIUS
Definition: MarbleGlobal.h:257
Marble::Quaternion::slerp
static Quaternion slerp(const Quaternion &q1, const Quaternion &q2, qreal t)
Definition: Quaternion.cpp:201
QObject
Marble::Still
still image
Definition: MarbleGlobal.h:75
GeoDataLineString.h
Marble::ViewportParams::screenCoordinates
bool screenCoordinates(const qreal lon, const qreal lat, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the map.
Definition: ViewportParams.cpp:357
MarbleAbstractPresenter.h
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
ViewportParams.h
This file contains the headers for ViewportParams.
Marble::GeoDataLookAt
Definition: GeoDataLookAt.h:23
Marble::FlyToMode
FlyToMode
Describes possible flight mode (interpolation between source and target camera positions) ...
Definition: MarbleGlobal.h:173
Marble::MarblePhysics::MarblePhysics
MarblePhysics(MarbleAbstractPresenter *presenter)
Constructor.
Definition: MarblePhysics.cpp:108
Marble::MarbleAbstractPresenter
Definition: MarbleAbstractPresenter.h:26
QTimeLine
Marble::Instant
Change camera position immediately (no interpolation)
Definition: MarbleGlobal.h:175
Marble::Quaternion::getSpherical
void getSpherical(qreal &lon, qreal &lat) const
Definition: Quaternion.cpp:48
Marble::GeoDataLookAt::coordinates
GeoDataCoordinates coordinates() const
retrieve the lat/lon/alt triple as a GeoDataCoordinates object
Definition: GeoDataLookAt.cpp:109
MarblePhysics.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Marble::Linear
Linear interpolation of lon, lat and distance to ground.
Definition: MarbleGlobal.h:176
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal