Prima di tutto e’ necessario creare un database Postgresql ed aggiungerci l’estensione spaziale Postgis.
come utente postgres si entra in un database esistente o in un template:
# psql template1;
– Creiamo il database e impostiamo la proprietà all’utente (nel nostro caso “sit”):
template1=# CREATE DATABASE routing OWNER sit template template_gis;
il template_gis e’ stato creato a priori (database con estensioni spaziali postgis incorporate; questo per evitare ogni volta di dover aggiungere le tabelle “geometry_column” e “spatial_ref_sys”);
– Ci colleghiamo al database appena creato:
template1=# /connect routing;
e diamo i permessi necessari all’utente “sit” sulla tabella spaziali:
routing=# GRANT ALL ON geometry_columns to sit;
routing=# GRANT SELECT ON spatial_ref_sys to sit;
– Aggiungiamo le funzioni di routing (dopo essere usciti dal database ed esserci autenticati come utente “postgres”):
# psql -d routing -f /usr/share/postlbs/routing_core.sql
# psql -d routing -f /usr/share/postlbs/routing_wrappers.sql
# psql -d routing -f /usr/share/postlbs/routing_topology.sql
– Reperiamo i dati: nel mio caso ho reperito il planet italiano dal sito http://download.geofabrik.de/osm/europe/. Ho scaricato gli SHP. Dopo aver fatto un clip dei dati sul confine regionale di interesse (Veneto) medianti i preziosissimi ftools di qgis ho ottenuto il grafo stradale del territorio veneto.
– Importiamo i dati del database mediante il modulo shp2pgsql. Ecco la sintassi del comando (con SRID settato a 4326, i dati sono in lat-long WGS84).
$ shp2pgsql -S -s 4326 /home/sit/geodatabase/shp/stradario_regione/stradario_regione_seg.shp stradario_regione routing > /home/sit/sql/stradario_regione.sql
$ psql -h localhost -U postgres -d routing -f /home/sit/sql/stradario_regione.sql
Per i passi successivi ho seguito questo ottimo tutorial ):
– Aggiungiamo 3 colonne alla tabella: una per memorizzare gli ID dei nodi iniziali, una per gli ID dei nodi finali e la’ltra per la lunghezza:
routing=> ALTER TABLE stradario_regione ADD COLUMN source integer;
routing=> ALTER TABLE stradario_regione ADD COLUMN target integer;
routing=> ALTER TABLE stradario_regione ADD COLUMN length double precision;
– Creiamo la topologia e aggiungiamo il valore della lunghezza al campo appena creato:
routing=> SELECT assign_vertex_id(‘stradario_regione’, 0.0001, ‘the_geom’, ‘gid’);
routing=> UPDATE stradario_regione SET length = length(the_geom);
– Creiamo gli indici per le colonne “source”, “target” e “the_geom”;
routing=> CREATE INDEX source_idx ON stradario_regione(source);
routing=> CREATE INDEX target_idx ON stradario_regione(target);
routing=> CREATE INDEX geom_idx ON stradario_regione USING GIST(the_geom GIST_GEOMETRY_OPS);
– Impostiamo la query di routing e salviamo il tutto in una nuova tabella chiamata “dijkstra_resust” (prima di tutto cancelliamo una eventuale tabella omonima precedentemente creata):
routing=> DROP TABLE IF EXISTS dijsktra_result;
routing=> CREATE TABLE dijsktra_result(gid int4) with oids;
routing=> SELECT AddGeometryColumn(‘dijsktra_result’, ‘the_geom’, ‘4326’, ‘MULTILINESTRING’, 2);
routing=> INSERT INTO dijsktra_result(the_geom) SELECT the_geom FROM dijkstra_sp(‘stradario_regione’, 73441, 13547);
Questa query trova il percorso minimo tra due vertici (con ID pari a 73441 e 133547).
In prima battuta, nel mio caso, ho ottenuto un messaggio d’errore per violazione di un CONSTRAINT:
ERROR: new row for relation “dijkstra_result” violates check constraint “enforce_geotype_the_geom”
Ho cancellato questo constraint (via pgadmin3) e re-impartito la query ottenendo la nuova tabella dijkstra popolata. Il risultato si può visualzzare in qgis.