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