[Marble-commits] KDE/kdeedu/marble/src/lib/routing

Dennis Nienhüser earthwings at gentoo.org
Sat Jul 10 20:29:33 CEST 2010


SVN commit 1148459 by nienhueser:

When openrouteservice.org fails to calculate a route (e.g. requests outside of Europe or no streets nearby), use nroets.dev.openstreetmap.org as a fallback. This server is a variant of yours with worldwide data and much better hardware than yournavigation.org. For now only basic routing; route summary, via point support and directions to be done.
CCMAIL: nroets at gmail.com

 M  +50 -27    RoutingManager.cpp  
 M  +1 -0      RoutingManager.h  
 M  +53 -2     RoutingModel.cpp  
 M  +9 -1      RoutingModel.h  
 M  +3 -2      YoursRoutingProvider.cpp  


--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingManager.cpp #1148458:1148459
@@ -13,6 +13,7 @@
 #include "MarbleDebug.h"
 #include "MarbleWidget.h"
 #include "OrsRoutingProvider.h"
+#include "YoursRoutingProvider.h"
 #include "RouteSkeleton.h"
 #include "RoutingModel.h"
 
@@ -24,32 +25,62 @@
 class RoutingManagerPrivate
 {
 public:
+    RoutingManager* q;
+
     RoutingModel *m_routingModel;
 
-    AbstractRoutingProvider *m_routingProvider;
+    AbstractRoutingProvider *m_orsProvider;
 
+    AbstractRoutingProvider *m_yoursProvider;
+
     MarbleWidget *m_marbleWidget;
 
-    RoutingManagerPrivate( MarbleWidget *widget, QObject *parent );
-
     RouteSkeleton *m_route;
 
     bool m_workOffline;
+
+    RoutingManagerPrivate( MarbleWidget *widget, RoutingManager* manager, QObject *parent );
+
+    void updateRoute( AbstractRoutingProvider* provider );
 };
 
-RoutingManagerPrivate::RoutingManagerPrivate( MarbleWidget *widget, QObject *parent ) :
-        m_routingModel( new RoutingModel( parent ) ),
-        m_routingProvider( new OrsRoutingProvider( parent ) ),
+RoutingManagerPrivate::RoutingManagerPrivate( MarbleWidget *widget, RoutingManager* manager, QObject *parent ) :
+        q( manager ), m_routingModel( new RoutingModel( parent ) ),
+        m_orsProvider( new OrsRoutingProvider( parent ) ),
+        m_yoursProvider( new YoursRoutingProvider( parent ) ),
         m_marbleWidget( widget ), m_route( 0 ), m_workOffline( false )
 {
     // nothing to do
 }
 
+void RoutingManagerPrivate::updateRoute( AbstractRoutingProvider* provider )
+{
+    if ( !m_workOffline && m_route && m_route->size() > 1 ) {
+        int realSize = 0;
+        for ( int i = 0; i < m_route->size(); ++i ) {
+            // Sort out dummy targets
+            if ( m_route->at( i ).longitude() != 0.0 && m_route->at( i ).latitude() != 0.0 ) {
+                ++realSize;
+            }
+        }
+
+        if ( realSize > 1 ) {
+            emit q->stateChanged( RoutingManager::Downloading, m_route );
+            provider->retrieveDirections( m_route );
+        } else {
+            m_routingModel->clear();
+            emit q->stateChanged( RoutingManager::Retrieved, m_route );
+        }
+    }
+}
+
 RoutingManager::RoutingManager( MarbleWidget *widget, QObject *parent ) : QObject( parent ),
-        d( new RoutingManagerPrivate( widget, this ) )
+        d( new RoutingManagerPrivate( widget, this, this ) )
 {
-    connect( d->m_routingProvider, SIGNAL( routeRetrieved( AbstractRoutingProvider::Format, QByteArray ) ),
+    connect( d->m_orsProvider, SIGNAL( routeRetrieved( AbstractRoutingProvider::Format, QByteArray ) ),
              this, SLOT( setRouteData( AbstractRoutingProvider::Format, QByteArray ) ) );
+    connect( d->m_yoursProvider, SIGNAL( routeRetrieved( AbstractRoutingProvider::Format, QByteArray ) ),
+             this, SLOT( setRouteData( AbstractRoutingProvider::Format, QByteArray ) ) );
 }
 
 RoutingManager::~RoutingManager()
@@ -71,10 +102,18 @@
 void RoutingManager::setRouteData( AbstractRoutingProvider::Format format, const QByteArray &data )
 {
     /** @todo: switch to using GeoDataDocument* */
-    Q_UNUSED( format );
 
     if ( data.size() ) {
-        d->m_routingModel->importOpenGis( data );
+        if ( format == AbstractRoutingProvider::OpenGIS ) {
+            if ( !d->m_routingModel->importOpenGis( data ) ) {
+                mDebug() << " Invalid ORS route, trying YOURS instead";
+                d->updateRoute( d->m_yoursProvider );
+            }
+        } else if ( format == AbstractRoutingProvider::KML ) {
+            d->m_routingModel->importKml( data );
+        } else {
+            mDebug() << "Gpx format import for routing is not implemented yet";
+        }
         d->m_marbleWidget->repaint();
     } else {
         mDebug() << "Got an empty result instead of route data";
@@ -87,25 +126,9 @@
 
 void RoutingManager::updateRoute()
 {
-    if ( !d->m_workOffline && d->m_route && d->m_route->size() > 1 ) {
-        int realSize = 0;
-        for ( int i = 0; i < d->m_route->size(); ++i ) {
-            // Sort out dummy targets
-            if ( d->m_route->at( i ).longitude() != 0.0 && d->m_route->at( i ).latitude() != 0.0 ) {
-                ++realSize;
+    d->updateRoute( d->m_orsProvider );
             }
-        }
 
-        if ( realSize > 1 ) {
-            emit stateChanged( Downloading, d->m_route );
-            d->m_routingProvider->retrieveDirections( d->m_route );
-        } else {
-            d->m_routingModel->clear();
-            emit stateChanged( Retrieved, d->m_route );
-        }
-    }
-}
-
 void RoutingManager::setWorkOffline( bool offline )
 {
     d->m_workOffline = offline;
--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingManager.h #1148458:1148459
@@ -83,6 +83,7 @@
     void setRouteData( AbstractRoutingProvider::Format format, const QByteArray &data );
 
 private:
+    friend class RoutingManagerPrivate;
     RoutingManagerPrivate *const d;
 };
 
--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingModel.cpp #1148458:1148459
@@ -15,6 +15,8 @@
 #include "MarbleMath.h"
 #include "GeoDataCoordinates.h"
 #include "GeoDataDocument.h"
+#include "GeoDataGeometry.h"
+#include "GeoDataFolder.h"
 #include "GeoDataParser.h"
 #include "GeoDataPlacemark.h"
 #include "RouteSkeleton.h"
@@ -129,20 +131,27 @@
     return QVariant();
 }
 
-void RoutingModel::importOpenGis( const QByteArray &content )
+bool RoutingModel::importOpenGis( const QByteArray &content )
 {
     d->m_route.clear();
 
     QDomDocument xml;
     if ( !xml.setContent( content ) ) {
         mDebug() << "Cannot parse xml file with routing instructions.";
-        return;
+        reset();
+        return false;
     }
 
     QDomElement root = xml.documentElement();
 
     QDomNodeList errors = root.elementsByTagName( "xls:Error" );
     if ( errors.size() > 0 ) {
+        reset();
+        return false;
+        // Returning early because fallback routing providers are used now
+        // The code below can be used to parse OpenGis errors reported by ORS
+        // and may be useful in the future
+
         for ( unsigned int i = 0; i < errors.length(); ++i ) {
             QDomNode node = errors.item( i );
             QString errorMessage = node.attributes().namedItem( "message" ).nodeValue();
@@ -244,8 +253,50 @@
     }
 
     reset();
+    return true;
 }
 
+bool RoutingModel::importKml( const QByteArray &content )
+{
+    d->m_route.clear();
+    GeoDataParser parser( GeoData_UNKNOWN );
+
+    // Open file in right mode
+    QBuffer buffer;
+    buffer.setData( content );
+    buffer.open( QIODevice::ReadOnly );
+
+    if ( !parser.read( &buffer ) ) {
+        qDebug() << "Cannot parse kml data! Input is " << content ;
+        reset();
+        return false;
+    }
+    GeoDataDocument* document = static_cast<GeoDataDocument*>( parser.releaseDocument() );
+    Q_ASSERT( document );
+
+    QVector<GeoDataFolder> folders = document->folders();
+    foreach( const GeoDataFolder &folder, folders ) {
+        foreach( const GeoDataPlacemark &placemark, folder.placemarks() ) {
+            GeoDataGeometry* geometry = placemark.geometry();
+            if ( geometry->geometryId() == GeoDataLineStringId ) {
+                GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry );
+                Q_ASSERT( lineString && "Internal error: geometry ID does not match class type" );
+                if ( lineString ) {
+                    for ( int i=0; i<lineString->size(); ++i ) {
+                        RouteElement element;
+                        element.type = WayPoint;
+                        element.position = lineString->at( i );
+                        d->m_route.push_back( element );
+                    }
+                }
+            }
+        }
+    }
+
+    reset();
+    return true;
+}
+
 RoutingModel::Duration RoutingModel::duration() const
 {
     return d->m_totalDuration;
--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingModel.h #1148458:1148459
@@ -91,9 +91,17 @@
       * @todo: Add geodata/handlers/opengis, use it in the route provider and use a
       * parsed GeoDocument here
       */
-    void importOpenGis( const QByteArray &xmlData );
+    bool importOpenGis( const QByteArray &xmlData );
 
     /**
+      * @brief Parse the provided data in kml format.
+      *
+      * Old data in the model is discarded, the parsed content of the provided xml data
+      * in kml format is used as the new model data and a model reset is done
+      */
+    bool importKml( const QByteArray &content );
+
+    /**
       * Returns the total (estimated) time it takes to travel from
 -     * source to destination
       */
--- trunk/KDE/kdeedu/marble/src/lib/routing/YoursRoutingProvider.cpp #1148458:1148459
@@ -43,10 +43,11 @@
     double tLon = destination.longitude( GeoDataCoordinates::Degree );
     double tLat = destination.latitude( GeoDataCoordinates::Degree );
 
-    QString base = "http://www.yournavigation.org/api/1.0/gosmore.php";
+    //QString base = "http://www.yournavigation.org/api/1.0/gosmore.php";
+    QString base = "http://nroets.dev.openstreetmap.org/demo/gosmore.php";
     QString args = "?flat=%1&flon=%2&tlat=%3&tlon=%4";
     args = args.arg( fLat, 0, 'f', 6 ).arg( fLon, 0, 'f', 6 ).arg( tLat, 0, 'f', 6 ).arg( tLon, 0, 'f', 6 );
-    QString preferences = "&v=motorcar&fast=1&layer=mapnik&format=kml";
+    QString preferences = "&v=motorcar&fast=1&layer=mapnik";
     QString request = base + args + preferences;
     // mDebug() << "GET: " << request;
 


More information about the Marble-commits mailing list