Come prometto a vuoto da mesi, finalmente mi voglio mettere a scrivere un articolo per spiegare un sistema completamente automatico mediante script bash per generare una mappa a partire dai dati di OpenStreetMap. Lo script è un allegro guazzabuglio di utility da riga di comando destinate a scaricare i dati dal server OSM sotto forma di xml, “compilarli” per generare un file SVG, convertire tale file in un PNG e aggiungerci qualche particolare utile: un header, un footer con il copyright, un frame di contorno e una scala kilometrica. Questo articolo, come i miei fedeli lettori avranno già intuito, nasce da una fusione di precedenti post: questo, questo, questo, questo.
Per iniziare i requisiti:
- Avremo bisogno di un computer linux connesso alla rete (e fin qui…); io uso Ubuntu, non posso garantire il funzionamento di tutte le utility richiamate da questo script su altre piattaforme, anche se probabilmente su Mac si può fare (se qualcuno ci prova mi faccia sapere che aggiornerò l’articolo). Ovviamente Windows non è neanche preso in considerazione.
- Avremo bisogno di queste utility, scaricabili dal repository: xsltproc (nell’installazione di default, a quanto mi risulta), wget (idem), convert+composite (nella suite ImageMagick), bc.
- Avremo bisogno del programma per calcolare la distanza in chilometri tra due punti espressi in coordinate GPS, di cui ho parlato in precedenza (in questo post, nella sezione “un programma in C”). Copiarlo in un editor di testo, compilarlo seguendo le istruzioni nel post e avere cura che l’eseguibile si chiami “calcola” (senza alcuna estensione), non “converti” come nell’esempio.
- Per finire, avremo bisogno di una serie di files da scaricare dai repository di openstreetmap, che ci serviranno per compilare la mappa vera e propria.
In riferimento all’ultimo punto dell’elenco, avremo bisogno di un ambiente di lavoro costituito dalla seguente struttura di cartelle:
data
|– osm-map-features-z17.xml
|– calcola
|– renderizza (così chiameremo lo script che andremo a utilizzare)
|– osmarenderer.xsl
stylesheets
|– symbols
|– il contenuto di questa cartella
Uhm.. dovremmo avere tutto, spero di non aver dimenticato nulla.. Per semplificarvi la vita, ho provveduto a uppare su una condivisione box.net uno zip con tutto il necessario per cominciare a renderizzare (sempre se non mi sono dimenticato nulla); scaricate pure qui. A questo punto manca solo lo script, che come ho detto prima si chiamerà, con molta fantasia, “renderizza” (beh, potete anche cambiargli il nome).
Ecco dunque l’agognato script, pezzo per pezzo:
Impostiamo un pò di variabili che ci verranno buone per dopo. Le uniche da modificare sono ovviamente le coordinate GPS (latitudine e longitune) della zona che vogliamo inserire nella mappa
# coordinate gps zona
# nb: max 0.25 gradi sia latitudine che longitudine
MAXLAT=45.8239
MINLAT=45.8045
MAXLON=10.0841
MINLON=10.0584
# nomi file
OSM=”data.osm” # nome del file dati OSM
SVG=”map.svg” # nome dell’output in formato svg
PNG=”map.png” # nome dell’output in formato png
Recuperiamo i dati aggiornati:
echo “recupero dati dal server OSM…”
wget -O ${OSM} http://api.openstreetmap.org/api/0.5/map?bbox=$MINLON,$MINLAT,$MAXLON,$MAXLAT
Eseguiamo il rendering:
# livello del rendering
livello=17
# identifica il livello di dettaglio del rendering;
# per aree piccole conviene usare il livello 17;
# per eseguire il rendering sarà richiesto il
# file osm-map-features-zXX.xml (XX = livello).
echo “rendering mappa..”
xsltproc osmarender.xsl osm-map-features-z${livello}.xml > ${SVG}
Convertiamo la mappa (in formato SVG) in un file grafico PNG, più facilmente utilizzabile:
# —- conversione mappa in png
density=600 # risoluzione del file grafico.
scale=1000 # dimensione in px del file grafico
echo “conversione in PNG…”
convert -density ${density} -scale ${scale} ${SVG} ${PNG}
Aggiungiamo un header con un testo a scelta. In questo caso inserisco il mio nome e la data dell’aggiornamento (ovvero la data corrispondente al file dati).
# —- aggiunta header
echo “aggiunta della data alla cartina..”
convert xc:white -resize 1×15! blank.ppm
convert -append blank.ppm ${PNG} intermediate.ppm
convert intermediate.ppm -gravity “North” -draw “text 0,3 ‘Updated on: $(date -r ${OSM}) by PicciMario’” ${PNG}
rm blank.ppm intermediate.ppm
Aggiungo un footer con un copyright OSM.
# —- aggiunta footer
echo “aggiunta copyright alla cartina..”
convert xc:white -resize 1×20! blank.ppm
convert -append ${PNG} blank.ppm intermediate.ppm
convert intermediate.ppm -gravity “South”
(continua) -draw “text 0,3 ‘Copyright 2008 OpenStreetMap (openstreetmap.org)’” ${PNG}
rm blank.ppm intermediate.ppm
La parte più incasinata: creo il simbolo della scala e lo inserisco nella mappa
# —- aggiunta scala
echo “aggiunta scala 1km”
# calcola larghezza in km della mappa
larghezza=$(./calcola $MINLON, $MAXLON, $MINLAT, $MINLAT )
# misura la larghezza in px della mappa
larghezzapixel=$(identify -format %w $PNG)
# calcola l’equivalenza px/km
pixel1km=$(echo “$larghezzapixel/$larghezza” | bc)
# creazione simbolo scala
framewidth=1
scalesymbol=scale.png
scaleheight=10
scalecolor1=xc:blue
scalecolor2=xc:white
pixel100m=$(echo “($pixel1km-(2*framewidth))/10″ | bc)
convert ${scalecolor1} -resize ${pixel100m}x${scaleheight}! block1.ppm
convert ${scalecolor2} -resize ${pixel100m}x${scaleheight}! block2.ppm
convert +append block1.ppm block2.ppm block1.ppm block2.ppm block1.ppm block2.ppm block1.ppm block2.ppm block1.ppm block2.ppm ${scalesymbol}
convert -mattecolor blue -frame ${framewidth}x${framewidth} ${scalesymbol} ${scalesymbol}
rm block1.ppm block2.ppm
# aggiunta del simbolo alla cartina
composite -geometry +10+30 -gravity southwest ${scalesymbol} ${PNG} ${PNG}
rm ${scalesymbol}
E per finire l’aggiunta di un bordino blu di rifinitura.
# —- aggiunta frame di contorno al file completo
echo “aggiunta frame…”
convert -mattecolor blue -frame 1×1 ${PNG} ${PNG}
echo “operazione completata.”
Facile, no? Si, lo so, è abbastanza contorto.. Ma ha l’innegabile vantaggio che, una volta pronto, non devo fare altro che andare nella cartella, scrivere ./renderizza e lui fa tutto e mi presenta la bellissima cartina completa.
Ad esempio, mi piacerebbe metterlo nel cron del mio server per mostrare su una pagina web la cartina del mio paese con aggiornamenti giornalieri (peccato che il mio server è un computer di 10 anni fa e per fare il rendering ci mette 20 minuti). Se poi pensiamo alla possibilità di modificare il file xml (osm-map-features ecc..), che descrive il modo in cui la mappa è creata, possiamo ottenere infinite potenzialità di personalizzazione della mappa da noi creata (modificare i simboli, le dimensioni e i colori delle strade, scegliere cosa inserire e cosa no, …).
Beh, per oggi mi accontento di questo.. Fatemi sapere se il sistema vi piace e in caso mandatemi un link delle vostre opere d’arte
Ciao a tutti!





