8#include "AutoNavigation.h"
10#include "GeoDataCoordinates.h"
11#include "PositionTracking.h"
12#include "MarbleDebug.h"
15#include "RoutingManager.h"
16#include "RoutingModel.h"
27class Q_DECL_HIDDEN AutoNavigation::Private
31 AutoNavigation *
const m_parent;
32 const MarbleModel *
const m_model;
33 const ViewportParams *
const m_viewport;
34 const PositionTracking *
const m_tracking;
35 AutoNavigation::CenterMode m_recenterMode;
37 QTimer m_lastWidgetInteraction;
38 bool m_selfInteraction;
41 Private( MarbleModel *model,
const ViewportParams *viewport, AutoNavigation *parent );
48 void moveOnBorderToCenter(
const GeoDataCoordinates &position, qreal speed );
55 GeoDataCoordinates findIntersection( qreal currentX, qreal currentY )
const;
61 void adjustZoom(
const GeoDataCoordinates ¤tPosition, qreal speed );
66 void centerOn(
const GeoDataCoordinates &position );
69AutoNavigation::Private::Private( MarbleModel *model,
const ViewportParams *viewport, AutoNavigation *parent ) :
72 m_viewport( viewport ),
73 m_tracking( model->positionTracking() ),
74 m_recenterMode( AutoNavigation::DontRecenter ),
76 m_selfInteraction( false )
78 m_lastWidgetInteraction.setInterval( 10 * 1000 );
79 m_lastWidgetInteraction.setSingleShot(
true );
82void AutoNavigation::Private::moveOnBorderToCenter(
const GeoDataCoordinates &position, qreal )
87 if(!( m_viewport->screenCoordinates( position, x, y ) ) ) {
90 qreal centerLon = m_viewport->centerLongitude();
91 qreal centerLat = m_viewport->centerLatitude();
96 m_viewport->screenCoordinates( centerLon, centerLat, centerX, centerY );
98 const qreal borderRatio = 0.25;
100 int shiftX = qRound( centerX * borderRatio );
101 int shiftY = qRound( centerY * borderRatio );
103 QRect recenterBorderBound;
104 recenterBorderBound.
setCoords( centerX-shiftX, centerY-shiftY, centerX+shiftX, centerY+shiftY );
106 if( !recenterBorderBound.
contains( x,y ) ) {
107 centerOn( position );
111GeoDataCoordinates AutoNavigation::Private::findIntersection( qreal currentX, qreal currentY )
const
113 qreal direction = m_tracking->direction();
114 if ( direction >= 360 ) {
115 direction = fmod( direction,360.0 );
118 const qreal width = m_viewport->width();
119 const qreal height = m_viewport->height();
126 bool crossHorizontal =
false;
127 bool crossVertical =
false;
130 if( 0 < direction && direction < 90 ) {
131 const qreal angle = direction * DEG2RAD;
134 intercept.
setX( width - currentX );
135 intercept.
setY( intercept.
x() / tan( angle ) );
136 destinationVertical.
setX( width );
137 destinationVertical.
setY( currentY-intercept.
y() );
140 intercept.
setY( currentY );
141 intercept.
setX( intercept.
y() * tan( angle ) );
142 destinationHorizontal.
setX( currentX + intercept.
x() );
143 destinationHorizontal.
setY( 0 );
145 if ( destinationVertical.
y() < 0 ) {
146 crossHorizontal =
true;
148 else if( destinationHorizontal.
x() > width ) {
149 crossVertical =
true;
153 else if( 270 < direction && direction < 360 ) {
154 const qreal angle = (direction - 270) * DEG2RAD;
157 intercept.
setY( currentY );
158 intercept.
setX( intercept.
y() / tan( angle ) );
159 destinationHorizontal.
setX( currentX - intercept.
x() );
160 destinationHorizontal.
setY( 0 );
163 intercept.
setX( currentX );
164 intercept.
setY( intercept.
x() * tan( angle ) );
165 destinationVertical.
setY( currentY - intercept.
y() );
166 destinationVertical.
setX( 0 );
168 if( destinationHorizontal.
x() > width ) {
169 crossVertical =
true;
171 else if( destinationVertical.
y() < 0 ) {
172 crossHorizontal =
true;
176 else if( 180 < direction && direction < 270 ) {
177 const qreal angle = (direction - 180) * DEG2RAD;
180 intercept.
setX( currentX );
181 intercept.
setY( intercept.
x() / tan( angle ) );
182 destinationVertical.
setY( currentY + intercept.
y() );
183 destinationVertical.
setX( 0 );
186 intercept.
setY( currentY );
187 intercept.
setX( intercept.
y() * tan( angle ) );
188 destinationHorizontal.
setX( currentX - intercept.
x() );
189 destinationHorizontal.
setY( height );
191 if ( destinationVertical.
y() > height ) {
192 crossHorizontal =
true;
194 else if ( destinationHorizontal.
x() < 0 ) {
195 crossVertical =
true;
199 else if( 90 < direction && direction < 180 ) {
200 const qreal angle = (direction - 90) * DEG2RAD;
203 intercept.
setY( height - currentY );
204 intercept.
setX( intercept.
y() / tan( angle ) );
205 destinationHorizontal.
setX( currentX + intercept.
x() );
206 destinationHorizontal.
setY( height );
209 intercept.
setX( width - currentX );
210 intercept.
setY( intercept.
x() * tan( angle ) );
211 destinationVertical.
setX( width );
212 destinationVertical.
setY( currentY + intercept.
y() );
214 if ( destinationHorizontal.
x() > width ) {
215 crossVertical =
true;
217 else if( destinationVertical.
y() > height ) {
218 crossHorizontal =
true;
222 else if( direction == 0 ) {
223 destinationHorizontal.
setX( currentX );
224 destinationHorizontal.
setY( 0 );
225 crossHorizontal =
true;
227 else if( direction == 90 ) {
228 destinationVertical.
setX( width );
229 destinationVertical.
setY( currentY );
230 crossVertical =
true;
232 else if( direction == 180 ) {
233 destinationHorizontal.
setX( currentX );
234 destinationHorizontal.
setY( height );
235 crossHorizontal =
true;
237 else if( direction == 270 ) {
238 destinationVertical.
setX( 0 );
239 destinationVertical.
setY( currentY );
240 crossVertical =
true;
243 if ( crossHorizontal ==
true && crossVertical ==
false ) {
244 destination.
setX( destinationHorizontal.
x() );
245 destination.
setY( destinationHorizontal.
y() );
247 else if ( crossVertical ==
true && crossHorizontal ==
false ) {
248 destination.
setX( destinationVertical.
x() );
249 destination.
setY( destinationVertical.
y() );
252 qreal destinationLon = 0.0;
253 qreal destinationLat = 0.0;
254 m_viewport->geoCoordinates( destination.
x(), destination.
y(), destinationLon, destinationLat,
255 GeoDataCoordinates::Radian );
256 GeoDataCoordinates destinationCoord( destinationLon, destinationLat, GeoDataCoordinates::Radian );
258 return destinationCoord;
261void AutoNavigation::Private::adjustZoom(
const GeoDataCoordinates ¤tPosition, qreal speed )
265 if( !m_viewport->screenCoordinates(currentPosition, currentX, currentY ) ) {
269 const GeoDataCoordinates destination = findIntersection( currentX, currentY );
271 const qreal greatCircleDistance = currentPosition.sphericalDistanceTo(destination);
272 qreal radius = m_model->planetRadius();
273 qreal
distance = greatCircleDistance * radius;
277 qreal remainingTime =
distance / speed;
280 qreal thresholdLow = 15;
281 qreal thresholdHigh = 120;
283 m_selfInteraction =
true;
284 if ( remainingTime < thresholdLow ) {
285 emit m_parent->zoomOut( Instant );
287 else if ( remainingTime > thresholdHigh ) {
288 emit m_parent->zoomIn( Instant );
290 m_selfInteraction =
false;
294void AutoNavigation::Private::centerOn(
const GeoDataCoordinates &position )
296 m_selfInteraction =
true;
297 RoutingManager
const * routingManager = m_model->routingManager();
298 RoutingModel
const * routingModel = routingManager->routingModel();
299 if (!routingManager->guidanceModeEnabled() || routingModel->deviatedFromRoute()){
300 emit m_parent->centerOn( position,
false );
302 GeoDataCoordinates positionOnRoute = routingModel->route().positionOnRoute();
303 emit m_parent->centerOn( positionOnRoute,
false );
305 m_selfInteraction =
false;
308AutoNavigation::AutoNavigation( MarbleModel *model,
const ViewportParams *viewport,
QObject *parent ) :
310 d( new AutoNavigation::Private( model, viewport, this ) )
312 connect( d->m_tracking, SIGNAL(gpsLocation(GeoDataCoordinates,qreal)),
313 this, SLOT(adjust(GeoDataCoordinates,qreal)) );
316AutoNavigation::~AutoNavigation()
321void AutoNavigation::adjust(
const GeoDataCoordinates &position, qreal speed )
323 if ( d->m_lastWidgetInteraction.isActive() ) {
327 switch( d->m_recenterMode ) {
332 d->centerOn( position );
334 case RecenterOnBorder:
335 d->moveOnBorderToCenter( position, speed );
339 if ( d->m_adjustZoom ) {
340 switch( d->m_recenterMode ) {
345 case RecenterOnBorder:
346 d->adjustZoom( position, speed );
352void AutoNavigation::setAutoZoom(
bool autoZoom )
354 d->m_adjustZoom = autoZoom;
355 emit autoZoomToggled( autoZoom );
358void AutoNavigation::setRecenter( CenterMode recenterMode )
360 d->m_recenterMode = recenterMode;
361 emit recenterModeChanged( recenterMode );
364void AutoNavigation::inhibitAutoAdjustments()
366 if ( !d->m_selfInteraction ) {
367 d->m_lastWidgetInteraction.start();
371AutoNavigation::CenterMode AutoNavigation::recenterMode()
const
373 return d->m_recenterMode;
376bool AutoNavigation::autoZoom()
const
378 return d->m_adjustZoom;
383#include "moc_AutoNavigation.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for ViewportParams.
Binds a QML item to a specific geodetic location in screen coordinates.
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
bool contains(const QPoint &point, bool proper) const const
void setCoords(int x1, int y1, int x2, int y2)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)