7#include "AutoNavigation.h" 
    9#include "GeoDataCoordinates.h" 
   10#include "MarbleDebug.h" 
   12#include "PositionTracking.h" 
   14#include "RoutingManager.h" 
   15#include "RoutingModel.h" 
   27class Q_DECL_HIDDEN AutoNavigation::Private
 
   30    AutoNavigation *
const m_parent;
 
   31    const MarbleModel *
const m_model;
 
   32    const ViewportParams *
const m_viewport;
 
   33    const PositionTracking *
const m_tracking;
 
   34    AutoNavigation::CenterMode m_recenterMode;
 
   36    QTimer m_lastWidgetInteraction;
 
   37    bool m_selfInteraction;
 
   40    Private(MarbleModel *model, 
const ViewportParams *viewport, AutoNavigation *parent);
 
   47    void moveOnBorderToCenter(
const GeoDataCoordinates &position, qreal speed);
 
   54    GeoDataCoordinates findIntersection(qreal currentX, qreal currentY) 
const;
 
   60    void adjustZoom(
const GeoDataCoordinates ¤tPosition, qreal speed);
 
   65    void centerOn(
const GeoDataCoordinates &position);
 
   71    , m_viewport(viewport)
 
   72    , m_tracking(model->positionTracking())
 
   73    , m_recenterMode(AutoNavigation::DontRecenter)
 
   75    , m_selfInteraction(false)
 
   77    m_lastWidgetInteraction.setInterval(10 * 1000);
 
   78    m_lastWidgetInteraction.setSingleShot(
true);
 
   81void AutoNavigation::Private::moveOnBorderToCenter(
const GeoDataCoordinates &position, qreal)
 
   86    if (!(m_viewport->screenCoordinates(position, x, y))) {
 
   89    qreal centerLon = m_viewport->centerLongitude();
 
   90    qreal centerLat = m_viewport->centerLatitude();
 
   95    m_viewport->screenCoordinates(centerLon, centerLat, centerX, centerY);
 
   97    const qreal borderRatio = 0.25;
 
   99    int shiftX = qRound(centerX * borderRatio);
 
  100    int shiftY = qRound(centerY * borderRatio);
 
  102    QRect recenterBorderBound;
 
  103    recenterBorderBound.
setCoords(centerX - shiftX, centerY - shiftY, centerX + shiftX, centerY + shiftY);
 
  105    if (!recenterBorderBound.
contains(x, y)) {
 
  110GeoDataCoordinates AutoNavigation::Private::findIntersection(qreal currentX, qreal currentY)
 const 
  112    qreal direction = m_tracking->direction();
 
  113    if (direction >= 360) {
 
  114        direction = fmod(direction, 360.0);
 
  117    const qreal width = m_viewport->width();
 
  118    const qreal height = m_viewport->height();
 
  125    bool crossHorizontal = 
false;
 
  126    bool crossVertical = 
false;
 
  129    if (0 < direction && direction < 90) {
 
  130        const qreal angle = direction * DEG2RAD;
 
  133        intercept.
setX(width - currentX);
 
  134        intercept.
setY(intercept.
x() / tan(angle));
 
  135        destinationVertical.
setX(width);
 
  136        destinationVertical.
setY(currentY - intercept.
y());
 
  139        intercept.
setY(currentY);
 
  140        intercept.
setX(intercept.
y() * tan(angle));
 
  141        destinationHorizontal.
setX(currentX + intercept.
x());
 
  142        destinationHorizontal.
setY(0);
 
  144        if (destinationVertical.
y() < 0) {
 
  145            crossHorizontal = 
true;
 
  146        } 
else if (destinationHorizontal.
x() > width) {
 
  147            crossVertical = 
true;
 
  150    } 
else if (270 < direction && direction < 360) {
 
  151        const qreal angle = (direction - 270) * DEG2RAD;
 
  154        intercept.
setY(currentY);
 
  155        intercept.
setX(intercept.
y() / tan(angle));
 
  156        destinationHorizontal.
setX(currentX - intercept.
x());
 
  157        destinationHorizontal.
setY(0);
 
  160        intercept.
setX(currentX);
 
  161        intercept.
setY(intercept.
x() * tan(angle));
 
  162        destinationVertical.
setY(currentY - intercept.
y());
 
  163        destinationVertical.
setX(0);
 
  165        if (destinationHorizontal.
x() > width) {
 
  166            crossVertical = 
true;
 
  167        } 
else if (destinationVertical.
y() < 0) {
 
  168            crossHorizontal = 
true;
 
  171    } 
else if (180 < direction && direction < 270) {
 
  172        const qreal angle = (direction - 180) * DEG2RAD;
 
  175        intercept.
setX(currentX);
 
  176        intercept.
setY(intercept.
x() / tan(angle));
 
  177        destinationVertical.
setY(currentY + intercept.
y());
 
  178        destinationVertical.
setX(0);
 
  181        intercept.
setY(currentY);
 
  182        intercept.
setX(intercept.
y() * tan(angle));
 
  183        destinationHorizontal.
setX(currentX - intercept.
x());
 
  184        destinationHorizontal.
setY(height);
 
  186        if (destinationVertical.
y() > height) {
 
  187            crossHorizontal = 
true;
 
  188        } 
else if (destinationHorizontal.
x() < 0) {
 
  189            crossVertical = 
true;
 
  192    } 
else if (90 < direction && direction < 180) {
 
  193        const qreal angle = (direction - 90) * DEG2RAD;
 
  196        intercept.
setY(height - currentY);
 
  197        intercept.
setX(intercept.
y() / tan(angle));
 
  198        destinationHorizontal.
setX(currentX + intercept.
x());
 
  199        destinationHorizontal.
setY(height);
 
  202        intercept.
setX(width - currentX);
 
  203        intercept.
setY(intercept.
x() * tan(angle));
 
  204        destinationVertical.
setX(width);
 
  205        destinationVertical.
setY(currentY + intercept.
y());
 
  207        if (destinationHorizontal.
x() > width) {
 
  208            crossVertical = 
true;
 
  209        } 
else if (destinationVertical.
y() > height) {
 
  210            crossHorizontal = 
true;
 
  213    } 
else if (direction == 0) {
 
  214        destinationHorizontal.
setX(currentX);
 
  215        destinationHorizontal.
setY(0);
 
  216        crossHorizontal = 
true;
 
  217    } 
else if (direction == 90) {
 
  218        destinationVertical.
setX(width);
 
  219        destinationVertical.
setY(currentY);
 
  220        crossVertical = 
true;
 
  221    } 
else if (direction == 180) {
 
  222        destinationHorizontal.
setX(currentX);
 
  223        destinationHorizontal.
setY(height);
 
  224        crossHorizontal = 
true;
 
  225    } 
else if (direction == 270) {
 
  226        destinationVertical.
setX(0);
 
  227        destinationVertical.
setY(currentY);
 
  228        crossVertical = 
true;
 
  231    if (crossHorizontal == 
true && crossVertical == 
false) {
 
  232        destination.
setX(destinationHorizontal.
x());
 
  233        destination.
setY(destinationHorizontal.
y());
 
  234    } 
else if (crossVertical == 
true && crossHorizontal == 
false) {
 
  235        destination.
setX(destinationVertical.
x());
 
  236        destination.
setY(destinationVertical.
y());
 
  239    qreal destinationLon = 0.0;
 
  240    qreal destinationLat = 0.0;
 
  241    m_viewport->geoCoordinates(destination.
x(), destination.
y(), destinationLon, destinationLat, GeoDataCoordinates::Radian);
 
  242    GeoDataCoordinates destinationCoord(destinationLon, destinationLat, GeoDataCoordinates::Radian);
 
  244    return destinationCoord;
 
  247void AutoNavigation::Private::adjustZoom(
const GeoDataCoordinates ¤tPosition, qreal speed)
 
  251    if (!m_viewport->screenCoordinates(currentPosition, currentX, currentY)) {
 
  258    qreal radius = m_model->planetRadius();
 
  259    qreal 
distance = greatCircleDistance * radius;
 
  263        qreal remainingTime = 
distance / speed;
 
  266        qreal thresholdLow = 15;
 
  267        qreal thresholdHigh = 120;
 
  269        m_selfInteraction = 
true;
 
  270        if (remainingTime < thresholdLow) {
 
  271            Q_EMIT m_parent->zoomOut(Instant);
 
  272        } 
else if (remainingTime > thresholdHigh) {
 
  273            Q_EMIT m_parent->zoomIn(Instant);
 
  275        m_selfInteraction = 
false;
 
  281    m_selfInteraction = 
true;
 
  282    RoutingManager 
const *routingManager = m_model->routingManager();
 
  283    RoutingModel 
const *routingModel = routingManager->routingModel();
 
  284    if (!routingManager->guidanceModeEnabled() || routingModel->deviatedFromRoute()) {
 
  285        Q_EMIT m_parent->centerOn(position, 
false);
 
  288        Q_EMIT m_parent->centerOn(positionOnRoute, 
false);
 
  290    m_selfInteraction = 
false;
 
  293AutoNavigation::AutoNavigation(MarbleModel *model, 
const ViewportParams *viewport, 
QObject *parent)
 
  295    , d(new AutoNavigation::Private(model, viewport, this))
 
  297    connect(d->m_tracking, &PositionTracking::gpsLocation, 
this, &AutoNavigation::adjust);
 
  300AutoNavigation::~AutoNavigation()
 
  307    if (d->m_lastWidgetInteraction.isActive()) {
 
  311    switch (d->m_recenterMode) {
 
  316        d->centerOn(position);
 
  318    case RecenterOnBorder:
 
  319        d->moveOnBorderToCenter(position, speed);
 
  323    if (d->m_adjustZoom) {
 
  324        switch (d->m_recenterMode) {
 
  329        case RecenterOnBorder: 
 
  330            d->adjustZoom(position, speed);
 
  336void AutoNavigation::setAutoZoom(
bool autoZoom)
 
  338    d->m_adjustZoom = autoZoom;
 
  339    Q_EMIT autoZoomToggled(autoZoom);
 
  342void AutoNavigation::setRecenter(CenterMode recenterMode)
 
  344    d->m_recenterMode = recenterMode;
 
  345    Q_EMIT recenterModeChanged(recenterMode);
 
  348void AutoNavigation::inhibitAutoAdjustments()
 
  350    if (!d->m_selfInteraction) {
 
  351        d->m_lastWidgetInteraction.start();
 
  355AutoNavigation::CenterMode AutoNavigation::recenterMode()
 const 
  357    return d->m_recenterMode;
 
  360bool AutoNavigation::autoZoom()
 const 
  362    return d->m_adjustZoom;
 
  367#include "moc_AutoNavigation.cpp" 
This file contains the headers for MarbleModel.
 
This file contains the headers for ViewportParams.
 
A 3d point representation.
 
qreal sphericalDistanceTo(const GeoDataCoordinates &other) const
This method calculates the shortest distance between two points on a sphere.
 
The data model (not based on QAbstractModel) for a MarbleWidget.
 
A public class that controls what is visible in the viewport of a Marble map.
 
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)