6 #include "Navigation.h"
10 #include "MarbleQuickItem.h"
11 #include "routing/Route.h"
12 #include "routing/RoutingManager.h"
13 #include "routing/RoutingModel.h"
14 #include "PositionTracking.h"
15 #include "AutoNavigation.h"
16 #include "routing/VoiceNavigationModel.h"
18 #include "GeoDataAccuracy.h"
22 class NavigationPrivate
27 MarbleQuickItem * m_marbleQuickItem;
31 RouteSegment m_currentSegment;
33 AutoNavigation* m_autoNavigation;
35 VoiceNavigationModel m_voiceNavigation;
37 qreal m_nextInstructionDistance;
39 qreal m_destinationDistance;
41 double m_screenAccuracy;
44 RouteSegment nextRouteSegment()
const;
46 void updateNextInstructionDistance(
const Route &route );
48 MarbleModel * model()
const;
50 QPointF positionOnRoute()
const;
51 QPointF currentPosition()
const;
53 RouteSegment m_secondLastSegment;
54 RouteSegment m_lastSegment;
58 NavigationPrivate::NavigationPrivate() :
59 m_marbleQuickItem( nullptr ), m_muted( false ), m_autoNavigation( nullptr ), m_nextInstructionDistance( 0.0 ),
60 m_destinationDistance( 0.0 ), m_screenAccuracy(0)
65 void NavigationPrivate::updateNextInstructionDistance(
const Route &route )
67 const GeoDataCoordinates position = route.position();
68 const GeoDataCoordinates interpolated = route.positionOnRoute();
69 const GeoDataCoordinates onRoute = route.currentWaypoint();
71 qreal planetRadius = 0;
73 planetRadius = model()->planet()->radius();
75 qreal
distance = planetRadius * (position.sphericalDistanceTo(interpolated) + interpolated.sphericalDistanceTo(onRoute));
76 qreal remaining = 0.0;
77 const RouteSegment &segment = route.currentSegment();
78 for (
int i=0; i<segment.path().size(); ++i ) {
79 if ( segment.path()[i] == onRoute ) {
80 distance += segment.path().length( planetRadius, i );
85 bool upcoming =
false;
86 for (
int i=0; i<route.size(); ++i ) {
87 const RouteSegment &segment = route.at( i );
90 remaining += segment.path().length( planetRadius );
93 if ( segment == route.currentSegment() ) {
98 m_nextInstructionDistance =
distance;
99 m_destinationDistance =
distance + remaining;
102 MarbleModel * NavigationPrivate::model()
const
104 return m_marbleQuickItem ? m_marbleQuickItem->model() :
nullptr;
107 RouteSegment NavigationPrivate::nextRouteSegment()
const
110 return m_marbleQuickItem ? model()->routingManager()->routingModel()->route().currentSegment().nextRouteSegment() : RouteSegment();
113 Navigation::Navigation(
QObject* parent) :
114 QObject( parent ), d( new NavigationPrivate )
116 connect( &d->m_voiceNavigation, SIGNAL(instructionChanged()),
this, SIGNAL(voiceNavigationAnnouncementChanged()) );
119 Navigation::~Navigation()
125 bool Navigation::guidanceModeEnabled()
const
127 return d->m_marbleQuickItem ? d->model()->routingManager()->guidanceModeEnabled() :
false;
130 void Navigation::setGuidanceModeEnabled(
bool enabled )
132 if ( d->m_marbleQuickItem ) {
133 d->model()->routingManager()->setGuidanceModeEnabled( enabled );
134 d->m_autoNavigation->setAutoZoom( enabled );
135 d->m_autoNavigation->setRecenter( enabled ? AutoNavigation::RecenterOnBorder : AutoNavigation::DontRecenter );
137 if ( enabled && !d->m_muted ) {
143 bool Navigation::muted()
const
148 void Navigation::setMuted(
bool enabled)
150 d->m_muted = enabled;
153 QString Navigation::nextInstructionText()
const
155 return d->nextRouteSegment().maneuver().instructionText();
158 QString Navigation::nextRoad()
const
160 return d->nextRouteSegment().maneuver().roadName();
163 QString Navigation::nextInstructionImage()
const
165 switch ( d->nextRouteSegment().maneuver().direction() ) {
166 case Maneuver::Continue:
return QStringLiteral(
"qrc:/marble/turn-continue.svg");
167 case Maneuver::Merge:
return QStringLiteral(
"qrc:/marble/turn-merge.svg");
168 case Maneuver::Straight:
return QStringLiteral(
"qrc:/marble/turn-continue.svg");
169 case Maneuver::SlightRight:
return QStringLiteral(
"qrc:/marble/turn-slight-right.svg");
170 case Maneuver::Right:
return QStringLiteral(
"qrc:/marble/turn-right.svg");
171 case Maneuver::SharpRight:
return QStringLiteral(
"qrc:/marble/turn-sharp-right.svg");
172 case Maneuver::TurnAround:
return QStringLiteral(
"qrc:/marble/turn-around.svg");
173 case Maneuver::SharpLeft:
return QStringLiteral(
"qrc:/marble/turn-sharp-left.svg");
174 case Maneuver::Left:
return QStringLiteral(
"qrc:/marble/turn-left.svg");
175 case Maneuver::SlightLeft:
return QStringLiteral(
"qrc:/marble/turn-slight-left.svg");
176 case Maneuver::RoundaboutFirstExit:
return QStringLiteral(
"qrc:/marble/turn-roundabout-first.svg");
177 case Maneuver::RoundaboutSecondExit:
return QStringLiteral(
"qrc:/marble/turn-roundabout-second.svg");
178 case Maneuver::RoundaboutThirdExit:
return QStringLiteral(
"qrc:/marble/turn-roundabout-third.svg");
179 case Maneuver::RoundaboutExit:
return QStringLiteral(
"qrc:/marble/turn-roundabout-far.svg");
180 case Maneuver::ExitLeft:
return QStringLiteral(
"qrc:/marble/turn-exit-left.svg");
181 case Maneuver::ExitRight:
return QStringLiteral(
"qrc:/marble/turn-exit-right.svg");
182 case Maneuver::Unknown:
188 qreal Navigation::nextInstructionDistance()
const
190 return d->m_nextInstructionDistance;
193 qreal Navigation::destinationDistance()
const
195 return d->m_destinationDistance;
198 QString Navigation::voiceNavigationAnnouncement()
const
200 return d->m_voiceNavigation.instruction();
203 QString Navigation::speaker()
const
205 return d->m_voiceNavigation.speaker();
208 void Navigation::setSpeaker(
const QString &speaker )
210 d->m_voiceNavigation.setSpeaker( speaker );
213 bool Navigation::deviated()
const
215 if ( d->m_marbleQuickItem ) {
216 RoutingModel
const * routingModel = d->model()->routingManager()->routingModel();
217 return routingModel->deviatedFromRoute();
223 MarbleQuickItem *Navigation::marbleQuickItem()
const
225 return d->m_marbleQuickItem;
228 QPointF NavigationPrivate::positionOnRoute()
const
230 RoutingModel
const * routingModel = model()->routingManager()->routingModel();
231 GeoDataCoordinates coordinates = routingModel->route().positionOnRoute();
234 if (coordinates.isValid()) {
235 m_marbleQuickItem->map()->viewport()->screenCoordinates(coordinates, x, y);
240 QPointF NavigationPrivate::currentPosition()
const
242 GeoDataCoordinates coordinates = model()->positionTracking()->currentLocation();
245 m_marbleQuickItem->map()->viewport()->screenCoordinates(coordinates, x, y);
249 QPointF Navigation::screenPosition()
const
251 return d->m_screenPosition;
254 double Navigation::screenAccuracy()
const
256 return d->m_screenAccuracy;
259 void Navigation::setMarbleQuickItem(MarbleQuickItem *marbleQuickItem)
261 if ( d->m_marbleQuickItem == marbleQuickItem) {
265 if (d->m_marbleQuickItem) {
266 disconnect( d->model()->routingManager()->routingModel(),
267 SIGNAL(positionChanged()),
this, SLOT(
update()) );
269 d->m_marbleQuickItem, SLOT(
zoomIn()) );
271 d->m_marbleQuickItem, SLOT(
zoomOut()) );
272 disconnect( d->m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,
bool)),
273 d->m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)) );
275 disconnect( d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
276 d->m_autoNavigation, SLOT(inhibitAutoAdjustments()) );
279 d->m_marbleQuickItem = marbleQuickItem;
280 if ( d->m_marbleQuickItem ) {
281 d->model()->routingManager()->setShowGuidanceModeStartupWarning(
false );
282 connect( d->model()->routingManager()->routingModel(),
283 SIGNAL(positionChanged()),
this, SLOT(
update()) );
284 connect( d->model()->routingManager()->routingModel(),
285 SIGNAL(deviatedFromRoute(
bool)),
this, SIGNAL(deviationChanged()) );
287 delete d->m_autoNavigation;
288 d->m_autoNavigation =
new AutoNavigation( d->model(), d->m_marbleQuickItem->map()->viewport(),
this );
290 d->m_marbleQuickItem, SLOT(
zoomIn()) );
292 d->m_marbleQuickItem, SLOT(
zoomOut()) );
293 connect( d->m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,
bool)),
294 d->m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)) );
296 connect( d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
297 d->m_autoNavigation, SLOT(inhibitAutoAdjustments()) );
299 connect( d->m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
300 this, SLOT(updateScreenPosition()) );
301 connect( d->model()->positionTracking(), SIGNAL(gpsLocation(GeoDataCoordinates,qreal)),
302 this, SLOT(updateScreenPosition()) );
303 connect( d->model()->positionTracking(), SIGNAL(statusChanged(PositionProviderStatus)),
304 this, SLOT(updateScreenPosition()) );
307 emit marbleQuickItemChanged(marbleQuickItem);
310 void Navigation::update()
316 RoutingModel
const * routingModel = d->model()->routingManager()->routingModel();
317 d->updateNextInstructionDistance( routingModel->route() );
318 emit nextInstructionDistanceChanged();
319 emit destinationDistanceChanged();
320 RouteSegment segment = routingModel->route().currentSegment();
323 d->m_voiceNavigation.update( routingModel->route(), d->m_nextInstructionDistance, d->m_destinationDistance, routingModel->deviatedFromRoute() );
325 if ( segment != d->m_currentSegment ) {
326 d->m_currentSegment = segment;
327 emit nextInstructionTextChanged();
328 emit nextInstructionImageChanged();
329 emit nextRoadChanged();
332 updateScreenPosition();
335 void Navigation::updateScreenPosition()
337 if(d->m_marbleQuickItem) {
338 double distanceMeter = d->model()->positionTracking()->accuracy().horizontal;
339 d->m_screenAccuracy = distanceMeter * d->m_marbleQuickItem->map()->radius() / d->model()->planetRadius();
340 emit screenAccuracyChanged();
342 d->m_screenPosition = deviated() ? d->currentPosition() : d->positionOnRoute();
343 emit screenPositionChanged();
349 #include "moc_Navigation.cpp"