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:

points_to_route1

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:

points_to_route0

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:

points_to_route2

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.

About these ads
36 comments
  1. Curlew said:

    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.

  2. Vincent Tinet said:

    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

  3. 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.

      • Thanks. I contacted Victor through twitter. I can’t really justify joining the devel mailing list.

  4. barret said:

    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 ……

      • barret said:

        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;

  5. barret said:

    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?

      • barret said:

        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.

  6. Morten said:

    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

      • Morten said:

        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.

  7. Rochele said:

    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?

      • Rochele said:

        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.

      • Rochele said:

        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

      • Rochele said:

        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.

      • Rochele said:

        Ok Anita, thank you – I must find this button…
        Any progress or failure, I let you know.
        Rochele

  8. Morten said:

    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

      • Morten said:

        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.

  9. Klaus said:

    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

  10. Katie said:

    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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 3,003 other followers

%d bloggers like this: