8#include "AutoNavigation.h"
9#include "GeoDataAccuracy.h"
11#include "MarbleQuickItem.h"
13#include "PositionTracking.h"
15#include "routing/Route.h"
16#include "routing/RoutingManager.h"
17#include "routing/RoutingModel.h"
18#include "routing/VoiceNavigationModel.h"
23class NavigationPrivate
28 MarbleQuickItem *m_marbleQuickItem;
32 RouteSegment m_currentSegment;
34 AutoNavigation *m_autoNavigation;
36 VoiceNavigationModel m_voiceNavigation;
38 qreal m_nextInstructionDistance;
40 qreal m_destinationDistance;
42 double m_screenAccuracy;
45 RouteSegment nextRouteSegment()
const;
47 void updateNextInstructionDistance(
const Route &route);
49 MarbleModel *model()
const;
51 QPointF positionOnRoute()
const;
52 QPointF currentPosition()
const;
54 RouteSegment m_secondLastSegment;
55 RouteSegment m_lastSegment;
58NavigationPrivate::NavigationPrivate()
59 : m_marbleQuickItem(nullptr)
61 , m_autoNavigation(nullptr)
62 , m_nextInstructionDistance(0.0)
63 , m_destinationDistance(0.0)
69void NavigationPrivate::updateNextInstructionDistance(
const Route &route)
71 const GeoDataCoordinates position = route.position();
72 const GeoDataCoordinates interpolated = route.positionOnRoute();
73 const GeoDataCoordinates onRoute = route.currentWaypoint();
75 qreal planetRadius = 0;
77 planetRadius = model()->planet()->radius();
79 qreal
distance = planetRadius * (position.sphericalDistanceTo(interpolated) + interpolated.sphericalDistanceTo(onRoute));
80 qreal remaining = 0.0;
81 const RouteSegment &segment = route.currentSegment();
82 for (
int i = 0; i < segment.path().size(); ++i) {
83 if (segment.path()[i] == onRoute) {
84 distance += segment.path().length(planetRadius, i);
89 bool upcoming =
false;
90 for (
int i = 0; i < route.size(); ++i) {
91 const RouteSegment &segment = route.at(i);
94 remaining += segment.path().length(planetRadius);
97 if (segment == route.currentSegment()) {
102 m_nextInstructionDistance =
distance;
103 m_destinationDistance =
distance + remaining;
106MarbleModel *NavigationPrivate::model()
const
108 return m_marbleQuickItem ? m_marbleQuickItem->model() :
nullptr;
111RouteSegment NavigationPrivate::nextRouteSegment()
const
114 return m_marbleQuickItem ? model()->routingManager()->routingModel()->route().currentSegment().nextRouteSegment() : RouteSegment();
117Navigation::Navigation(
QObject *parent)
119 , d(new NavigationPrivate)
121 connect(&d->m_voiceNavigation, SIGNAL(instructionChanged()),
this, SIGNAL(voiceNavigationAnnouncementChanged()));
124Navigation::~Navigation()
129bool Navigation::guidanceModeEnabled()
const
131 return d->m_marbleQuickItem ? d->model()->routingManager()->guidanceModeEnabled() :
false;
134void Navigation::setGuidanceModeEnabled(
bool enabled)
136 if (d->m_marbleQuickItem) {
137 d->model()->routingManager()->setGuidanceModeEnabled(enabled);
138 d->m_autoNavigation->setAutoZoom(enabled);
139 d->m_autoNavigation->setRecenter(enabled ? AutoNavigation::RecenterOnBorder : AutoNavigation::DontRecenter);
141 if (enabled && !d->m_muted) {
147bool Navigation::muted()
const
152void Navigation::setMuted(
bool enabled)
154 d->m_muted = enabled;
157QString Navigation::nextInstructionText()
const
159 return d->nextRouteSegment().maneuver().instructionText();
162QString Navigation::nextRoad()
const
164 return d->nextRouteSegment().maneuver().roadName();
167QString Navigation::nextInstructionImage()
const
169 switch (d->nextRouteSegment().maneuver().direction()) {
170 case Maneuver::Continue:
171 return QStringLiteral(
"qrc:/marble/turn-continue.svg");
172 case Maneuver::Merge:
173 return QStringLiteral(
"qrc:/marble/turn-merge.svg");
174 case Maneuver::Straight:
175 return QStringLiteral(
"qrc:/marble/turn-continue.svg");
176 case Maneuver::SlightRight:
177 return QStringLiteral(
"qrc:/marble/turn-slight-right.svg");
178 case Maneuver::Right:
179 return QStringLiteral(
"qrc:/marble/turn-right.svg");
180 case Maneuver::SharpRight:
181 return QStringLiteral(
"qrc:/marble/turn-sharp-right.svg");
182 case Maneuver::TurnAround:
183 return QStringLiteral(
"qrc:/marble/turn-around.svg");
184 case Maneuver::SharpLeft:
185 return QStringLiteral(
"qrc:/marble/turn-sharp-left.svg");
187 return QStringLiteral(
"qrc:/marble/turn-left.svg");
188 case Maneuver::SlightLeft:
189 return QStringLiteral(
"qrc:/marble/turn-slight-left.svg");
190 case Maneuver::RoundaboutFirstExit:
191 return QStringLiteral(
"qrc:/marble/turn-roundabout-first.svg");
192 case Maneuver::RoundaboutSecondExit:
193 return QStringLiteral(
"qrc:/marble/turn-roundabout-second.svg");
194 case Maneuver::RoundaboutThirdExit:
195 return QStringLiteral(
"qrc:/marble/turn-roundabout-third.svg");
196 case Maneuver::RoundaboutExit:
197 return QStringLiteral(
"qrc:/marble/turn-roundabout-far.svg");
198 case Maneuver::ExitLeft:
199 return QStringLiteral(
"qrc:/marble/turn-exit-left.svg");
200 case Maneuver::ExitRight:
201 return QStringLiteral(
"qrc:/marble/turn-exit-right.svg");
202 case Maneuver::Unknown:
208qreal Navigation::nextInstructionDistance()
const
210 return d->m_nextInstructionDistance;
213qreal Navigation::destinationDistance()
const
215 return d->m_destinationDistance;
218QString Navigation::voiceNavigationAnnouncement()
const
220 return d->m_voiceNavigation.instruction();
223QString Navigation::speaker()
const
225 return d->m_voiceNavigation.speaker();
228void Navigation::setSpeaker(
const QString &speaker)
230 d->m_voiceNavigation.setSpeaker(speaker);
233bool Navigation::deviated()
const
235 if (d->m_marbleQuickItem) {
236 RoutingModel
const *routingModel = d->model()->routingManager()->routingModel();
237 return routingModel->deviatedFromRoute();
243MarbleQuickItem *Navigation::marbleQuickItem()
const
245 return d->m_marbleQuickItem;
248QPointF NavigationPrivate::positionOnRoute()
const
250 RoutingModel
const *routingModel = model()->routingManager()->routingModel();
251 GeoDataCoordinates coordinates = routingModel->route().positionOnRoute();
254 if (coordinates.isValid()) {
255 m_marbleQuickItem->map()->viewport()->screenCoordinates(coordinates, x, y);
260QPointF NavigationPrivate::currentPosition()
const
262 GeoDataCoordinates coordinates = model()->positionTracking()->currentLocation();
265 m_marbleQuickItem->map()->viewport()->screenCoordinates(coordinates, x, y);
269QPointF Navigation::screenPosition()
const
271 return d->m_screenPosition;
274double Navigation::screenAccuracy()
const
276 return d->m_screenAccuracy;
279void Navigation::setMarbleQuickItem(MarbleQuickItem *marbleQuickItem)
281 if (d->m_marbleQuickItem == marbleQuickItem) {
285 if (d->m_marbleQuickItem) {
286 disconnect(d->model()->routingManager()->routingModel(), SIGNAL(positionChanged()),
this, SLOT(
update()));
287 disconnect(d->m_autoNavigation, SIGNAL(
zoomIn(FlyToMode)), d->m_marbleQuickItem, SLOT(
zoomIn()));
288 disconnect(d->m_autoNavigation, SIGNAL(
zoomOut(FlyToMode)), d->m_marbleQuickItem, SLOT(
zoomOut()));
289 disconnect(d->m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,
bool)), d->m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)));
291 disconnect(d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()), d->m_autoNavigation, SLOT(inhibitAutoAdjustments()));
294 d->m_marbleQuickItem = marbleQuickItem;
295 if (d->m_marbleQuickItem) {
296 d->model()->routingManager()->setShowGuidanceModeStartupWarning(
false);
297 connect(d->model()->routingManager()->routingModel(), SIGNAL(positionChanged()),
this, SLOT(
update()));
298 connect(d->model()->routingManager()->routingModel(), SIGNAL(deviatedFromRoute(
bool)),
this, SIGNAL(deviationChanged()));
300 delete d->m_autoNavigation;
301 d->m_autoNavigation =
new AutoNavigation(d->model(), d->m_marbleQuickItem->map()->viewport(),
this);
302 connect(d->m_autoNavigation, SIGNAL(
zoomIn(FlyToMode)), d->m_marbleQuickItem, SLOT(
zoomIn()));
304 connect(d->m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,
bool)), d->m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)));
306 connect(d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()), d->m_autoNavigation, SLOT(inhibitAutoAdjustments()));
308 connect(d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
this, SLOT(updateScreenPosition()));
309 connect(d->model()->positionTracking(), SIGNAL(gpsLocation(GeoDataCoordinates, qreal)),
this, SLOT(updateScreenPosition()));
310 connect(d->model()->positionTracking(), SIGNAL(statusChanged(PositionProviderStatus)),
this, SLOT(updateScreenPosition()));
312 Q_EMIT marbleQuickItemChanged(marbleQuickItem);
315void Navigation::update()
321 RoutingModel
const *routingModel = d->model()->routingManager()->routingModel();
322 d->updateNextInstructionDistance(routingModel->route());
323 Q_EMIT nextInstructionDistanceChanged();
324 Q_EMIT destinationDistanceChanged();
325 RouteSegment segment = routingModel->route().currentSegment();
328 d->m_voiceNavigation.update(routingModel->route(), d->m_nextInstructionDistance, d->m_destinationDistance, routingModel->deviatedFromRoute());
330 if (segment != d->m_currentSegment) {
331 d->m_currentSegment = segment;
332 Q_EMIT nextInstructionTextChanged();
333 Q_EMIT nextInstructionImageChanged();
334 Q_EMIT nextRoadChanged();
337 updateScreenPosition();
340void Navigation::updateScreenPosition()
342 if (d->m_marbleQuickItem) {
343 double distanceMeter = d->model()->positionTracking()->accuracy().horizontal;
344 d->m_screenAccuracy = distanceMeter * d->m_marbleQuickItem->map()->radius() / d->model()->planetRadius();
345 Q_EMIT screenAccuracyChanged();
347 d->m_screenPosition = deviated() ? d->currentPosition() : d->positionOnRoute();
348 Q_EMIT screenPositionChanged();
354#include "moc_Navigation.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for ViewportParams.
void update(Part *part, const QByteArray &data, qint64 dataSize)
QAction * zoomIn(const QObject *recvr, const char *slot, QObject *parent)
QAction * zoomOut(const QObject *recvr, const char *slot, QObject *parent)
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)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)