Analisi di rete in GRASS File

Transcript

Analisi di rete in GRASS File
Analisi di reti con
GRASS
In collaborazione con
Paolo Zatelli
Dipartimento di Ingegneria Civile ed Ambientale
Università degli Studi di Trento
Cartografia numerica e GIS
Problemi legati ad una rete
Le domande che ci si può porre rispetto ad una rete (insieme di
linee connesse) è:
●
●
●
●
●
quale è il percorso più breve tra due punti (nodi)?
è possibile calcolare zone equidistanti (lungo la rete) da punti
(nodi) dati?
si può dividere la rete in sottoreti di elementi più vicini a punti
(nodi) dati?
è possibile determinare la sottorete di lunghezza minima che
connette un set di punti (nodi) dati (alberi di Steiner)?
si può calcolare il percorso più breve che passa per tutti i punti
(nodi) dati una sola volta (problema del commesso viaggiatore)?
Metrica sulla rete
Le domande sono poste in termini di distanza ma andrebbero
poste in termini di costo di percorrenza dei tratti e di
attraversamento dei nodi.
Ad es:
- la stessa distanza fisica su tipi di strade diverse (velocità diversa) può avere un
costo significativamente diverso per il calcolo del tempo di percorrenza, così come
la presenza di restringimenti e deviazioni sui nodi;
- per una rete di acquedotto il tipo e diametro dei tubi influenza la perdita di carico (il
costo di attraversamento), perdita che può essere anche concentrata su
saracinesche e giunzioni (nodi).
La distanza fisica deve essere sostituita da un costo, cioè la
distanza modificata secondo una metrica (velocità massima,
diametro dei tubi, ecc.).
Per i tratti il costo può essere dato in modo assoluto oppure
per unità di lunghezza, il costo viene cioè moltiplicato per la
lunghezza fisica del tratto.
Ad es. il tempo di percorrenza su una strada è pari alla velocità media moltiplicata
per la distanza percorsa.
Teoria dei grafi
L'analisi delle reti è basata sulla teoria dei grafi.
Un grafo consiste in un insieme finito di connessioni logiche tra
oggetti (detti vertici). I vertici sono rappresentati da nodi e i
collegamenti da archi (linee con verso).
GRASS per l'analisi delle reti utilizza la libreria DGLib
(Directed Graph Library) scritta da Roberto Micarelli.
E' possibile assegnare un costo diverso ad ogni nodo e ad
ogni linea e ad ogni verso di percorrenza.
Dati necessari
Per fare analisi di una rete si deve disporre di:
●
●
una mappa vettoriale con linee e punti (connessi alla
rete);
uno o più tabelle di DB contenenti i costi collegati agli
elementi della mappa (linee e nodi), se i costi non sono
disponibili si può usare solo la distanza.
Collegamenti di punti ad una rete
Un insieme di punti può essere collegato ad una rete di archi in
due passaggi:
0. creazione degli archi di collegamento tra rete e punti;
1. unione delle 3 mappe vettoriali che contengono rispettivamente
gli archi, i punti e i collegamenti.
I collegamenti si possono disegnare manualmente con v.digit
oppure tracciare automaticamente con v.distance, che permette
di determinare linee da un vettoriale ad un altro con diversi criteri
(uguale categoria, minima distanza, elementi di uguale x o y,
minima distanza lungo una linea e minima distanza in una
direzione data).
Le mappe si uniscono con v.patch.
Moduli di GRASS
Alcuni moduli di GRASS per l'analisi delle reti sono:
● d.path – calcola e visualizza il percorso minimo tra nodi
individuati con il mouse sul display in modo interattivo;
● v.net.path – come il precedente ma in modo non interattivo;
● v.net.iso – suddivide la rete in aree ad uguale costo lungo la rete
attorno a punti (nodi) della rete indicati in input;
● v.net.alloc – crea (alloca) sottoreti che corrispondono alle parti di
reti più vicine a ciascun punto (nodo) indicato in input;
● v.net.steiner – crea l'albero di Steiner (rete di minima lunghezza
che connette i nodi dati) per una data rete e un set di punti (nodi)
della rete;
● v.net.salesman – risolve il “problema del commesso viaggiatore”
(salesman) individuando il percorso più breve che passa una sola
volta per i punti (nodi) della rete dati.
Caratteristiche comuni ai moduli
Alcune caratteristiche, che derivano dall'implementazione
della DGLib, sono comuni a tutti i moduli:
● se non viene assegnato un costo a nodi e archi viene usata
la distanza (lunghezza);
● è possibile assegnare costi diversi ai due versi di
percorrenza degli archi (linee orientate, d.vect mappa
display=shape,dir);
● un costo pari a -1 indica che il tratto è bloccato e non viene
considerato nell'analisi della rete;
● è possibile assegnare costo -1 ad un solo verso di
percorrenza bloccandolo, l'arco è percorribile nell'altro verso
(sensi unici);
● nella implementazione attuale della DGLib i costi possono
essere dati solo con colonne del DB di tipo int;
Esercitazione
Predisporre cartografia d'aiuto all'intervento di
squadre di vigili del fuoco per lo spegnimento di
incendi
Location:
sistema di riferimento e proiezione usati dal dataset North
Carolina
Dati:
dati vettoriali del dataset North Carolina
Dati preparati durante la precedente esercitazione
utilizzando comandi di gestione di database e di
geoprocessing.
(eventualmente si utilizzi lo script: analisi_reti_preparazione.sh)
Percorsi più brevi tra stazioni dei pompieri lungo la rete
stradale (v.net.path)
Si utilizza ora il modulo v.net.path per determinare in modo non interattivo e
salvare in un file vettoriale il percorso minimo tra punti individuati dalla loro
categoria.
Si visualizzi la rete (network_cat3), in nero, ed i punti delle stazioni
(firestations_raleigh) dei pompieri in rosso nella mappa network:
Nella figura sono
visualizzate anche le
categorie dei punti che
rappresentano le caserme.
Per indicare i punti da connettere (firestations_raleigh) con un percorso minimo è necessario
conoscere le loro categorie, che si possono visualizzare sul secondo layer di network o
network_cat3:
> v.category --overwrite --verbose input=network_cat3 option=print layer=2
che visualizza
Volendo si potrebbe visualizzare la tabella associata si visualizza con db.select
> db.select sql= "select * from firestations_central where cat=21 or cat=26 or cat=27 or
cat=52"
che fornisce
cat|ID|LABEL|LOCATION|CITY|MUN_COUNT|PUMPERS|PUMPER_TAN|TANKER|
MINI_PUMPE|RESCUE_SER|AERIAL| BRUSH|OTHERS|WATER_RESC|MUNCOID|
BLDGCODE|AGENCY|STATIONID|RECNO|CV_SID2|CVLAG
21|0|RFD #20|1721 Trailwood Dr|Raleigh|M|1|0|0|0|2|0|0|0|0|1|260|RF|RF20|23|RF20|0
26|0|RFD #5|300 Oberlin Rd|Raleigh|M|1|0|0|0|1|0|0|0|0|1|265|RF|RF05|28|RF05|0
27|0|RFD #6|2601 Fairview Rd|Raleigh|M|1|0|0|0|1|0|0|0|1|1|266|RF|RF06|29|RF06|0
52|27|Swift Creek|6000 Holly Springs Rd|Raleigh|C|0|3|2|0|1|0|1|0|0|2|290|FD|SC1A|54|SC1A|
1.32
O ancor meglio si potrebbe visualizzare la tabella firestations_raleigh direttamente, con
db.select ovvero con il table manager.
> db.select table=firestations_raleigh
Si crea quindi una nuova mappa vettoriale che contiene il percorso di lunghezza minima tra le
caserme di Trailwood Drive (categoria 21) e quella di Oberlin Road (categoria 26):
> echo "2 21 26"|v.net.path --overwrite --verbose input=network_cat3 output=path_21_26
Si visualizza quindi la rete, in nero, i punti delle stazioni dei pompieri in rosso nella mappa
network ed il percorso in rosso nella mappa path_21_26:
E' possibile creare percorsi che passano per più di un punto, ad esempio si può creare una
nuova mappa vettoriale che contiene il percorso di lunghezza minima tra le caserme di
Trailwood Drive (categoria 21), Oberlin Road (categoria 26) e Fairview Road (categoria 27)
> echo "`printf '2 21 26\n2 26 27'`"|v.net.path --overwrite --verbose input=network
output=path_21_26_27
NOTA: I caratteri \n indicano al file
di punti l'azione dell'andare a capo
In alternativa alla procedura appena descritta, il numero del layer e le categorie dei punti da
toccare possono essere preventivamente scritti in un file, uno per riga, e dato come input a
v.net.path, utilizzando il comando scritto qui di seguito, che funziona solo se è già stato creato il
file file_di_punti.txt:
> v.net.path --overwrite --verbose input=network output=path_21_26_27 file=file_di_punti.txt
Percorsi minimi chiudendo alcune strade
I percorsi precedenti sono determinati usando come costo di attraversamento dei tratti la
distanza e permettendo il passaggio in tutte le strade.
N.B. E' possibile "chiudere" alcune strade in uno o entrambi i versi di percorrenza.
Per fare questo sono stati assegnati costi di percorrenza per gli archi (strade) in una colonna
della tabella associata: le strade a cui corrsiponde un costo uguale a -1 sono considerate
chiuse (in uno o entrambi i versi di percorrenza).
Per mantenere come costo la distanza (per le strade che non saranno chiuse) sono state create
due nuove colonne, una per i costi in avanti (concordi con il verso della linea) ed una per i costi
indietro (discordi con il verso della linea).
Si determina quindi il percorso minimo con costi da tabella, creando la mappa path_21_26_db, i
costi sono ancora le lunghezze ma sono lette dalla tabella:
> echo "2 21 26"|v.net.path --overwrite input=network_cat3 output=path_21_26_db alayer=3
afcolumn=lungh_a abcolumn=lungh_i
Il percorso ovviamente non cambia, i costi sono sempre le lunghezze.
Si vuole chiudere al traffico il primo tratto di strada che dalla Trailwood Drive (categoria 21) va
verso quella di Oberlin Road (categoria 26). Interrogando la mappa network_cat3 con il mouse
sul Display si individua la categoria di questa strada sul layer 3: 6658.
Le caratteristiche di questa strada sul layer 1:
> echo "select a_CARTONAM from network where cat=6658"|db.select
a_CARTONAM
NEW BERN AVE
sul layer 3
> echo "select * from network_cat3_3 where cat=6658"|db.select
cat|lungh_a|lungh_i
6658|1237.159234|1237.159234
Si chiude quindi New Bern Avenue (strada 6658) inserendo un costo pari a -1. In avanti:
> echo "UPDATE network_cat3_3 SET lungh_a=-1 WHERE cat=6658" | db.execute
e indietro
> echo "UPDATE network_cat3_3 SET lungh_i=-1 WHERE cat=6658" | db.execute
Ora la strada sul layer 3 è chiusa, come posso verificare utilizzando db select o piû
semplicemente interrogando la mappa network_cat3 in corrispondenza di New Bern avenue:
> echo "select * from network_cat3_3 where cat=6658"|db.select
cat|lungh_a|lungh_i
6658|-1|-1
Si determina il percorso con costi = lunghezze da DB - ma New Bern Avenue (strada 6658)
chiusa, creando la mappa path_21_26_db_no_new_bern_ave,:
>
echo
"2
21
26"|v.net.path
--overwrite
input=network_cat3
output=path_21_26_db_no_new_bern_ave alayer=3 afcolumn=lungh_a abcolumn=lungh_i
Il percorso minimo ovviamente cambia, non potendo più passare per New Bern
Avenue (visualizzata in verde).
Prima di continuare con le successive elaborazioni conviene riaprire le strade, reinserendo le
lunghezze in avanti:
> v.to.db --verbose map=network_cat3 type=line,boundary layer=3 qlayer=3 option=length
columns=lungh_a
e indietro
> v.to.db --verbose map=network_cat3 type=line,boundary layer=3 qlayer=3 option=length
columns=lungh_i
Percorsi minimi in funzione dei tempi di percorrenza
Invece di usare le lunghezze come costo di attraversamento di un tratto è spesso più
significativo usare altre grandezze, come ad esempio il tempo necessario a percorrere
ciascun tratto nel caso delle strade.
Il valore della velocità massima consentita per ogni strada è disponibile nella colonna
a_SPEED del layer 1 della rete in [miglia/ora]. Per calcolare il tempo di attraverso è
sufficiente dividere la lunghezza per la velocità.
Si deve riportare la colonna delle velocità dal layer=1 al layer=3, e calcolare il costo di
attraversamento in tempo = lungh/max_vel.
Per fare ciò,:
a) Si aggiungono due colonne (speed e cost) al layer 3 della mappa network_cat3_3.
b) Si inseriscono le velocità nella colonna speed, prendendole dalla tabella network
(layer=1);
c) Si inserisce nella colonna cost il tempo di percorrenza. Per passare da miglia a metri, la
velocità è moltiplicata per 1610.
> v.db.addcol --verbose layer=3 map=network_cat3 columns="speed double, cost double"
si noti che il parametro qlayer=1 non è specificato perchè 1 è il valore di default
> v.to.db --verbose map=network_cat3 layer=3 option=query columns=speed
qcolumn=a_SPEED
> db.execute sql="UPDATE network_cat3_3 SET cost=lungh_a/speed/1610"
Si determina per primo il percorso di lunghezza minima tra le caserme di Holly Springs
Road (categoria 52) e Fairview Road (categoria 27) con i costi dati dalla sola lunghezza
> echo "2 52 27"|v.net.path --overwrite input=network_cat3 output=path_52_27
Lo stesso percorso minimo tra le caserme di Holly Springs Road (categoria 52) e Fairview
Road (categoria 27) si calcola con i costi dati dai tempi di percorrenza di ogni tratto:
> echo "2 52 27"|v.net.path --overwrite input=network_cat3 output=path_52_27_db_cost
alayer=3 afcolumn=cost
Il nuovo percorso (in rosso) cambia rispetto a quello vecchio (in verde): il percorso più veloce
passa per le strade su cui è consentita una maggiore velocità anche se con una lunghezza
maggiore, come prevedibile.
Fasce di uguale distanza dalle stazioni dei pompieri (v.net.iso)
Si utilizza il modulo v.net.iso per dividere la rete in zone ad uguale distanza (lungo la rete
stessa) dalle caserme dei pompieri.
Dapprima si usa come costo la distanza, si suddivide la rete in zone a uguale costo di
raggiungimento, con fasce di 1000, 2000 e 5000 metri attorno alle caserme (categorie 21-52
sul layer 2 della mappa vettoriale network_cat3), creando un nuovo vettoriale network_iso i cui
vettori hanno assegnata una categoria a seconda della fascia in cui ricadono (categoria 1 per
la fascia entro i 1000 metri, 2 entro i 2000, ecc.).
Questa procedura può richiedere alcuni minuti di elaborazione:
> v.net.iso --overwrite
costs=1000,2000,5000
--verbose
input=network_cat3
output=network_iso
ccats=21-52
e si visualizza la rete (per assegnare un colore diverso ad ogni categoria delle linee scegliere
"Random colors according to category number" nel tab Colors relativo alla mappa network_iso
del Gis manager):
La parte di rete di colore grigio dista meno di 1000 metri da una delle caserme, la parte rossa tra
1000 e 2000, quella marrone tra 2000 e 5000, quella verde è oltre i 5000 metri. La parti di rete in
nero ai bordi della regione non sono raggiungibili (si ricordi che la rete stradale è stata "tagliata"
sulla regione).
Si possono determinare le fasce di distanza chiudendo New Bern Avenue (strada 6658),
inserendo un costo pari a -1. In avanti:
> db.execute sql="UPDATE network_cat3_3 SET lungh_a=-1 WHERE cat=6658"
e indietro
> db.execute sql="UPDATE network_cat3_3 SET lungh_i=-1 WHERE cat=6658"
> v.net.iso --overwrite --verbose input=network_cat3
output=network_iso_db_no_new_bern_ave ccats=21-52 costs=1000,2000,5000 alayer=3
afcolumn=lungh_a abcolumn=lungh_i
Si noti come le strade a nord di New Bern Avenue che ricadevano nella fascia rossa (10002000 metri) ora ricadono nella fascia marrone successiva (2000-5000 metri) perchè non sono
più raggiungibili attraverso New Bern Avenue.
Prima di continuare con le successive elaborazioni conviene riaprire le strade, reinserendo le
lunghezze in avanti:
> v.to.db --verbose map=network_cat3 type=line,boundary layer=3 qlayer=3 option=length
columns=lungh_a
e indietro
> v.to.db --verbose map=network_cat3 type=line,boundary layer=3 qlayer=3 option=length
columns=lungh_i
La divisione della rete si può calcolare con costi dati dai tempi di percorrenza di ogni tratto, i
limiti dei costi devono adesso essere espressi in ore anzichè metri, si scelgono come limiti degli
intervalli 0.02,0.05,0.1 ore, cioè 1.2, 3 e 6 minuti:
> v.net.iso --overwrite --verbose input=network_cat3 output=network_iso_db_cost ccats=21-52
costs=0.02,0.05,0.1 alayer=3 afcolumn=cost abcolumn=cost
Questo vettoriale individua le zone raggiungibili in 1.2, 3 e 6 minuti da una delle stazioni dei
pompieri. Si noti come la presenza di strade veloci influenzi la forma delle aree.
Zone di competenza per ogni stazione dei pompieri, in funzione
della distanza (lungo la rete stradale) dalle stazioni stesse
(v.net.alloc)
Si utilizza ora il modulo v.net.alloc per dividere la rete in zone di competenza per ogni caserma
dei pompieri in funzione del costo di percorrenza lungo la rete stradale dalle stazioni stesse.
Viene creata una nuova mappa vettoriale network_alloc in cui ogni linea ha categoria
corrispondente alla caserma dei pompieri più vicina, 1 -> caserma 21 (Trailwood Drive) , 2 ->
caserma 26 (Oberlin Road), ecc.. Utilizzando come costo la distanza:
> v.net.alloc --overwrite --verbose input=network_cat3 output=network_alloc ccats=21-52
I diversi colori indicano la caserma più vicina.
La suddivisione della rete si può fare utilizzando come costi i tempi di attraversamento:
> v.net.alloc --overwrite --verbose input=network_cat3 output=network_alloc_db_cost
ccats=21-52 alayer=3 afcolumn=cost
Si noti come cambia la suddivisione della rete!
Sottorete di minima lunghezza che collega tutti le stazioni
dei pompieri (albero minimo di Steiner) (v.net.steiner)
Si vuole determinare la sottorete di minima lunghezza che collega tutte le stazioni dei
pompieri (albero minimo di Steiner), ad esempio per collegarle, posando i cavi lungo le
strade, con una rete ad alta velocità (broadband).
Dapprima si usa come costo la distanza: viene creata la mappa vettoriale network_steiner
che contiene il percorso (albero) di lunghezza minima lungo la rete che collega tutti i punti
dati, cioè le caserme dei pompieri (categorie 21-52 sul layer 2):
> v.net.steiner --overwrite --verbose input=network_cat3 output=network_steiner tcats=21-52
Grafo minimo di steiner = sottorete di lunghezza minima che connette tutte le stazioni
La sottorete si può estrarre utilizzando come costi i tempi di attraversamento, anche se in
questo caso è poco significativo:
> v.net.steiner --overwrite --verbose input=network_cat3 output=network_steiner_db_cost
tcats=21-52 alayer=3 acolumn=cost
Si noti come la suddivisione della rete rimane la stessa!
Percorso minimo che collega tutte le caserme dei pompieri senza
passare per la stessa più di una volta (problema del commesso
viaggiatore) (v.net.salesman)
Si vuole ora calcolare il percorso minimo che collega tutte le caserme dei pompieri senza
passare per la stessa più di una volta (problema del commesso viaggiatore) per ottimizzare ad
esempio il percorso di fornitori e ispettori.
Si usa come costo la distanza, viene creata la mappa vettoriale network_salesman che contiene
il percorso di lunghezza minima lungo la rete che collega, passandoci una sola volta, tutti i punti
dati, cioè le caserme dei pompieri (categorie 21-52 sul layer 2):
> v.net.salesman
ccats=21-52
--overwrite
--verbose
input=network_cat3
output=network_salesman
La sottorete si può estrarre utilizzando come costi i tempi di attraversamento, si individua cioè il
percorso percorribile nel tempo minore:
> v.net.salesman --overwrite --verbose input=network_cat3 output=network_salesman_db_cost
ccats=21-52 alayer=3 acolumn=cost
Il percorso è cambiato, passando per strade più lunghe ma più veloci.
Questa presentazione è © 2012 Bianca Federici, Roberto Marzocchi, Domenico
Sguerso, disponibile come
http://www.creativecommons.it/Licenze