v.out.ogr input=roads type=line,boundary dsn=/home/ubuntu olayer=roads layer=1 format=ESRI_Shapefile
PostGIS fornisce un programma per trasformare le informazioni contenute da formato ESRI Shape ad un file di testo contenente gli SQL-statement che popoleranno la tabella nel database. I comandi da eseguire in una shell, una volta posizionatisi nella directory dove risiede lo shapefile sono:shp2pgsql -I -s 32767 roads roads2postgis > roads.sql
La flag "-I" crea automaticamente un indice di tipo GiST (Generalized Search Tree ) sulla colonna contenente le geometrie: ciò aumenta notevolmente la performance delle query su dati geografici in quanto, attraverso l'uso delle boundingbox, permette di effettuare le ricerce su subsets di dati (per contro v.out.ogr non crea in automatico l'indice sulla colonna delle geometrie). La flag "-s" con il relativo numero associa ai dati geografici un preciso datum (in questo caso quello della location Spearfish, NAD27 - Utm zona 13), roads è il nome dello shapefile, roads2postgis è il nome della tabella che verrà creata, roads.sql è il nome del file di testo contenente gli SQL-statements. Si procede quindi al caricamento dei dati nel database in un terminale (in GRASS o meno):psql -d spearpg -U grass -f roads.sql
Osservando con pgAdmin la tabella geometry_columns si nota come le colonne abbiano nomi diversi a seconda del meccanismo di esportazione dei dati: "the_geom" nel caso di shape2pgsql (loader), "wkb_geometry" nel caso dell'OGR (cioè per fields2postgis).SELECT srid,proj4text FROM spatial_ref_sys WHERE srid=32767;
che restituiscesrid | proj4text -------+------------------------------------------------------------------ 32767 | +proj=utm +zone=13 +ellps=clrk66 +datum=NAD27 +units=m +no_defs (1 row)
SELECT label AS descrizione, the_geom AS coordinate FROM roads2postgis WHERE label ~ 'primary highway' LIMIT 1;
ottenendo:
descrizione | coordinate
-------------------------------+--------------------------------------------------------------
primary highway, hard surface | 0105000020FF7F000001000000010200000003000000D7E164E20C2322...
Il formato risulta inintelleggibile, aiuta quindi la funzione di trasformazione delle geometrie AsText():
SELECT label AS descrizione, AsText(the_geom) AS coordinate FROM roads2postgis WHERE label ~ 'primary highway' LIMIT 1;
che restituisce:
descrizione | coordinate
-------------------------------+--------------------------------------------------------------
primary highway, hard surface | MULTILINESTRING((594310.44217592 4925247.08617608,594308.8...
SELECT sum(st_length(the_geom))/1000 AS km_roads FROM roads2postgis WHERE label='unimproved road';
In questo caso si crea un dato aggregato selezionando tutti e 153 i sentieri immagazzinati (con label='unimproved road') nel database. Per ogni tratto estratto viene calcolata la lunghezza che viene poi sommata.
km_roads
------------------
136.313999118462
Si vuole produrre l'elenco delle 10 più grandi particelle fondiarie di Spearfish ordinate per grandezza:
SELECT ogc_fid as particella, owner as proprietario, st_area(wkb_geometry)/10000 AS superficie FROM fields2postgis ORDER BY superficie DESC LIMIT 10;
Questa query combina una condizione sull'attributo ed una di calcolo spaziale:
particella | proprietario | superficie
------------+--------------------------+------------------
24 | Black Hills Natl. Forest | 11651.4876800005
38 | D. Portillo | 503.438798999917
1 | P. Biggam | 305.164704499996
25 | R. Reed | 292.013480499935
62 | B. Cartwright | 282.227241999912
21 | G. Tandy | 278.218926000047
9 | D. Liston | 262.542519000065
5 | P. Biggam | 262.541994500053
48 | C. Krenshaw | 230.196791000044
40 | D. Seagall | 196.777930999994
Pur essendo Mr.Portillo il detentore del record "il fondo più grande", si vede che Mr.Biggam non se la cava poi così male, detenendo una superficie totale maggiore, almeno tra le prime 10.
Dai dati precedenti siamo incuriositi sull'effettiva disponibilità di terreno agricolo (in ettari) di Mr. Biggam.
SELECT owner AS proprietario, sum(st_area(wkb_geometry))/10000 AS superficie FROM fields2postgis GROUP BY owner HAVING owner~'Biggam';
Per rispondere a questa domanda si e' dovuto calcolare l'area di ogni singolo poligono. Se dovessimo compiere spesso questo calcolo avrebbe senso aggiungere una colonna AREA alla tabella ed un ulteriore indice per migliorare le prestazioni della query.
proprietario | superficie --------------+------------------ P. Biggam | 891.545676000082
Qual e' la lunghezza dei sentieri contenuti all'interno di ogni proprietà?
SELECT f.owner AS proprietario, sum(st_length(r.the_geom))/1000 AS km_sentieri FROM fields2postgis AS f, roads2postgis AS r WHERE r.the_geom && f.wkb_geometry AND st_contains (f.wkb_geometry, r.the_geom) GROUP BY f.owner ORDER BY km_sentieri;
Questo e' un esempio di "spatial join" poiche' stiamo unendo i dati da due tavole (join) usando una condizione di interazione spaziale (st_contains) come condizione di join piuttosto che il tradizionale approccio di compiere un join tra tavole usando una chiave comune:
proprietario | km_sentieri
--------------------------+--------------------
P. Biggam | 0.0730895522860136
D. Seagall | 0.463857456898311
C. Mitchell | 1.05953562101462
Black Hills Natl. Forest | 75.190978824988
(4 rows)
Il piano regolatore di Spearfish prevede che i sentieri agricoli vengano trasformati in strade. La larghezza delle strade (compresa dell'area di rispetto) è di 6m. Si agirà per esproprio. Considerando che il valore del terreno agricolo a Spearfish è di 35$ al mq si vuole stimare a quanto ammonterà l'indennizzo per Mr. Mitchell.
SELECT f.owner AS proprietario, round(sum(st_length(st_intersection(r.the_geom,f.wkb_geometry)))) AS lunghezza_strada, round(sum(st_area(st_buffer(st_intersection(r.the_geom,f.wkb_geometry),3)))) AS area_esproprio, round(sum(st_area(st_buffer(st_intersection(r.the_geom,f.wkb_geometry),3)))*35) AS valore_terreno FROM roads2postgis AS r, fields2postgis AS f WHERE r.the_geom && f.wkb_geometry AND intersects(r.the_geom, f.wkb_geometry) AND f.owner = 'C. Mitchell' AND r.label = 'unimproved road' GROUP BY f.owner HAVING f.owner = 'C. Mitchell';
Il risultato della query è:
proprietario | lunghezza_strada | area_esproprio | valore_terreno --------------+------------------+----------------+---------------- C. Mitchell | 1420 | 8659 | 303081 (1 row)
La domanda ora è: mr.Mitchell si arrabbierà?