• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • plugins
  • runner
  • gosmore-routing
GosmoreRoutingRunner.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2010 Dennis Nienhüser <earthwings@gentoo.org>
9 // Copyright 2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
10 //
11 
12 #include "GosmoreRoutingRunner.h"
13 
14 #include "MarbleDebug.h"
15 #include "MarbleDirs.h"
16 #include "routing/RouteRequest.h"
17 #include "routing/instructions/WaypointParser.h"
18 #include "routing/instructions/InstructionTransformation.h"
19 #include "GeoDataDocument.h"
20 #include "GeoDataExtendedData.h"
21 
22 #include <QProcess>
23 #include <QMap>
24 
25 namespace Marble
26 {
27 
28 class GosmoreRunnerPrivate
29 {
30 public:
31  QFileInfo m_gosmoreMapFile;
32 
33  WaypointParser m_parser;
34 
36  static QMap<QString, QByteArray> m_partialRoutes;
37 
38  QByteArray retrieveWaypoints( const QString &query ) const;
39 
40  static GeoDataDocument* createDocument( GeoDataLineString* routeWaypoints, const QVector<GeoDataPlacemark*> instructions );
41 
42  static GeoDataLineString parseGosmoreOutput( const QByteArray &content );
43 
44  static void merge( GeoDataLineString* one, const GeoDataLineString& two );
45 
46  QVector<GeoDataPlacemark*> parseGosmoreInstructions( const QByteArray &content );
47 
48  GosmoreRunnerPrivate();
49 };
50 
51 GosmoreRunnerPrivate::GosmoreRunnerPrivate()
52 {
53  m_parser.setLineSeparator("\r");
54  m_parser.setFieldSeparator(',');
55  m_parser.setFieldIndex( WaypointParser::RoadName, 4 );
56  m_parser.addJunctionTypeMapping( "Jr", RoutingWaypoint::Roundabout );
57 }
58 
59 QMap<QString, QByteArray> GosmoreRunnerPrivate::m_partialRoutes;
60 
61 void GosmoreRunnerPrivate::merge( GeoDataLineString* one, const GeoDataLineString& two )
62 {
63  Q_ASSERT( one );
64 
65  QVector<GeoDataCoordinates>::const_iterator iter = two.constBegin();
66  for( ; iter != two.constEnd(); ++iter ) {
68  one->append( *iter );
69  }
70 }
71 
72 QByteArray GosmoreRunnerPrivate::retrieveWaypoints( const QString &query ) const
73 {
74  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
75  env.insert("QUERY_STRING", query);
76  env.insert("LC_ALL", "C");
77  QProcess gosmore;
78  gosmore.setProcessEnvironment(env);
79 
80  gosmore.start("gosmore", QStringList() << m_gosmoreMapFile.absoluteFilePath() );
81  if (!gosmore.waitForStarted(5000)) {
82  mDebug() << "Couldn't start gosmore from the current PATH. Install it to retrieve routing results from gosmore.";
83  return QByteArray();
84  }
85 
86  if ( gosmore.waitForFinished(15000) ) {
87  return gosmore.readAllStandardOutput();
88  }
89  else {
90  mDebug() << "Couldn't stop gosmore";
91  }
92 
93  return QByteArray();
94 }
95 
96 GeoDataLineString GosmoreRunnerPrivate::parseGosmoreOutput( const QByteArray &content )
97 {
98  GeoDataLineString routeWaypoints;
99 
100  QStringList lines = QString::fromLocal8Bit( content ).split( '\r' );
101  foreach( const QString &line, lines ) {
102  QStringList fields = line.split(',');
103  if (fields.size() >= 5) {
104  qreal lon = fields.at(1).toDouble();
105  qreal lat = fields.at(0).toDouble();
106  GeoDataCoordinates coordinates( lon, lat, 0.0, GeoDataCoordinates::Degree );
107  routeWaypoints.append( coordinates );
108  }
109  }
110 
111  return routeWaypoints;
112 }
113 
114 QVector<GeoDataPlacemark*> GosmoreRunnerPrivate::parseGosmoreInstructions( const QByteArray &content )
115 {
116  // Determine gosmore version
117  QStringList lines = QString::fromUtf8( content ).split( '\r' );
118  if ( lines.size() > 2 ) {
119  QStringList fields = lines.at( lines.size()-2 ).split(',');
120  m_parser.setFieldIndex( WaypointParser::RoadName, fields.size()-1 );
121  if ( fields.size() < 5 || fields.size() > 6 ) {
122  // Can happen when gosmore changes the output format, returns garbage
123  // or the last street name contains a comma. We may still parse it correctly, just try.
124  mDebug() << "Unexpected number of fields. This gosmore version may be unsupported.";
125  }
126  }
127 
128  QVector<GeoDataPlacemark*> result;
129  QTextStream stream( content );
130  stream.setCodec("UTF8");
131  stream.setAutoDetectUnicode( true );
132 
133  RoutingInstructions directions = InstructionTransformation::process( m_parser.parse( stream ) );
134  for( int i=0; i<directions.size(); ++i ) {
135  GeoDataPlacemark* placemark = new GeoDataPlacemark( directions[i].instructionText() );
136  GeoDataExtendedData extendedData;
137  GeoDataData turnType;
138  turnType.setName( "turnType" );
139  turnType.setValue( qVariantFromValue<int>( int( directions[i].turnType() ) ) );
140  extendedData.addValue( turnType );
141  GeoDataData roadName;
142  roadName.setName( "roadName" );
143  roadName.setValue( directions[i].roadName() );
144  extendedData.addValue( roadName );
145  placemark->setExtendedData( extendedData );
146  Q_ASSERT( !directions[i].points().isEmpty() );
147  GeoDataLineString* geometry = new GeoDataLineString;
148  QVector<RoutingWaypoint> items = directions[i].points();
149  for (int j=0; j<items.size(); ++j ) {
150  RoutingPoint point = items[j].point();
151  GeoDataCoordinates coordinates( point.lon(), point.lat(), 0.0, GeoDataCoordinates::Degree );
152  geometry->append( coordinates );
153  }
154  placemark->setGeometry( geometry );
155  result.push_back( placemark );
156  }
157 
158  return result;
159 }
160 
161 GeoDataDocument* GosmoreRunnerPrivate::createDocument( GeoDataLineString* routeWaypoints, const QVector<GeoDataPlacemark*> instructions )
162 {
163  if ( !routeWaypoints || routeWaypoints->isEmpty() ) {
164  return 0;
165  }
166 
167  GeoDataDocument* result = new GeoDataDocument();
168  GeoDataPlacemark* routePlacemark = new GeoDataPlacemark;
169  routePlacemark->setName( "Route" );
170  routePlacemark->setGeometry( routeWaypoints );
171  result->append( routePlacemark );
172 
173  QString name = "%1 %2 (Gosmore)";
174  QString unit = QLatin1String( "m" );
175  qreal length = routeWaypoints->length( EARTH_RADIUS );
176  if (length >= 1000) {
177  length /= 1000.0;
178  unit = "km";
179  }
180  result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) );
181 
182  foreach( GeoDataPlacemark* placemark, instructions )
183  {
184  result->append( placemark );
185  }
186 
187  return result;
188 }
189 
190 GosmoreRunner::GosmoreRunner( QObject *parent ) :
191  RoutingRunner( parent ),
192  d( new GosmoreRunnerPrivate )
193 {
194  // Check installation
195  QDir mapDir( MarbleDirs::localPath() + "/maps/earth/gosmore/" );
196  d->m_gosmoreMapFile = QFileInfo ( mapDir, "gosmore.pak" );
197 }
198 
199 GosmoreRunner::~GosmoreRunner()
200 {
201  delete d;
202 }
203 
204 void GosmoreRunner::retrieveRoute( const RouteRequest *route )
205 {
206  if ( !d->m_gosmoreMapFile.exists() )
207  {
208  emit routeCalculated( 0 );
209  return;
210  }
211 
212  GeoDataLineString* wayPoints = new GeoDataLineString;
213  QByteArray completeOutput;
214 
215  for( int i=0; i<route->size()-1; ++i )
216  {
217  QString queryString = "flat=%1&flon=%2&tlat=%3&tlon=%4&fastest=1&v=motorcar";
218  GeoDataCoordinates source = route->at(i);
219  double fLon = source.longitude( GeoDataCoordinates::Degree );
220  double fLat = source.latitude( GeoDataCoordinates::Degree );
221  queryString = queryString.arg(fLat, 0, 'f', 8).arg(fLon, 0, 'f', 8);
222  GeoDataCoordinates destination = route->at(i+1);
223  double tLon = destination.longitude( GeoDataCoordinates::Degree );
224  double tLat = destination.latitude( GeoDataCoordinates::Degree );
225  queryString = queryString.arg(tLat, 0, 'f', 8).arg(tLon, 0, 'f', 8);
226 
227  QByteArray output;
228  if ( d->m_partialRoutes.contains( queryString ) ) {
229  output = d->m_partialRoutes[queryString];
230  }
231  else {
232  output = d->retrieveWaypoints( queryString );
233  }
234 
235  GeoDataLineString points = d->parseGosmoreOutput( output );
236  d->merge( wayPoints, points );
237  completeOutput.append( output );
238  }
239 
240  QVector<GeoDataPlacemark*> instructions = d->parseGosmoreInstructions( completeOutput );
241 
242  GeoDataDocument* result = d->createDocument( wayPoints, instructions );
243  emit routeCalculated( result );
244 }
245 
246 } // namespace Marble
GeoDataDocument.h
Marble::RouteRequest::size
int size() const
Number of points in the route.
Definition: RouteRequest.cpp:126
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
QString::append
QString & append(QChar ch)
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:65
Marble::WaypointParser::RoadName
Definition: WaypointParser.h:33
QProcessEnvironment
QVector::append
void append(const T &value)
QByteArray
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QVector::constEnd
const_iterator constEnd() const
QList::at
const T & at(int i) const
QMap< QString, QByteArray >
QProcessEnvironment::insert
void insert(const QString &name, const QString &value)
Marble::MarbleDirs::localPath
static QString localPath()
Definition: MarbleDirs.cpp:223
GeoDataExtendedData.h
Marble::RoutingInstructions
QVector< RoutingInstruction > RoutingInstructions
Definition: RoutingInstruction.h:157
Marble::GeoDataCoordinates::latitude
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Definition: GeoDataCoordinates.cpp:751
InstructionTransformation.h
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
QTextStream
QList::size
int size() const
Marble::RouteRequest
Points to be included in a route.
Definition: RouteRequest.h:31
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
Marble::EARTH_RADIUS
const qreal EARTH_RADIUS
Definition: MarbleGlobal.h:257
Marble::InstructionTransformation::process
static RoutingInstructions process(const RoutingWaypoints &waypoints)
Transforms waypoints and metadata into driving directions.
Definition: InstructionTransformation.cpp:18
QProcess
QObject
Marble::GosmoreRunner::~GosmoreRunner
~GosmoreRunner()
Definition: GosmoreReverseGeocodingRunner.cpp:81
MarbleDirs.h
Marble::GosmoreRunner::retrieveRoute
virtual void retrieveRoute(const RouteRequest *request)
Start a route download orw calculation.
Definition: GosmoreRoutingRunner.cpp:204
Marble::GosmoreRunner::GosmoreRunner
GosmoreRunner(QObject *parent=0)
Definition: GosmoreReverseGeocodingRunner.cpp:72
QString
WaypointParser.h
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
QStringList
QByteArray::append
QByteArray & append(char ch)
QFileInfo
Marble::GeoDataCoordinates::longitude
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Definition: GeoDataCoordinates.cpp:739
QProcess::waitForStarted
bool waitForStarted(int msecs)
Marble::RoutingRunner::routeCalculated
void routeCalculated(GeoDataDocument *route)
Route download/calculation is finished, result in the given route object.
QDir
QProcess::setProcessEnvironment
void setProcessEnvironment(const QProcessEnvironment &environment)
QVector::constBegin
const_iterator constBegin() const
QVector
QLatin1String
Marble::RoutingWaypoint::Roundabout
Definition: RoutingWaypoint.h:31
GosmoreRoutingRunner.h
QVector::push_back
void push_back(const T &value)
RouteRequest.h
QProcessEnvironment::systemEnvironment
QProcessEnvironment systemEnvironment()
QVector::size
int size() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
QProcess::readAllStandardOutput
QByteArray readAllStandardOutput()
QProcess::start
void start(const QString &program, const QStringList &arguments, QFlags< QIODevice::OpenModeFlag > mode)
QProcess::waitForFinished
bool waitForFinished(int msecs)
Marble::RouteRequest::at
GeoDataCoordinates at(int index) const
Accessor for the n-th position.
Definition: RouteRequest.cpp:149
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal