Tuesday, 14 February 2017

qgis - Calculating many shortest paths with pgRouting


I 145013 Danish addresses, and 10 big cities in Denmark as points in QGIS. Furthermore, I have four vector layers that connect all the points. They are small roads, main roads, freeways and ferry routes. See the screen dump from QGIS below for an illustration:



QGIS screen dump illustrating my problem


Now I would like to calculate the shortest distance from each address to each of the 10 big cities. I will use pgRouting for this, and I have followed the nice tutorial on finding 1 shortest path here http://anitagraser.com/2013/07/06/pgrouting-2-0-for-windows-quick-guide/


However, I can't figure out how to extend the problem from 1 path to (145013 * 10 =) 1450130 paths.



  • What method should I use in pgRouting, and how do I incorporate all the 1450130 paths?


I use:



  • QGIS 2.1.0

  • postgres 9.2


  • postgis 2.0

  • pgRouting 2.0

  • OS: Win 7 64bit


I have shared my data here: https://www.dropbox.com/sh/rn8gdxr1bki4q4x/fFRd0PerkP


It's in in a QGIS project file.


I appreciate all comments and answers!



Answer



First load data into postgis and convert all data to same projection. Create one table from all data and follow PgRouting tutorial to create edges and vertexes. I really hope that that data is topologically correct already and you dont need to fix those issues. ( Have you considered just using osm2po data for your network ? )


If you have already done it, then see pgrouting dijkstra example and do:



This works but is slow. i used Finnish osm2po data for testing


CREATE OR REPLACE FUNCTION get_all_routes(target int) RETURNS VOID  AS
$BODY$
DECLARE
r record;

BEGIN

CREATE TABLE route_res as SELECT 0 , route.*
FROM (SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra('

SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM vw_finland_routing',
10 , 60, false, false) ) as route ;



FOR r IN

SELECT source from vw_finland_routing
LOOP

INSERT INTO route_res SELECT r.source , route.*
FROM (SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra('
SELECT gid AS id,
source::integer,
target::integer,
length::double precision AS cost
FROM vw_finland_routing',

r.source , target, false, false) ) as route ;

RAISE NOTICE ' Running at % source id' ,r.source ;
END LOOP;

END
$BODY$
LANGUAGE plpgsql;

AND



SELECT get_all_routes(10) -- where 10 is target from city 

Solution is slow and badly written. CREATE table needs to be taken out from function or needs to be in if exist block. to get some performance out of this you need to run N queries to target or if you can change it so that source is city and target is in for loop. My other ideas for problem are using pgr_kDijkstra. Or you can create city wide polygon and use it to overwrite that area source/target id's so function needs only find an area (takes 1000-> or more edges from route table)


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...