A routing script for the Processing toolbox
Did you know that there is a network analysis library in QGIS core? It’s well hidden so far, but at least it’s documented in the PyQGIS Cookbook. The code samples from the cookbook can be used in the QGIS Python console and you can play around to get a grip of what the different steps are doing.
As a first exercise, I’ve decided to write a Processing script which will use the network analysis library to create a network-based route layer from a point layer input. You can find the result on Github.
You can get a Spatialite file with testdata from Github as well. It contains a network and a routepoints1 layer:
The interface of the points_to_route tool is very simple. All it needs as an input is information about which layer should be used as a network and which layer contains the route points:
The input points are considered to be ordered. The tool always routes between consecutive points.
The result is a line layer with one line feature for each point pair:
The network analysis library is a really great new feature and I hope we will see a lot of tools built on top of it.
Cool, here a little bug report:
-> It returns an empty output layer if there is only one way from a to b. See test data (http://www.datafilehost.com/d/3dca1f8d)
-> It raises an error if multiple points far from the line are used as input. Try for instance the railroads and airports layers from the QGIS alaska testdata.
Thanks for the feedback! In case you use Github, could you also open tickets there?
The issue seems to be that it fails to match some points onto the graph. Whenever one point fails, the current version of the script returns an empty layer. I’ve now changed the behavior a bit. The tool now ignores point pairs where it fails to match one or both points.
I’ve built a set of processing scripts for transportation analysis based on the network analysis library. It contains scripts for building a network file (from to cost and direction columns) from a road file or a GTFS file (public transport), 2 scripts for calculating a point file with shortest paths costs form a set of features to all points (road and public transport), and 2 scripts for calculating origins-destinations shortest paths from a set of lines.
Those scripts can be shared (in your repo if you want), but are not very pythonic in style, and a mix of french and english… I don’t really have time to make them useful for general use. It also contains some custom features, not necessarily useful for everyone (rerouting around tolls, correcting erroneous GTFS files…)
On the API side, i foud that Network Analysis is quit fast, but the API design far two complex for doing simple things. That’s why I directly used the Graph object instead of following the pyqgis manual. I can go in further delays if necessary.
Hi Vincent,
That sounds just great! Are you familiar enough with Github to fork my repo and send pull requests containing your scripts? If not, I can also add them myself if you mail them. I’m very interested to see how you implemented GTFS and directions. One thing I’d also like to see some day is the possibility to have turn restrictions considered as well. Have you ever looked into this issue?
Best wishes,
Anita
Pingback: A routing script for the Processing toolbox | S...
I really wish the QGIS folks had thought harder about the name of this plugin. Processing — http://processing.org/ — is a well-established visual computing language. It was hard enough to search for resources before the QGIS thing broke out.
This is pretty unfortunate indeed. Note that if you want to reach the developers, it would be better to send your thoughts to the QGIS mailing list. Processing was simply not on the radar. You can find the discussion here: http://osgeo-org.1560.x6.nabble.com/Renaming-SEXTANTE-td5071779.html
Thanks. I contacted Victor through twitter. I can’t really justify joining the devel mailing list.
Bonjour
Tout d’abord, un grand merci pour le travail effectué et surtout bonne continuation !
Je vous joins le message que j’obtiens lorsque je lance le script :
Traceback (most recent call last):
File “E:/qgis_fich/apps/QGIS Dufour/apps/qgis/./python/plugins\processing\core\GeoAlgorithm.py”, line 150, in execute
self.processAlgorithm(progress)
File “E:/qgis_fich/apps/QGIS Dufour/apps/qgis/./python/plugins\processing\script\ScriptAlgorithm.py”, line 213, in processAlgorithm
exec(script) in ns
File “”, line 73, in
TypeError: QgsFeature.setGeometry(QgsGeometry): argument 1 has unexpected type ‘NoneType’
Je ne comprend pas le message ……
Have you tried if it works with the test data?
https://github.com/anitagraser/QGIS-Processing-tools/tree/master/testdata
Thanks for the response.
I have tried the test data, it works.
But when i take my own data it doesn’t work :
Description of my two tables :
— Table: public.lyo03_adr_voie_lieu_adraxevoie
— DROP TABLE public.lyo03_adr_voie_lieu_adraxevoie;
CREATE TABLE public.lyo03_adr_voie_lieu_adraxevoie
(
id integer NOT NULL DEFAULT nextval(‘lyo03_adr_voie_lieu_adraxevoie_id_seq’::regclass),
geom geometry(MultiLineString,3946),
nom character varying(80),
commune character varying(80),
codefuv character varying(80),
codetronco character varying(80),
importance character varying(80),
domanialit character varying(80),
typecirc character varying(80),
senscirc character varying(80),
senscircsp character varying(80),
gid character varying(80),
source integer,
target integer,
cost_len double precision,
cost_time double precision,
rcost_len double precision,
rcost_time double precision,
x1 double precision,
y1 double precision,
x2 double precision,
y2 double precision,
to_cost double precision,
rule text,
isolated integer,
CONSTRAINT lyo03_adr_voie_lieu_adraxevoie_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.lyo03_adr_voie_lieu_adraxevoie
OWNER TO postgres;
— Index: public.lyo03_adr_voie_lieu_adraxevoie_geom_gidx
— DROP INDEX public.lyo03_adr_voie_lieu_adraxevoie_geom_gidx;
CREATE INDEX lyo03_adr_voie_lieu_adraxevoie_geom_gidx
ON public.lyo03_adr_voie_lieu_adraxevoie
USING gist
(geom);
— Index: public.lyo03_adr_voie_lieu_adraxevoie_source_idx
— DROP INDEX public.lyo03_adr_voie_lieu_adraxevoie_source_idx;
CREATE INDEX lyo03_adr_voie_lieu_adraxevoie_source_idx
ON public.lyo03_adr_voie_lieu_adraxevoie
USING btree
(source);
— Index: public.lyo03_adr_voie_lieu_adraxevoie_target_idx
— DROP INDEX public.lyo03_adr_voie_lieu_adraxevoie_target_idx;
CREATE INDEX lyo03_adr_voie_lieu_adraxevoie_target_idx
ON public.lyo03_adr_voie_lieu_adraxevoie
USING btree
(target);
——————————————————————————————————————————
— Table: public.”lyo03_adr_voie_lieu.adradresse”
— DROP TABLE public.”lyo03_adr_voie_lieu.adradresse”;
CREATE TABLE public.”lyo03_adr_voie_lieu.adradresse”
(
id integer NOT NULL DEFAULT nextval(‘”lyo03_adr_voie_lieu.adradresse_id_seq”‘::regclass),
geom geometry(MultiPoint,3946),
numero character varying(80),
voie character varying(80),
commune character varying(80),
inseecommu character varying(80),
codefuv character varying(80),
datecreati character varying(80),
gid character varying(80),
id_adr integer,
“T_menage” integer,
CONSTRAINT “lyo03_adr_voie_lieu.adradresse_pkey” PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.”lyo03_adr_voie_lieu.adradresse”
OWNER TO postgres;
I use Postgresql 9.3 + postgis 2.1 + pgrouting 2 and qgis 2.0.1
Hard to tell what’s going on. Can you share the network data for test purposes?
Well now i have another problem, the tests data doesn’t work and i have this message when i click on the button “Run” :
‘module’ object has no attribute ‘getobject’
See log for more details
I also see that there is another version of “Processing” (20 November). I have tried to install this but the same problem appear at the begining.
I don’t understand what i have to do now ?
getobject is a Processing function. If that does not work, I assume it’s an issue with the installation. Which version of Sextante do you have installed now?
What happens if you try to load the test data using Add Spatialite Layer?
The problem was indeed caused by a change between Processing versions. I’ve updated the script to reflect the latest changes. Please try it now.
Looks interesting but I can’t get to use the testdata:
https://github.com/anitagraser/QGIS-Processing-tools/tree/master/testdata.
When I try to add it in Qgis or in Spatialite-GUI I get the message:
table info on geometry_columns failed
file is encrypted or is not a database
Tried to download it 3 times but same result with all downloads :-(
I am working in Win 7 64 bit
I’m also working on Win7 64bit and the file works fine after downloading it from https://github.com/anitagraser/QGIS-Processing-tools/raw/master/testdata/testdata.sqlite
Please try once more.
It worked with the fourth download attempt – I can now open then testdata.sqlite in QGIS.
But I get exactly the same error as Barret mentions above:
module’ object has no attribute ‘getobject’
The Sextante log shows this info:
Uncaught error while executing algorithm
Traceback (most recent call last):
Traceback (most recent call last):
File “C:\Users\map/.qgis2/python/plugins\processing\core\GeoAlgorithm.py”, line 202, in execute
self.processAlgorithm(progress)
File “C:\Users\map/.qgis2/python/plugins\processing\script\ScriptAlgorithm.py”, line 252, in processAlgorithm
exec script in ns
File “”, line 21, in
AttributeError: ‘module’ object has no attribute ‘getobject’
I am using Qgis 2.0.1 installed by use of OQGeo4w.
Thanks for your feedback Morten!
The latest Processing version changed getobject() to getObject() and getfeatures() to features(). That’s why the script did not work. I’m updating it now.
Hi Anita,
I´m trying to use your script and your testdata, but I still with the same error as Morten and Barret. The error shows that description:
Traceback (most recent call last):
File “C:/PROGRA~1/QGISDU~1/apps/qgis/./python/plugins\processing\core\GeoAlgorithm.py”, line 150, in execute
self.processAlgorithm(progress)
File “C:/PROGRA~1/QGISDU~1/apps/qgis/./python/plugins\processing\script\ScriptAlgorithm.py”, line 213, in processAlgorithm
exec(script) in ns
File “”, line 21, in
AttributeError: ‘module’ object has no attribute ‘getObject’
I´m using your last script in this link: https://github.com/anitagraser/QGIS-Processing-tools/blob/master/1.1/scripts/points_to_route.py
And your testdata in this link: https://github.com/anitagraser/QGIS-Processing-tools/raw/master/testdata/testdata.sqlite
I´m using QGis 2.0.1
I would appreciate some help.
Best wishes,
Rochele
Hi Rochele,
Which version of the Processing plugin do you have?
Hi Anita,
Thank you for answering my question.
I´m sorry, I´m a beginner user and I don´t know how to answer your question! :(
So, I wrote all the information that I found about QGIS – please see below:
QGis version: 2.0.1-Dufour
QGIS Code version: d94c044
Compiled on Qt: 4.8.5
Running on Qt 4.8.5
Compiled on GDAL/OGR: 1.10.0
Running on GDAL/OGR: 1.10.0
Compiled on GEOS: 3.4.2 – CAPI – 1.8.2
Running on GEOS: 3.4.2 – CAPI – 1.8.2
PostgreSQL version: 9.2.4
SpatiaLite version4.1.1
QWT version: 5.2.3
PROJ.4 version: 480
QScintilla2 version: 2.7.2
I hope that these information could help. Otherwise, would you explain how I can find information about processing plugin?
Thank you
Rochele
You can see the Processing plugin version in the Plugin Manager.
Hi Anita,
Thank you for your answer.
here the information:
Processing
Spatial data processing framework for QGIS
Category: Analysis
Autor: Victor Olaya
Version: 1.1
Thanks,
Rochele
Please try upgrading Processing, you should be able to get version: 2.0-20131120
Ok Anita, I will try to update. I already get the new version in Plugin Repository site (http://plugins.qgis.org/plugins/processing/), but I don´t know yet how to update the version.
My first try: I only replaced the old processing folder (version 1.1) to the new processing folder (2.0), but didn´t work. Probably I´m missing something…
Whatever, thank you very much for your help. If I have some progress, I´ll post here.
Rochele
You should be able to just select the plugin in Plugin Manager and press the “Update plugin” button there.
Ok Anita, thank you – I must find this button…
Any progress or failure, I let you know.
Rochele
Hi Anita
I have now got your Point to Route script to work and intend to use for converting a list of georeferenced bus stops to the actual bus route driven on the road network.
I have also taken a look at your “Lines to route script” and “Find similar line feature” which look very interesting. As a traffic planner and analyst I often have to combine data from different representations of the same actual road network.
But I have a problem with Python-Scipy which is required for “Find Similar line feature”. You write it can be installed from OSgeo4w shell but is is not available when I try running the OSGeo4w shell and I do not see it on the OSGeo4w package list either: http://trac.osgeo.org/osgeo4w/wiki/PackageListing.
Googling a little reveals some problems with Scipy and 64 bit windows – that might be the problem?
How did you install scipy?
Regards Morten
Great you got the routing script to work! I’ve recently modified it to run faster. So I recommend updating if you still use the old version. Concerning your scipy problem: Do you have numpy installed http://trac.osgeo.org/osgeo4w/wiki/pkg-python-numpy? That might be enough.
I’ve already got numpy installed and the error message when running the “Find Similar line feature” script tells “No module named scipy.spatial.distance”:
Uncaught error while executing algorithm
Traceback (most recent call last):
Traceback (most recent call last):
File “C:\Users\map/.qgis2/python/plugins\processing\core\GeoAlgorithm.py”, line 202, in execute
self.processAlgorithm(progress)
File “C:\Users\map/.qgis2/python/plugins\processing\script\ScriptAlgorithm.py”, line 252, in processAlgorithm
exec script in ns
File “”, line 19, in
File “C:/OSGEO4~1/apps/qgis/./python\qgis\utils.py”, line 453, in _import
mod = _builtin_import(name, globals, locals, fromlist, level)
ImportError: No module named scipy.spatial.distance
I’ve now compared the 32bit and 64bit installers and indeed, python-scipy is only available for 32bit. I guess there is a good reason for that and that we are out of luck.
Hi Anita,
I really like your script and it works fine with my data (OSM-road network and bus stops as points). Is it possible to integrate one way streets into the script? I’d like to have results, which are comparable to the road graph plugin in QGIS.
The road network table has a one way street column with the values 0 for both directions und 1 for one way streets. It also has columns for costs and return costs, which were generated during the PostGIS import with osm2po. I am using QGIS 2.2 (sometimes 2.3 if I want to use the fixed road graph plugin), PostGIS 9.3 and pgRouting 2.0.
If this isn’t working with your script, I’ll try to build a similar function with pgRouting, which generates the shortest pathes between the bus stops of a bus line. But I would prefer your script, because my pgRouting solution requires much work on the network data.
Have a nice weekend
Kind regards
Klaus
Hi Anita,
I’m relatively new to GIS and in searching the web for tutorials/troubleshooting I can tell you’re a frequent contributor. I really appreciate your work and your interest in helping others. For my current project, I am trying to calculate the shortest path (time) between multiple points. I have a road layer and a set of GPS coordinates. Is there a way to combine the functionality of your Points to Route tool with the Road Graph plugin, particularly the option that allows you to calculate for shortest time based on road speeds?
Additionally, it’d be great if I get a “review” of the route’s steps once calculated, such as after how many kms to turn, what road to turn onto, etc. I couldn’t find any information on how this can be done and wanted to see if you had any ideas?
Thanks again for your help!
Katie
Hi Katie,
About the fastest path: I’m not completely sure it’s possible yet but I have asked here http://osgeo-org.1560.x6.nabble.com/Is-fastest-not-shortest-path-routing-possible-in-PyQGIS-td5151566.html
Concerning step-by-step navigation instructions, I’m afraid there is nothing implemented in QGIS yet. If you are interested how it can be done, look at some of the OpenStreetMap routing projects. Some, like Graphhopper http://graphhopper.com include navigation instructions.