Bighouse news

"Siamo tutti in una fogna, ma alcuni di noi guardano le stelle"

Etichette avanzate in QGis

one comment

Da qualche tempo QGis permette di gestire le etichette con delle funzionalità più avanzate rispetto a quelle “standard” presenti nelle proprietà del Layer. Questa opzione, disponibile nel menù Layer -> Etichettatura o tramite l’icona nella relativa toolbar, comprende numerose opzioni sia legate allo stile sia per la gestione del posizionamento.

Nella versione che a breve verrà rilasciata, la 1.8.0, è stata aggiunta un’ulteriore funzionalità che permette di costruire le etichette sfruttando la sintassi SQL ed altre utili funzionalità.

Lo strumento, che ricordo è disponibile unicamente nella versione 1.8.0 o superiore, è accessibile nel tool Etichettatura premendo il piccolo pulsante accanto al menù per selezionare il campo da utilizzare per le etichette.

pulsante_etichette_avanzate

L'accesso avviene selezionando il pulsante a destra del menù a tendina

La parte superiore della finestra comprende l’elenco delle funzioni disponibili raggruppate per tipologia ed una guida sul loro utilizzo: ci sono funzioni per eseguire operazioni matematiche, funzioni per operare su stringhe e strumenti che permettono di ricavare parametri come area o lunghezza. La parte in basso della finestra viene invece utilizzata proprio per comporre l’espressione; è interessante osservare che man mano che si scrive il testo, questo viene validato in modo da evidenziare eventuali errori di sintassi.

etichette_avanzate

Esempio delle numerosi funzioni disponibili

Un semplice esempio

L’obiettivo è quello di realizzare un’etichetta composta da tre righe: una con il nome della Regione, una con il valore dell’area (espressa in ettari e come numero intero) e l’ultima con un testo variabile a seconda del valore dell’area. Come dati si sono utilizzati i Confini Regionali presenti nell’Atlante di geografia statistica ed amministrativa prodotto dall’ISTAT.

La prima riga è la più semplice da realizzare, ma serva a mostrare come concatenare stringhe con valori presenti nella tabella degli attributi. Basterà utilizzare l’operatore || e ricordarsi di delimitare il testo tra apici:

 'Nome: ' || NOME_REG || '\n' 

Il carattere ‘\n’ serve ad andare a capo dopo questa riga.

La riga successiva utilizza il parametro $area per ottenere l’area della geometria e la funzione toint per convertirla in numero intero. Per la conversione in ettari basterà inserire direttamente l’espressione di conversione.

 || 'Area: ' || toint($area/10000) || '\n' 

Ancora una volta tutti gli elementi sono stati concatenati (anche la riga precedente) con l’operatore || e si è andati a capo con ‘\n’. In ultimo, per complicarci un po’ le cose, inseriamo un’espressione condizionale che scrive un testo o un altro in funzione della superficie della geometria. Per questo scopo utilizziamo la sintassi CASE WHEN espressione THEN testo se vera ELSE testo se falsa END.

 || CASE WHEN ( $area/10000 > 600000) THEN 'Pippo' ELSE 'Pluto' END 
risultato_etichette

L'espressione completa

umbria_etichetta

L'etichetta relativa all'Umbria

Share this article

Written by Luca

maggio 8th, 2012 at 10:28 pm

Posted in qgis

GeoNode: favorire la condivisione e l’utilizzo dell’informazione geografica

one comment

Lo sviluppo tecnologico per la pubblicazione di dati territoriali in rete ha fatto notevoli passi avanti anche in relazione alla possibilità di utilizzarle senza specifiche competenze informatiche. Un caso è sicuramente quello di chi ha intensione di pubblicare un proprio elaborato, magari in formato ESRI ShapeFile oppure in GeoTIFF, all’interno di un sito Web.

In questo contesto si inserisce GeoNode che permette con pochi e semplici passaggi di caricare un proprio dato, stilizzarlo ed utilizzarlo per comporre uno strumento  WebGIS.

Sulle spalle dei giganti

GeoNode è quello che può definirsi un mix di strumenti tecnologici nato per favorire la diffusione dell’informazione geografica mediante un’interazione diretta con gli utenti. Parlo di mix perché ritroviamo:

Django si occupa di lavorare come “collante” tra i vari strumenti, gestendo le credenziali di accesso degli utenti oppure l’archiviazione dei parametri che costituiscono i singoli WebGIS creati. GeoServer genera i servizi necessari alla visualizzazione del dato e GeoNetwork gestisce la ricerca ed i metadati. Aggiungo anche gsconfig, una libreria scritta in Python ed utilizzabile per la configurazione di GeoServer.

Per provare  gli argomenti illustrati, si può utilizzare il sito demo di GeoNode.

Ricerca e caricamento di dati

Ricercare dati territoriali è l’operazione più comune che viene svolta. Basta selezionare la voce Dati per accedere alla funzionalità di ricerca:

  • Semplice in cui viene richiesto solo uno o più termini;
  • Avanzata dove è possibile specificare una Bounding Box per limitare l’area di ricerca;
Al termine della procedura viene mostrato l’elenco dei risultati come visualizzato nell’immagine seguente.

Risultati di una ricerca effettuata con procedura avanzata

Qui si nota un’importante funzionalità del sistema e cioè la possibilità di limitare l’accesso ad un singolo dato solo ad utenti/gruppi stabiliti da chi lo ha caricato.
Se si fa click sul dato di interesse si visualizza una pagina riassuntiva che contiene una mappa con un’anteprima del dato stesso, dei collegamenti per scaricarlo in differenti formati e degli strumenti per la gestione dello stile.
Il caricamento di nuovi dati è disponibile nella schermata Dati solo dopo che ci si è autenticati nel sistema;  il primo passo è il caricamento dei vari file che costituiscono il dato territoriale e di altre informazioni facoltative come lo stile o un piccolo abstract descrittivo. Terminato con successo l’upload una maschera ci chiederà di compilare i metadati ed il gioco è fatto. In qualsiasi momento, in quanto proprietari del dato, potremo modificare i permessi di accesso oppure lo stile ad esso associato.

Creazione di nuove mappe

Una delle funzionalità di GeoNode che più mi ha convinto, è la possibilità di creare dei veri e propri WebGIS utilizzando sia i dati presenti nel sistema (quindi quelli che si sono caricati seguendo la procedura al precedente paragrafo), sia provenienti da servizi WMS di terze parti. Questa opzione è accessibile mediante la voce Mappe del menù principale e, al fine di salvare il lavoro, prevede che l’utente sia registrato come nel caso dell’upload.

Selezionando l’opzione aggiungi un nuovo layer presente nella toolbar, viene mostrata una maschera con tutti i layer già archiviati in GeoNode e di cui l’utente ha diritti di accesso. Scegliendo l’opzione  Add a WMS Server si può invece aggiungere un nuovo server WMS per caricare i dati in esso disponibili.

map_geonode

Aggiunta di un nuovo layer

L’editor di mappe contiene altri strumenti utili come la gestione degli stili dei layer caricati, la possibilità di stampare la mappa visualizzata e l’utilizzo, ahimè non disponibile per Linux, del plugin di Google Earth per il Browser. Altra opzione sicuramente utile è la possibilità di visualizzare un codice HTML che contiene un iframe da piazzare in una qualsiasi pagina web per visualizzare la mappa che si è appena realizzata.

In conclusione

GeoNode ha sicuramente apportato un grosso contributo nella semplificazione delle procedure di distribuzione ed utilizzo dell’informazione geografica. Pensare che un qualsiasi utente senza alcuna conoscenza di servizi Web, Javascript, HTML, può caricare il proprio eleborato, stilizzarlo ed usarlo per creare un suo WebGIS è veramente un grosso passo avanti.

Ovviamente GeoNode è utile anche per gli amministratori che già lavorano con questo tipo di servizi. Basti pensare che i singoli permessi impostati sul dato caricato, vengono automaticamente associati anche quando si accede al sistema mediante servizi WMS o che l’archiviazione dei dati può essere fatta all’interno di un database PostGIS.

Attualmente lo sto utilizzando come GeoPortale per un progetto gestito da un’ente pubblico e devo dire che sono rimasti tutti molto contenti delle funzionalità che offre :)

Share this article

Written by Luca

gennaio 25th, 2012 at 11:11 pm

Posted in geonode

pyWPS ed OpenLayers: un servizio WPS tutto compreso!

leave a comment

Premessa

L’articolo descrive come realizzare un servizio WPS per generare un buffer di un dato vettoriale partendo dalla geometria e dalla distanza. Il materiale è ripreso dal talk svolto durante il FOSS4G 2010 e necessita di concetti base su Python, OpenLayers e pyWPS. Si presuppone di lavorare con Ubuntu 10.04.

Scaricare ed installare pyWPS

Al fine di utilizzare le ultime funzionalità presenti in pyWPS,  in questa guida utilizzeremo la versione di sviluppo.  Per scaricarla dovremo aver installato il pacchetto subversion recuperabile tramite apt-get. Se non ce l’abbiamo già installato, digitiamo:

sudo apt-get install subversion 

Posizioniamoci nella cartella /tmp/ ed eseguiamo il seguente comando:

cd /tmp/ && svn checkout https://svn.wald.intevation.org/svn/pywps/trunk

A questo punto possiamo procedere con l’installazione:

 cd trunk && sudo python setup.py install 

Ora installiamo alcuni pacchetti necessari all’esecuzione di pyWPS e del processo:

sudo apt-get install python-xml python-magic python-gdal

Creazione delle cartelle necessarie, del file di configurazione e del wrapper CGI

PyWPS può essere configurato in modo da eseguire differenti servizi WPS. Ogni servizio necessita semplicemente di una directory dove sono presenti i processi disponibili ed un file di configurazione. Nell’esempio useremo la cartella /usr/local/wps/ per ospitare il nostro servizio.
Creiamo la cartella per contenere i processi:

 sudo mkdir -p /usr/local/wps/processes

Creiamo la cartella per i file temporanei

 sudo mkdir -p /var/www/tmp/wps && sudo chmod -R 777 /var/www/tmp/

Creiamo il file di configurazione usando il template presente in pyWPS

 cp /tmp/trunk/pywps/default.cfg /usr/local/wps/pywps.cfg 

Facendo riferimento al numero di riga, modifichiamo il file di configurazione appena copiato:

serveraddress=http://localhost/cgi-bin/pywps.cgi

outputUrl=http://localhost/tmp/wps
outputPath=/var/www/tmp/wps

A questo punto dobbiamo creare uno script CGI in cui impostiamo le variabili PYWPS_CFG e PYWPS_PROCESSES che spcificano il percorso al file di configurazione e alla cartella contenente i processi. Il file va creato nella cartella cgi-bin del nostro web server (di solito /usr/lib/cgi-bin).

 sudo touch /usr/lib/cgi-bin/pywps.cgi

Ecco il contenuto dello script:

#!/bin/sh
# Author: Jachym Cepicky
# Purpose: CGI script for wrapping PyWPS script</span></li>
# Licence: GNU/GPL</span></li>
# Usage: Put this script to your web server cgi-bin directory, e.g.</span></li>
# /usr/lib/cgi-bin/ and make it executable (chmod 755 pywps.cgi)</span></li>
export PYWPS_CFG=/usr/local/wps/pywps.cfg</span></li>
export PYWPS_PROCESSES=/usr/local/wps/processes/
/usr/local/bin/wps.py $1

Rendiamolo eseguibile

 sudo chmod 755 pywps.cgi

Per verificare la corretta installazione, apriamo il seguente indirizzo:

http://localhost/cgi-bin/pywps.cgi?request=GetCapabilities&service=WPS

In caso positivo, l’xml mostrato descriverà le informazioni sul nostro servizio WPS

Processo per la creazione del buffer

Il processo che utilizzeremo permette di generare un buffer delle feature presenti in un dato vettoriale; come input necessita del dato (che noi invieremo come formato GML) e dell’ampiezza del buffer. Questo tipo di elaborazione può venir svolta in differenti modi, ad esempio passando per GRASS, ma noi utilizzeremo OGR al fine di limitare il numero di pacchetti da installare.

Il processo è disponibile nella cartella di esempio, per cui copiamolo come abbiamo fatto in precedenza ed aggiorniamo il file __init__.py

 sudo cp /tmp/trunk/tests/processes/buffer.py /usr/local/wps/processes/
cd /usr/local/wps/processes/
sudo echo "__all__=['ultimatequestionprocess','buffer']" > __init__.py

A questo punto facciamo alcune modifiche al processo così da adattarlo al tutorial. Occhio al numero di riga e all’indentazione.

Aggiungiamo:

type=type(0.0), 
size = self.size.getValue()

Modifichiamo:

buff = inGeometry.Buffer(size)

La prima modifica serve a permettere valori decimali per il raggio di buffer, la seconda e la terza corregge lo script in modo da utilizzare effettivamente il valore passato come input (altrimenti usava 1000).
Verifichiamo che il processo sia stato aggiunto correttamente eseguendo una richiesta DescribeProcess:

http://localhost/cgi-bin/pywps.cgi?request=DescribeProcess&service=WPS&identifier=buffer&version=1.0.0

Lanciamo il processo prendendo dei dati di esempio presenti in rete. Eseguiamola in due differenti modi per vedere due differenti modalità  con cui il WPS può restituire i risultati

http://localhost/cgi-bin/pywps.cgi?service=wps&version=1.0.0&request=execute&identifier=buffer&datainputs=[size=1;data=http://apps.esdi-humboldt.cz/classification/traning_areas/training_areas_en.gml]&responsedocument=buffer=@asreference=true
http://localhost/cgi-bin/pywps.cgi?service=wps&version=1.0.0&request=execute&identifier=buffer&datainputs=[size=10;data=http://apps.esdi-humboldt.cz/classification/traning_areas/training_areas_en.gml]

Come si vede, nella prima richiesta abbiamo aggiunto la proprietà asreference=true ed il risultato è un link all’output generato, mentre nell’altro caso l’output è presente direttamente nel documento generato dal servizio.

Configurazione di OpenLayers

Configurazione OpenLayers

pyWPS include anche una libreria Javascript basata su OpenLayers che permette di semplificare la gestione di chiamate effettuate ad un servizio WPS. Copiamo il file WPS.js dalla cartella di pyWPS alla root di apache:

sudo cp /tmp/trunk/webclient/WPS.js /var/www/

A questo punto configuriamo la parte relativa ad OpenLayers: per questo esempio, che ricordo consiste nel creare un buffer di un poligono disegnato sopra la mappa, abbiamo bisogno di un layer base, un vettoriale per disegnare il poligono ed uno per contenere il buffer di output.

Posizioniamoci nella cartella /var/www/ e creiamo un nuovo file HTML chiamato ad esmpio wps.html.

cd /var/www/ && sudo touch wps.html

A questo punto iniziamo a modificarlo inserendo le varie parti descritte di seguito:

<html xmlns="http://www.w3.org/1999/xhtml">
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<script src="WPS.js"></script>
<script type="text/javascript">
var lon = 5;
var lat = 40;
var zoom = 5;
var map,layer,vlayer,rlayer;

function init(){
    layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
              "http://labs.metacarta.com/wms/vmap0",
              {layers: 'basic'} );
    vlayer = new OpenLayers.Layer.Vector("Editable");
    map = new OpenLayers.Map( 'map', {
                 controls: [
                     new OpenLayers.Control.PanZoom(),
                     new OpenLayers.Control.EditingToolbar(vlayer),
                     new OpenLayers.Control.LayerSwitcher()
                 ]
             });
    map.addLayers([layer, vlayer]);
    map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);
}

Tramite OpenLayers generiamo una semplice mappa ed aggiungiamo la possibilità di disegnare a mano delle features (layer vlayer).

var onWPSClicked = function() {

    //Istanziamo la classe WPS impostando l'indirizzo del server WPS e la funzione da eseguire in caso di elaborazione corretta.
    var wps = new OpenLayers.WPS("http://localhost/cgi-bin/pywps.cgi",{onSucceeded: onWPSSussceeded});

    //Definiamo gli input usando i nomi presenti nel processo (data e size)
    var data = new OpenLayers.Format.GML();
    var dataInput = new OpenLayers.WPS.ComplexPut({
                    identifier:"data",
                    value:  data.write(vlayer.features)
                    });

    var sizeInput = new OpenLayers.WPS.LiteralPut({
                    identifier:"size",
                    value: document.getElementById("radius").value
                    });
    //Definiamo anche l'output, sempre con l'identificativo utilizzato dal processo (buffer)
    var complexOutput = new OpenLayers.WPS.ComplexPut({
                    identifier: "buffer",
                    asReference: "true"
                    });

    //Definiamo il processo ed associamogli l'input e l'output appena creati

    var returnerProcess = new OpenLayers.WPS.Process({
                        identifier: "buffer",
                        inputs: [dataInput,sizeInput],
                        outputs: [complexOutput] });
    wps.addProcess(returnerProcess);
    //Eseguiamo il processo
    wps.execute("buffer");
}

Questa seconda parte definisce gli elementi del processo che andremo ad eseguire. Tutti i nomi dei parametri di input e di output, nonchè le loro caratteristiche, sono presenti nella richiesta DescribeProcess che è sempre bene effettuare prima dell’esecuzione del processo.

var onWPSSussceeded = function(process) {
try {
        map.removeLayer(rlayer);
        rlayer.destroy();
} catch(e) {}
        url = process.getOutput("buffer").value;
        rlayer = new OpenLayers.Layer.GML("Result",url);
        map.addLayer(rlayer);
};
</head>

Questa è la funzione che viene eseguita se il processo è svolto correttamente. Non fa altro che rimuovere l’output di precedenti elaborazioni, prendere il risultato (buffer) fornito da pyWPS, creare un nuovo layer GML ed aggiungerlo alla mappa.

<body onLoad="init()">
    <div id="map"></div>
Raggio: <input type="text" value="1" id="radius" size="4">
<input type="button" onClick="onWPSClicked();" value="WPSit!">
</body>
</html>

La parte HTML serve a generare la mappa e ad  inserire un input per il valore del raggio ed  un pulsante per avviare l’elaborazione. E’ bene precisare che il sistema di riferimento della mappa è il WGS84 per cui il valore del raggio deve essere compatibile con questo sistema di riferimento (10 gradi sono una bella distanza :) ).

Conlcusione

L’esempio vuole mostrare come sia semplice realizzare un servizio WPS completo della parte Server e della parte Desktop. Maggiori informazioni si possono trovare sul sito di OpenLayers, su quello di pyWPS e sul wiki usato per il materiale del FOSS4G 2010.

Share this article

Written by Luca

gennaio 14th, 2011 at 9:59 pm

Posted in Senza categoria,WPS

Creare filtri personalizzati in Django

leave a comment

Una delle funzionalità che mi ha colpito la prima volta che ho messo le mani su Django, è la possibilità di creare layout personalizzati tramite i filtri all interno dei template. Se ad esempio voglio che una variabile chiamata temperatura, venga arrotondata ad una sola cifra decimale, sarà sufficiente scrivere:

{{temperatura|floatformat:1}}

I filtri a disposizione sono numerosi, ma può capitare (come successo oggi a me) di doverne creare qualcuno da zero.

Creazione della funzione filtro

Per prima cosa creiamo una cartella templatetags nella cartella della vostra applicazione; a questo punto, usando il comando touch creiamo un file __init__.py ( per far si che la cartella sia vista come un pacchetto) e un custom_filters.py (nome di esempio) dove verrà specificata la funzione da usare come filtro.

dati/
    models.py
    templatetags/
        __init__.py
        custom_filters.py
    views.py

A questo punto andiamo a creare la funzione filtro modificando il file custom_filters. Per prima cosa, affinchè il filtro sia valido, scriviamo:

from django import template
register = template.Library()

A questo punto definiamo la funzione, tenendo presente che possiamo passare uno o due argomenti: la variabile a cui applicare il filtro ed un valore da utilizzare nel filtro:

def cut(value, arg):
    "Removes all values of arg from the given string"
    return value.replace(arg, '')

Applicare il filtro

Una volta creato, bisogna registrare il filtro nell’instance di Libray: questo può essere fatto con il decorator @register, messo prima della definizione della funzione:

@register.filter(name='cut')

L’ultimo passo per poter usare il filtro nel template, è quello di caricarlo con il tag {% load%}. All’inizio del nostro template scriviamo:

{% load custom_filters %}

Share this article

Written by Luca

dicembre 13th, 2010 at 10:06 pm

Posted in Django

Visualizzare Google Maps (e molto altro..) in QGis

one comment

QGis offre la possibilità di visualizzare numerose sorgenti dati: raster, vettoriali, servizi W*S oppure database PostgreSQL o SpatiaLite. Grazie ad un plugin Python chiamato “OpenLayers Plugin”, è possibile visualizzare anche dati provenienti da:

  • Google
  • Yahoo
  • OpenStreetMap

Abilitare il plugin

Il plugin si trova nel repository Sourcepole che può essere aggiunto selezionando l’opzione “Aggiungi repository di terze parti”. Ricordo che per eseguire questa operazione bisogna accedere al menù plugin, scegliere la voce Recupero Plugin Python, e qui premere il pulsante Aggiungi repository di terze parti.

Aggiunta plugin di terze parti

Aggiunta dei repository di terze parti

Utilizzo

Dopo averlo abilitato verrà aggiunta una voce OpenLayers Plugin direttamente nel menù plugin; tramite questo menù è possibile aggiungere i layer che vogliamo visualizzare.

Aggiungere un nuovo layer

Aggiungere un nuovo layer

Note conclusive

Quando viene aggiunto un nuovo layer  il sistema di riferimento del progetto viene automaticamente impostato a EPSG:900913. Questo comporta che tutti dati i aggiunti successivamente dovranno avere lo stesso sistema di riferimento o, nel caso contrario, venir riproiettati. Per i dati vettoriali il problema non si pone in quanto QGis effettua automaticamente la riproiezione, a patto di aver impostato correttamente lo SRS del layer. I dati raster dovranno invece essere riproiettati prima di venir aggiunti al progetto: in questo caso possiamo usare il plugin Gdal Tools presente anch’esso in QGis.

Bisogna sempre ricordarsi che le operazioni di riproiezione vanno effettuate tenendo conto dei parametri towgs84. Se ad esempio lavoriamo con un dato in Gauss Boaga Roma40 Fuso 2 (EPSG:3004), la stringa proj associata è:

+proj=tmerc +lat_0=0 +lon_0=15 +k=0.9996 +x_0=2520000 +y_0=0 +ellps=intl +units=m +no_defs

Questa però porta ad un errore di riproiezione di circa 30-40 m. La stringa proj con i parametri towgs84 è invece:

+proj=tmerc +lat_0=0 +lon_0=15 +k=0.9996 +x_0=2520000 +y_0=0 +ellps=intl +units=m +towgs84=-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68 +no_defs

Creando un nuovo sistema di riferimento personalizzato ed associandolo al layer si riducono al minimo errori di riproiezione.

Senza parametri towgs84 nella stringa proj

Senza parametri towgs84 nella stringa proj

Con parametri togwgs84

Con parametri towgs84 nella strina proj

Share this article

Written by Luca

ottobre 1st, 2010 at 9:54 am

Posted in plugin,qgis

Switch to our mobile site