6 #include "RoutingModel.h"
9 #include "PlanetFactory.h"
11 #include "RouteRequest.h"
12 #include "PositionTracking.h"
13 #include "MarbleGlobal.h"
14 #include "GeoDataAccuracy.h"
21 class RoutingModelPrivate
31 explicit RoutingModelPrivate(PositionTracking *positionTracking, RouteRequest *request);
35 PositionTracking *
const m_positionTracking;
36 RouteRequest*
const m_request;
38 RouteDeviation m_deviation;
40 void updateViaPoints(
const GeoDataCoordinates &position );
43 RoutingModelPrivate::RoutingModelPrivate(PositionTracking *positionTracking, RouteRequest *request) :
44 m_positionTracking(positionTracking),
51 void RoutingModelPrivate::updateViaPoints(
const GeoDataCoordinates &position )
54 qreal
const threshold = 500 / EARTH_RADIUS;
55 for(
int i=0; i<m_request->size(); ++i ) {
56 if ( !m_request->visited( i ) ) {
57 if (position.sphericalDistanceTo(m_request->at(i)) < threshold) {
58 m_request->setVisited( i,
true );
64 RoutingModel::RoutingModel(RouteRequest *request, PositionTracking *positionTracking,
QObject *parent) :
66 d(new RoutingModelPrivate(positionTracking, request))
68 QObject::connect( d->m_positionTracking, SIGNAL(gpsLocation(GeoDataCoordinates,qreal)),
69 this, SLOT(updatePosition(GeoDataCoordinates,qreal)) );
73 roles.
insert( RoutingModel::TurnTypeIconRole,
"turnTypeIcon" );
74 roles.
insert( RoutingModel::LongitudeRole,
"longitude" );
75 roles.
insert( RoutingModel::LatitudeRole,
"latitude" );
76 d->m_roleNames = roles;
79 RoutingModel::~RoutingModel()
84 int RoutingModel::rowCount (
const QModelIndex &parent )
const
86 return parent.
isValid() ? 0 : d->m_route.turnPoints().size();
92 return QString(
"Instruction" );
104 if ( index.
row() < d->m_route.turnPoints().size() && index.
column() == 0 ) {
105 const RouteSegment &segment = d->m_route.at( index.
row() );
109 return segment.maneuver().instructionText();
112 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
113 if ( segment.maneuver().hasWaypoint() ) {
114 int const size = smallScreen ? 64 : 32;
115 return d->m_request->pixmap( segment.maneuver().waypointIndex(), size, size/4 );
118 QPixmap const pixmap = segment.maneuver().directionPixmap();
119 return smallScreen ? pixmap : pixmap.
scaled( 32, 32 );
123 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
124 int const size = smallScreen ? 64 : 32;
125 return QSize( size, size );
127 case RoutingModel::CoordinateRole:
129 case RoutingModel::LongitudeRole:
130 return QVariant(segment.maneuver().position().longitude(GeoDataCoordinates::Degree));
131 case RoutingModel::LatitudeRole:
132 return QVariant(segment.maneuver().position().latitude(GeoDataCoordinates::Degree));
133 case RoutingModel::TurnTypeIconRole:
134 return segment.maneuver().directionPixmap();
145 return d->m_roleNames;
148 void RoutingModel::setRoute(
const Route &route )
151 d->m_deviation = RoutingModelPrivate::Unknown;
155 emit currentRouteChanged();
158 void RoutingModel::exportGpx(
QIODevice *device )
const
160 QString content =
QLatin1String(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
161 "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"Marble\" version=\"1.1\" "
162 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
163 "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 "
164 "http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
165 "<metadata>\n <link href=\"http://edu.kde.org/marble\">\n "
166 "<text>Marble Virtual Globe</text>\n </link>\n</metadata>\n"
167 " <rte>\n <name>Route</name>\n");
168 bool hasAltitude =
false;
169 for (
int i=0; !hasAltitude && i<d->m_route.size(); ++i ) {
170 hasAltitude = d->m_route.at( i ).maneuver().position().altitude() != 0.0;
172 for (
int i=0; i<d->m_route.size(); ++i ) {
173 const Maneuver &maneuver = d->m_route.at( i ).maneuver();
174 qreal lon = maneuver.position().longitude( GeoDataCoordinates::Degree );
175 qreal lat = maneuver.position().latitude( GeoDataCoordinates::Degree );
176 QString const text = maneuver.instructionText();
177 content +=
QString(
" <rtept lat=\"%1\" lon=\"%2\">\n" ).
arg( lat, 0,
'f', 7 ).
arg( lon, 0,
'f', 7 );
178 content +=
QString(
" <name>%1</name>\n").
arg( text );
180 content +=
QString(
" <ele>%1</ele>\n" ).
arg( maneuver.position().altitude(), 0,
'f', 2 );
182 content +=
QString(
" </rtept>\n" );
185 "<trk>\n <name>Route</name>\n <trkseg>\n");
186 GeoDataLineString points = d->m_route.path();
188 for (
int i=0; !hasAltitude && i<points.size(); ++i ) {
189 hasAltitude = points[i].altitude() != 0.0;
191 for (
int i=0; i<points.size(); ++i ) {
192 GeoDataCoordinates
const &point = points[i];
193 qreal lon = point.longitude( GeoDataCoordinates::Degree );
194 qreal lat = point.latitude( GeoDataCoordinates::Degree );
195 content +=
QString(
" <trkpt lat=\"%1\" lon=\"%2\">\n" ).
arg( lat, 0,
'f', 7 ).
arg( lon, 0,
'f', 7 );
197 content +=
QString(
" <ele>%1</ele>\n" ).
arg( point.altitude(), 0,
'f', 2 );
199 content +=
QString(
" </trkpt>\n" );
207 void RoutingModel::clear()
209 d->m_route = Route();
212 emit currentRouteChanged();
215 int RoutingModel::rightNeighbor(
const GeoDataCoordinates &position, RouteRequest
const *
const route )
const
217 Q_ASSERT( route &&
"Must not pass a null route ");
220 if ( route->size() < 3 ) {
221 return route->size() - 1;
225 GeoDataLineString points = d->m_route.path();
233 for (
int j=1; j<route->size()-1; ++j ) {
234 qreal minDistance = -1.0;
235 for (
int i=mapping[j-1]; i<points.size(); ++i ) {
236 const qreal
distance = points[i].sphericalDistanceTo(route->at(j));
237 if (minDistance < 0.0 || distance < minDistance ) {
245 qreal minWaypointDistance = -1.0;
247 for (
int i=0; i<points.size(); ++i ) {
248 const qreal waypointDistance = points[i].sphericalDistanceTo(position);
249 if ( minWaypointDistance < 0.0 || waypointDistance < minWaypointDistance ) {
250 minWaypointDistance = waypointDistance;
256 mapping[route->size()-1] = points.
size()-1;
260 for ( ; iter != mapping.
constEnd(); ++iter ) {
261 if ( iter.value() > waypoint ) {
262 int index = iter.key();
263 Q_ASSERT( index >= 0 && index <= route->size() );
268 return route->size()-1;
271 void RoutingModel::updatePosition(
const GeoDataCoordinates& location, qreal speed )
273 d->m_route.setPosition( location );
275 d->updateViaPoints( location );
277 const qreal
distance = planetRadius *
location.sphericalDistanceTo(d->m_route.positionOnRoute());
278 emit positionChanged();
280 qreal deviation = 0.0;
281 if ( d->m_positionTracking && d->m_positionTracking->accuracy().vertical > 0.0 ) {
282 deviation = qMax<qreal>( d->m_positionTracking->accuracy().vertical, d->m_positionTracking->accuracy().horizontal );
284 qreal
const threshold = deviation + qBound(10.0, speed*10.0, 150.0);
286 RoutingModelPrivate::RouteDeviation
const deviated =
distance < threshold ? RoutingModelPrivate::OnRoute : RoutingModelPrivate::OffRoute;
287 if ( d->m_deviation != deviated ) {
288 d->m_deviation = deviated;
289 emit deviatedFromRoute( deviated == RoutingModelPrivate::OffRoute );
293 bool RoutingModel::deviatedFromRoute()
const
295 return d->m_deviation == RoutingModelPrivate::OffRoute;
298 const Route & RoutingModel::route()
const
305 #include "moc_RoutingModel.cpp"