• 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
  • cyclestreets
CycleStreetsRunner.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 2013 Mihail Ivchenko <ematirov@gmail.com>
9 //
10 
11 #include "CycleStreetsRunner.h"
12 
13 #include "MarbleDebug.h"
14 #include "GeoDataDocument.h"
15 #include "GeoDataExtendedData.h"
16 #include "TinyWebBrowser.h"
17 #include "routing/Maneuver.h"
18 #include "routing/RouteRequest.h"
19 
20 #include <QUrl>
21 #include <QTimer>
22 #include <QNetworkReply>
23 #include <QDomDocument>
24 #include <QVector>
25 #include <QPair>
26 
27 #if QT_VERSION >= 0x050000
28  #include <QUrlQuery>
29 #endif
30 
31 namespace Marble
32 {
33 
34 CycleStreetsRunner::CycleStreetsRunner( QObject *parent ) :
35  RoutingRunner( parent ),
36  m_networkAccessManager(),
37  m_request()
38 {
39  connect( &m_networkAccessManager, SIGNAL(finished(QNetworkReply*)),
40  this, SLOT(retrieveData(QNetworkReply*)) );
41 
42  turns.insert( "", Maneuver::Continue );
43  turns.insert( "straight on", Maneuver::Straight );
44  turns.insert( "bear right", Maneuver::SlightRight );
45  turns.insert( "bear left", Maneuver::SlightLeft );
46  turns.insert( "sharp right", Maneuver::SharpRight );
47  turns.insert( "sharp left", Maneuver::SharpLeft );
48  turns.insert( "turn right", Maneuver::Right );
49  turns.insert( "turn left", Maneuver::Left );
50  turns.insert( "double-back", Maneuver::TurnAround);
51  turns.insert( "first exit", Maneuver::RoundaboutFirstExit );
52  turns.insert( "second exit", Maneuver::RoundaboutSecondExit );
53  turns.insert( "third exit", Maneuver::RoundaboutThirdExit );
54  turns.insert( "fourth exit", Maneuver::RoundaboutExit );
55  turns.insert( "fifth exit", Maneuver::RoundaboutExit );
56  turns.insert( "sixth exit", Maneuver::RoundaboutExit );
57  turns.insert( "seventh or more exit", Maneuver::RoundaboutExit );
58 }
59 
60 CycleStreetsRunner::~CycleStreetsRunner()
61 {
62  // nothing to do
63 }
64 
65 void CycleStreetsRunner::retrieveRoute( const RouteRequest *route )
66 {
67  if ( route->size() < 2 || route->size() > 12 ) {
68  return;
69  }
70 
71  QHash<QString, QVariant> settings = route->routingProfile().pluginSettings()["cyclestreets"];
72 
73  QUrl url("http://www.cyclestreets.net/api/journey.xml");
74  QMap<QString, QString> queryStrings;
75  queryStrings["key"] = "cdccf13997d59e70";
76  queryStrings["useDom"] = '1';
77  queryStrings["plan"] = settings["plan"].toString();
78  queryStrings["speed"] = settings["speed"].toString();
79  GeoDataCoordinates::Unit const degree = GeoDataCoordinates::Degree;
80  QString itinerarypoints;
81  itinerarypoints.append( QString::number( route->source().longitude( degree ), 'f', 6 ) + ',' + QString::number( route->source().latitude( degree ), 'f', 6 ) );
82  for ( int i=1; i<route->size(); ++i ) {
83  itinerarypoints.append( '|' + QString::number( route->at( i ).longitude( degree ), 'f', 6 ) + ',' + QString::number( route->at( i ).latitude( degree ), 'f', 6 ) );
84  }
85  queryStrings["itinerarypoints"] = itinerarypoints;
86 
87 #if QT_VERSION >= 0x050000
88  QUrlQuery urlQuery;
89  Q_FOREACH( const QString& key, queryStrings.keys()){
90  urlQuery.addQueryItem(key, queryStrings.value(key));
91  }
92  url.setQuery( urlQuery);
93 #else
94  typedef QMap<QString, QString>::ConstIterator Iterator;
95  Iterator end = queryStrings.constEnd();
96  for ( Iterator iter = queryStrings.constBegin(); iter != end; ++iter ) {
97  url.addQueryItem(iter.key(), iter.value());
98  }
99 #endif
100 
101  m_request.setUrl( url );
102  m_request.setRawHeader( "User-Agent", TinyWebBrowser::userAgent( "Browser", "CycleStreetsRunner" ) );
103 
104  QEventLoop eventLoop;
105 
106  QTimer timer;
107  timer.setSingleShot( true );
108  timer.setInterval( 15000 );
109 
110  connect( &timer, SIGNAL(timeout()),
111  &eventLoop, SLOT(quit()));
112  connect( this, SIGNAL(routeCalculated(GeoDataDocument*)),
113  &eventLoop, SLOT(quit()) );
114 
115  // @todo FIXME Must currently be done in the main thread, see bug 257376
116  QTimer::singleShot( 0, this, SLOT(get()) );
117  timer.start();
118 
119  eventLoop.exec();
120 }
121 
122 void CycleStreetsRunner::get()
123 {
124  QNetworkReply *reply = m_networkAccessManager.get( m_request );
125  connect( reply, SIGNAL(error(QNetworkReply::NetworkError)),
126  this, SLOT(handleError(QNetworkReply::NetworkError)), Qt::DirectConnection );
127 }
128 
129 void CycleStreetsRunner::retrieveData( QNetworkReply *reply )
130 {
131  if ( reply->isFinished() ) {
132  QByteArray data = reply->readAll();
133  reply->deleteLater();
134  //mDebug() << "Download completed: " << data;
135  GeoDataDocument *document = parse( data );
136 
137  if ( !document ) {
138  mDebug() << "Failed to parse the downloaded route data" << data;
139  }
140 
141  emit routeCalculated( document );
142  }
143 }
144 
145 int CycleStreetsRunner::maneuverType(QString& cycleStreetsName) const
146 {
147  if ( turns.contains( cycleStreetsName ) ) {
148  return turns[cycleStreetsName];
149  }
150  return Maneuver::Unknown;
151 }
152 
153 GeoDataDocument *CycleStreetsRunner::parse( const QByteArray &content ) const
154 {
155  QDomDocument xml;
156  if ( !xml.setContent( content ) ) {
157  mDebug() << "Cannot parse xml file with routing instructions.";
158  return 0;
159  }
160  GeoDataDocument *result = new GeoDataDocument();
161  result->setName( "CycleStreets" );
162  GeoDataPlacemark *routePlacemark = new GeoDataPlacemark;
163  routePlacemark->setName( "Route" );
164 
165  GeoDataLineString *routeWaypoints = new GeoDataLineString;
166  QDomNodeList features = xml.elementsByTagName( "gml:featureMember" );
167 
168  if ( features.isEmpty() ) {
169  return 0;
170  }
171  QDomElement route = features.at( 0 ).toElement().firstChild().toElement();
172  QDomElement lineString = route.elementsByTagName( "gml:LineString" ).at( 0 ).toElement();
173  QDomElement coordinates = lineString.toElement().elementsByTagName( "gml:coordinates" ).at( 0 ).toElement();
174  QStringList coordinatesList = coordinates.text().split( ' ' );
175 
176  QStringList::iterator iter = coordinatesList.begin();
177  QStringList::iterator end = coordinatesList.end();
178 
179  for( ; iter != end; ++iter) {
180  QStringList coordinate = iter->split(',');
181  if ( coordinate.size() == 2 ) {
182  double const lon = coordinate.at( 0 ).toDouble();
183  double const lat = coordinate.at( 1 ).toDouble();
184  GeoDataCoordinates const position( lon, lat, 0.0, GeoDataCoordinates::Degree );
185  routeWaypoints->append( position );
186  }
187  }
188  routePlacemark->setGeometry( routeWaypoints );
189 
190  QDomElement durationElement = route.elementsByTagName( "cs:time" ).at(0).toElement();
191  QTime duration;
192  duration = duration.addSecs( durationElement.text().toInt() );
193  qreal length = routeWaypoints->length( EARTH_RADIUS );
194 
195  const QString name = nameString( "CS", length, duration );
196  const GeoDataExtendedData data = routeData( length, duration );
197  routePlacemark->setExtendedData( data );
198  result->setName( name );
199  result->append( routePlacemark );
200 
201  int i;
202  for ( i = 1; i < features.count() && features.at( i ).firstChildElement().tagName() != "cs:segment"; ++i );
203  for ( ; i < features.count(); ++i) {
204  QDomElement segment = features.at( i ).toElement();
205 
206  QString name = segment.elementsByTagName( "cs:name" ).at( 0 ).toElement().text();
207  QString maneuver = segment.elementsByTagName( "cs:turn" ).at( 0 ).toElement().text();
208  QStringList points = segment.elementsByTagName( "cs:points" ).at( 0 ).toElement().text().split( ' ' );
209  QStringList const elevation = segment.elementsByTagName( "cs:elevations" ).at( 0 ).toElement().text().split( ',' );
210 
211  GeoDataPlacemark *instructions = new GeoDataPlacemark;
212  QString instructionName;
213  if ( !maneuver.isEmpty() ) {
214  instructionName = maneuver.left( 1 ).toUpper() + maneuver.mid( 1 );
215  } else {
216  instructionName = "Straight";
217  }
218  if ( name != "Short un-named link" && name != "Un-named link" ){
219  instructionName.append( " into " + name );
220  }
221  instructions->setName( instructionName );
222 
223  GeoDataExtendedData extendedData;
224  GeoDataData turnType;
225  turnType.setName( "turnType" );
226  turnType.setValue( maneuverType( maneuver ) );
227  extendedData.addValue( turnType );
228 
229  instructions->setExtendedData( extendedData );
230  GeoDataLineString *lineString = new GeoDataLineString;
231  QStringList::iterator iter = points.begin();
232  QStringList::iterator end = points.end();
233  for ( int j=0; iter != end; ++iter, ++j ) {
234  QStringList coordinate = iter->split( ',' );
235  if ( coordinate.size() == 2 ) {
236  double const lon = coordinate.at( 0 ).toDouble();
237  double const lat = coordinate.at( 1 ).toDouble();
238  double const alt = j < elevation.size() ? elevation[j].toDouble() : 0.0;
239  lineString->append( GeoDataCoordinates( lon, lat, alt, GeoDataCoordinates::Degree ) );
240  }
241  }
242  instructions->setGeometry( lineString );
243  result->append( instructions );
244  }
245  return result;
246 }
247 
248 void CycleStreetsRunner::handleError( QNetworkReply::NetworkError error )
249 {
250  mDebug() << " Error when retrieving cyclestreets.net route: " << error;
251 }
252 
253 } // namespace Marble
254 
255 #include "CycleStreetsRunner.moc"
Marble::GeoDataCoordinates::Unit
Unit
enum used constructor to specify the units used
Definition: GeoDataCoordinates.h:64
Marble::Maneuver::TurnAround
Definition: Maneuver.h:34
GeoDataDocument.h
QTimer::setInterval
void setInterval(int msec)
Marble::RouteRequest::size
int size() const
Number of points in the route.
Definition: RouteRequest.cpp:126
QDomElement::elementsByTagName
QDomNodeList elementsByTagName(const QString &tagname) const
Marble::Maneuver::RoundaboutExit
Definition: Maneuver.h:41
QString::append
QString & append(QChar ch)
TinyWebBrowser.h
QString::toUpper
QString toUpper() const
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:65
Marble::Maneuver::SharpRight
Definition: Maneuver.h:33
QUrl::setQuery
void setQuery(const QString &txt)
QEventLoop
QMap::contains
bool contains(const Key &key) const
QNetworkRequest::setUrl
void setUrl(const QUrl &url)
QByteArray
Marble::CycleStreetsRunner::CycleStreetsRunner
CycleStreetsRunner(QObject *parent=0)
Definition: CycleStreetsRunner.cpp:34
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
QNetworkReply
Marble::Maneuver::Left
Definition: Maneuver.h:36
QDomNodeList
QMap::constBegin
const_iterator constBegin() const
QList::at
const T & at(int i) const
QMap< QString, QString >
GeoDataExtendedData.h
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
QTime
MarbleDebug.h
Marble::Maneuver::Straight
Definition: Maneuver.h:30
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::Maneuver::Right
Definition: Maneuver.h:32
QList::size
int size() const
Maneuver.h
Marble::RoutingRunner::nameString
const QString nameString(const QString &name, qreal length, const QTime &duration) const
Definition: RoutingRunner.cpp:55
QDomNode::toElement
QDomElement toElement() const
CycleStreetsRunner.h
QMap::keys
QList< Key > keys() const
QDomNodeList::isEmpty
bool isEmpty() const
Marble::RouteRequest
Points to be included in a route.
Definition: RouteRequest.h:31
QObject::name
const char * name() const
Marble::Maneuver::RoundaboutFirstExit
Definition: Maneuver.h:38
Marble::RouteRequest::routingProfile
RoutingProfile routingProfile() const
Definition: RouteRequest.cpp:321
QDomNodeList::count
int count() const
QString::number
QString number(int n, int base)
QList::append
void append(const T &value)
Marble::EARTH_RADIUS
const qreal EARTH_RADIUS
Definition: MarbleGlobal.h:257
QDomElement::text
QString text() const
QTimer
Marble::CycleStreetsRunner::retrieveRoute
virtual void retrieveRoute(const RouteRequest *request)
Start a route download orw calculation.
Definition: CycleStreetsRunner.cpp:65
QHash< QString, QVariant >
QEventLoop::exec
int exec(QFlags< QEventLoop::ProcessEventsFlag > flags)
QObject
QString::toInt
int toInt(bool *ok, int base) const
QNetworkReply::isFinished
bool isFinished() const
QDomDocument::elementsByTagName
QDomNodeList elementsByTagName(const QString &tagname) const
QString::isEmpty
bool isEmpty() const
QMap::constEnd
const_iterator constEnd() const
QIODevice::readAll
QByteArray readAll()
QTime::addSecs
QTime addSecs(int s) const
Marble::Maneuver::SlightRight
Definition: Maneuver.h:31
Marble::RoutingRunner::routeData
const GeoDataExtendedData routeData(qreal length, const QTime &duration) const
Definition: RoutingRunner.cpp:61
QObject::deleteLater
void deleteLater()
QString
QList::iterator
QStringList
QList::end
iterator end()
Marble::CycleStreetsRunner::~CycleStreetsRunner
~CycleStreetsRunner()
Definition: CycleStreetsRunner.cpp:60
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
QUrl
QDomDocument
Marble::Maneuver::Continue
Definition: Maneuver.h:28
Marble::RoutingProfile::pluginSettings
const QHash< QString, QHash< QString, QVariant > > & pluginSettings() const
Definition: RoutingProfile.cpp:33
Marble::RoutingRunner::routeCalculated
void routeCalculated(GeoDataDocument *route)
Route download/calculation is finished, result in the given route object.
QDomNode::firstChild
QDomNode firstChild() const
Marble::Maneuver::RoundaboutThirdExit
Definition: Maneuver.h:40
QString::mid
QString mid(int position, int n) const
Marble::RoutingRunner
Definition: RoutingRunner.h:28
QNetworkRequest::setRawHeader
void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
QDomNode::firstChildElement
QDomElement firstChildElement(const QString &tagName) const
QString::left
QString left(int n) const
QTimer::start
void start(int msec)
QUrl::addQueryItem
void addQueryItem(const QString &key, const QString &value)
RouteRequest.h
Marble::TinyWebBrowser::userAgent
static QByteArray userAgent(const QString &platform, const QString &plugin)
Definition: TinyWebBrowser.cpp:106
QMap::insert
iterator insert(const Key &key, const T &value)
QDomElement::tagName
QString tagName() const
QNetworkAccessManager::get
QNetworkReply * get(const QNetworkRequest &request)
Marble::Maneuver::Unknown
Definition: Maneuver.h:27
Marble::Maneuver::SlightLeft
Definition: Maneuver.h:37
Marble::Maneuver::SharpLeft
Definition: Maneuver.h:35
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QDomElement
Marble::Maneuver::RoundaboutSecondExit
Definition: Maneuver.h:39
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
QList::begin
iterator begin()
Marble::RouteRequest::source
GeoDataCoordinates source() const
The first point, or a default constructed if empty.
Definition: RouteRequest.cpp:131
coordinate
Coordinate coordinate
Definition: tools/osm-addresses/OsmParser.cpp:39
QDomNodeList::at
QDomNode at(int index) const
QDomDocument::setContent
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QMap::value
const T value(const Key &key) const
QTimer::setSingleShot
void setSingleShot(bool singleShot)
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:38 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