Digital Geography

9. June 2015

Routing in QGIS… with OSM

Routing with Google is quite cool as the database/network is probably the best currently available. But the terms of services limit the possible usage. So what about OpenStreetMap? By figuring out how to use OSM for routing I found it much easier to get routes into QGIS with OSM compared to the Google way. Check it out….

Prerequisites for Routing with OSM: Coordinates

Before we will have a look on the routing and getting the web response from OSM into QGIS we need to translate our start and end locations/addresses into coordinates. If you have point features you can simply add the geometry to the attribute table: Of course you also have access to the point coordinates using the PyQGIS commands:
pl=qgis.utils.iface.activeLayer() #for your activated point shapefile
iterator = pl.getFeatures()
for feature in iterator:
    geom = feature.geometry()
    print geom.asPoint()
As we have all the coordinates we can move on to the routing.

Routing with and Import from OSM

The University of Heidelberg owns a great routing platform. Furthermore they have an API for this nice little tool which is well described on the OSM wiki. We will use this API. The API will respond a XML document which then will be parsed into a line shapefile. So let’s start:

First let’s get the response into the Python console. We will start with the route from Oedheim (Germany) to Modautal. The above described solutions will give us the coordinates from the start and end point or our route:
Oedheim	9.256506	49.240011
Modautal	8.72083	49.7606
We can use this coordinates already in the browser and open the following URL:
http://openls.geog.uni-heidelberg.de/testing2015/route?Start=9.256506,49.240011&End=8.72083,49.7606&Via=&lang=de&distunit=KM&routepref=Fastest&avoidAreas=&useTMC=false&noMotorways=false&noTollways=false&instructions=false

XML response from openrouteservice.org

How to do this in Python? We will use the requests module for getting the request and the build-in xml parser xml:
import requests
from xml.etree import ElementTree
url="http://openls.geog.uni-heidelberg.de/testing2015/route?Start=9.256506,49.240011&End=8.72083,49.7606&Via=&lang=de&distunit=KM&routepref=Fastest&avoidAreas=&useTMC=false&noMotorways=false&noTollways=false&instructions=false"
response = requests.get(url)
xml = ElementTree.fromstring(response.content)
Now we just need to analyze the structure (take a look at the response in your browser) and we need to know that this sentence from the Etree documentation:
Children are nested, and we can access specific child nodes by index: root[0][1].text
Keeping this in mind we can easily iterate over the point coordinates of the route and add them as vertices of a line shapefile:
from PyQt4.QtCore import QVariant
layer = QgsVectorLayer('LineString', 'route_OSM', "memory") 
pr = layer.dataProvider() 
pr.addAttributes([QgsField("attribution", QVariant.String)])
layer.updateFields()
fet = QgsFeature() 
seg=[]
for i in range(0,len(xml[1][0][1][0])): 
    seg.append(QgsPoint(float(str.split(xml[1][0][1][0][i].text)[0]),float(str.split(xml[1][0][1][0][i].text)[1]))) 

fet.setGeometry(QgsGeometry.fromPolyline(seg)) 
fet.setAttributes(["route provided by openrouteservice.org"])
pr.addFeatures([fet])
layer.updateExtents() #update it 
QgsMapLayerRegistry.instance().addMapLayer(layer)
And now let’s compare:

Google vs. OSM routing

Unfortunately we can’t rely on this project from the University Heidelberg:
Description: Through the OpenLS interface requests can be generated to the appropriate services without further query limitations. The offered API’s are only valid for ‘ one ‘ year. In case you plan a long-term use of the interfaces within your projects or high volume or for commercial applications , please contact openrouteservice AT geog.uni-heidelberg.de
Nevertheless: Download the example and alter it according to your needs.
  • Unfortunately Openrouteservice is disabled for North America…