21 settembre, 2009 | di

pencilUltimamente mi è stato richiesto un applicativo di webmapping che mettesse chiunque (o quasi…) in condizione di gestire agevolmente un geodatabase, aggiornando nel tempo le informazioni contenute, comprese le feature geografiche. In due parole: un gestionale web, ma con delle funzionalità proprie dei GIS desktop.
Il committente ha richiesto una soluzione open source ed io sono stato ben contento di proporre il rodato quartetto composto da UMN-Mapserver, PostGIS, PHP e MapFish.
In passato avevo già realizzato qualcosa di simile, ma si trattava di inserire dei punti a partire da una coppia di coordinate, operazione semplicissima grazie a PostGIS. Questa volta era necessario che l’utente disegnasse le geometrie online, direttamente nella finestra del browser, ed ho colto l’occasione per dare finalmente un’occhiata alle funzioni di editing vettoriale di OpenLayers 2.8. Ne sono rimasto estremamente soddisfatto, come sempre avviene quando si tratta di OpenLayers.
Scorrendo la pagina degli esempi ed inserendo il filtro “vector”, ci si rende subito conto della potenza dei controlli dedicati all’editing.

Grazie agli esempi, che coprono quasi tutto lo spettro delle possibilità, è stato facile produrre la parte client del mio lavoro.
L’editor ottenuto è adattabile a qualsiasi back-end “spatial enabled”, è indipendente dal mapserver scelto per pubblicare i dataset online, dal geodbms usato per contenerli e dal linguaggio di programmazione lato server.
Il cuore del client è costituito dalle funzioni presentate in questo esempio, che consentono di disegnare una feature da serializzare sotto forma di stringa in ben 6 formati standard differenti. Ottenuta la stringa, il gioco è fatto: uno script lato server si occupa di recuperarla e lanciare una query di inserimento nel geodabase (ci sono, come sempre, anche altre soluzioni).
L’operazione inversa, vale a dire deserializzare una stringa ed ottenere una feature, è ugualmente possibile e può essere molto utile.
Per esempio, volendo rifinire degli shapefile su una base Google Maps o Openstreetmap, basta trasformarli KML (o in uno degli altri 5 formati supportati), aprire il file con un editor di testo e, infine, copiare ed incollare il contenuto dentro la textarea del nostro editor. A questo punto si è liberi di modificare a piacimento le feature importate.
Questo è solo un esempio grezzo di import, dispobile “out of the box”, ma una volta collegato l’editor ad un back-end spaziale si può dare sfogo alla fantasia e creare delle funzioni di importazione più raffinate.

vector editing con openlayers

Cliccando qui potete vedere una versione super-generica del client di editing da me realizzato. Ho usato MapFish 1.1[1] per dare un aspetto un po’ più carino[2] al tutto ed ho modificato il codice degli esempi affinché le diverse funzioni di editing potessero essere attivate da una toolbar invece che da una serie di checkbox e radiobutton. I commenti nel codice dovrebbero essere abbastanza esplicativi.

[1] Si tratta di una versione leggermente modificata in cui ho sostituito OpenLayers 2.7 con OpenLayers 2.8

[2] Qualcuno potrebbe cimentarsi con Dojo o jQuery… sono sicuro che non verrebbe affatto male ;)

Nota
Devo scusarmi con i lettori di TANTO iscritti al feed RSS.
Stamattina ho accidentalmente cliccato sul bottone “Pubblica” mentre scrivevo la bozza e nonostante mi sia precipitato a recuperare, non sono riuscito ad evitare che l’articolo incompleto finisse nel feed. Per farmi perdonare mi sono incollato al computer ed ho fatto il possibile per finire l’articolo e la demo alla svelta! In futuro starò più attento a dove clicco e soprattutto non inizierò a scrivere bozze di domenica mattina prima di colazione! :)

23 aprile, 2009 | di

Come prima cosa vorrei ringraziare Andrea per avermi dato la possibilità di contribuire, nel mio piccolo, a TANTO, scusandomi con lui per tutto il tempo (davvero troppo) passato da quando gli ho promesso questo tutorial ad oggi!

In questo breve articolo-tutorial cercherò di fare una panoramica sulla componente client di MapFish, un framework open source basato su ExtJs e OpenLayers, grazie al quale è possibile realizzare delle applicazioni webgis in pieno stile web 2.0 con poco sforzo una volta compreso il funzionamento degli “ingranaggi”.

Innanzitutto va detto che la parte relativa al mapping vero e proprio può essere gestita esattamente come in OpenLayers che, come già ricordato, è compreso all’interno di MapFish.
Si ha quindi a disposizione tutta la flessibilità di OpenLayers (layer WMS, WFS, Google, Yahoo, ecc.) e se si sanno già realizzare mappe online con questa ottima libreria, il passaggio a MapFish consiste semplicemente nel comprendere come gestire layout ed eventi alla maniera di ExtJs (l’altra componente del framework) e nello scoprire gli utili widget che MapFish mette a disposizione dello sviluppatore.

L’utilizzo di questi widget è simile a quello dei controlli di OpenLayers, con la differenza che in questo caso viene sfruttata la potenza di ExtJs per aggiungere un’interfaccia utente avanzata al controllo. I widget che necessitano del solo codice lato client sono:

  • Toolbar – una barra degli strumenti con dei tasti preimpostati (full-extent, pan, zoombox, zoom out) che è possibile espandere con nuovi bottoni sapendosi muovere un minimo con OL;
  • Layer Tree – si tratta di una “toc”, simile al layer switcher di OL, ma molto più configurabile, con la possibilità di includere facilmente icone e di annidare e raggruppare i layer a proprio piacimento;
  • Scorciatoie – liste a discesa con possibilità di autocompletamento del testo inserito (come avviene in Google suggest, per capirci) che centrano la mappa sulle coordinate corrispondenti al luogo/elemento scelto;
  • Stampa – un semplice controllo da includere per stampare la porzione di mappa visualizzata.

Affinché gli altri widget di MapFish (stampa complessa, ricerca nel db, ecc.) funzionino, è necessario che sia installata la componente server del framework che, però, non tratteremo in questo articolo (anche perché, non avendoci mai lavorato, rischierei di scrivere una montagna di cavolate!).
ExtJs semplifica la creazione di layout, anche molto complessi, che risultano accattivanti per l’utente e cross-browser. Con poche righe di codice è possibile creare interfacce a schede (tab), menu accordion, form avanzati, ecc… avendo la sicurezza che l’applicazione verrà correttamente visualizzata su tutti i browser più diffusi in circolazione. Con ExtJs possiamo ottenere rapidamente delle belle GUI in cui “infilare” le nostre applicazioni webgis. Insomma, sono assicurati un risultato di tutto rispetto e un bel risparmio di diottrie e bile (è risaputo che quella di rendere cross-browser delle appicazioni web “complesse” sia una delle attività che più contribuiscono alla creazione di nuovi tipi di imprecazioni… :-) ).

Fatta questa introduzione, passiamo al tutorial vero e proprio!

Tutorial MapFish

Creeremo una semplice applicazione webgis, munita di una toolbar e di un layer tree, con cui sarà possibile visualizzare la localizzazione degli utenti GRASS su due mappe di base alternative.
Le informazioni che mostreremo provengono da diversi server WMS (Nasa, Metacarta, Grass).
Utilizzeremo la versione 1.1 del framework MapFish, scaricabile da qui come archivio compresso in formato tar.gz (se state lavorando in ambiente Windows, vi consiglio di procurarvi l’ottimo 7zip per estrarne il contenuto).

Il primo passaggio consiste ovviamente nello scompattare quanto abbiamo scaricato in modo da ottenere una cartella (MapFish-1.1) che contiene tutto il necessario per creare la nostra applicazione d’esempio.
Utilizzando la sola parte client non abbiamo bisogno di rendere visibile il tutto ad un eventuale webserver e possiamo posizionare la directory di cui sopra dove più ci aggrada nel filesystem…
Tuttavia, per mantenere un certo ordine, consiglio di creare una ulteriore cartella, che chiameremo “EsempioMF”, e di lavorare al suo interno.
Creiamo anche un file index.html, un file myMapFish.js e spostiamo anche loro nella cartella di lavoro “EsempioMF”.
A questo punto, quindi, la situazione dovrebbe essere la seguente:

EsempioMF
|
– MapFish-1.1
|
– index.html
|
– myMapfish.js

Ora che siamo organizzati in modo più o meno ordinato, è il momento di riempire il file index.html.
Ecco come:

	
<html>
<head>
<title>Esempio MapFish by TANTO</title>
	
<!-- link ai CSS della componente ExtJS
(è possibile scaricare temi dal sito di extjs e sostituire default.css con il foglio di stile del tema scaricato... ce ne sono un paio che meritano) -->
<link rel="stylesheet" type="text/css" href="MapFish-1.1/client/mfbase/ext/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="MapFish-1.1/client/mfbase/ext/resources/css/default.css" />
	
<!-- Inserisco i riferimenti agli script Javascript necessari al funzionamento del framework MapFish -->
<script type="text/javascript" src="MapFish-1.1/client/mfbase/openlayers/lib/OpenLayers.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/ext/ext-all.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/mapfish/MapFish.js"></script>
	
<!-- Inserisco il riferimento allo script Javascript myMapFish.js -->
<script type="text/javascript" src="myMapFish.js"></script>
</head>
<body>
<!-- Nel body creo i div che faranno da contenitori per la mappa vera e propria, per la toolbar e per il layer tree -->
<div id="map"></div>
<div id="buttonbar"></div>
<div id="tree"></div>
</body>
</html>
	

I commenti indicano cosa è stato inserito nell’header.Quindi possiamo chiudere index.html e iniziare a lavorare sullo script myMapFish.js.
Questo script conterrà due porzioni ben distinte:
- la prima servirà a definire il layout dell’applicazione (codice ExtJs);
- la seconda definirà la mappa vera e propria (codice OpenLayers) ed i widget MapFish che utilizzeremo.

Cominciamo, quindi, dalla prima parte dello script ed inseriamo quanto segue:

	
//Layout dell'applicazione
//************************
Ext.onReady(function() {
    new Ext.Viewport({
        layout:'border',
        items:[{
                region:'north',
                margins:'4 4 4 4',
                height: 63,
                html: '<img src="http://blog.spaziogis.it/wp-content/themes/blacknwhite/blacknwhite/images/TANTO_logo.png"/>',
                bodyStyle:'padding:2px;'
                },{
                region:'center',
                layout:'border',
                margins:'0 4 4 4',
                items:[{
                        region:'north',
                        border:false,
                        contentEl:'buttonbar',
                        height:26
                        },{
                        region:'center',
                        contentEl:'map',
                        border:false
                }]
                },{
                title:'Layer tree',
                region:'east',
                margins:'0 4 4 0',
                width:350,
                contentEl:'tree',
                collapsible:true
                },{
                region:'south',
                margins:'0 4 4 4',
                height:20,
                html:'Esempio realizzato per TANTO',
                bodyStyle:'padding:2px;font-size:12px;font-family:tahoma,arial,helvetica'
        }]
	
    });
	
});
	

questa porzione di codice definisce completamente la webgui, non c’è bisogno di altro.
In sintesi, dopo aver inizializzato ExtJs con il metodo Ext.onReady, abbiamo creato un oggetto Viewport per dire ad ExtJs di utilizzare tutta la finestra del browser (dimenticavo… vogliamo che la nostra applicazione sia a tutto schermo :) ) e poi abbiamo inserito un layout di tipo ‘border’ all’interndo del quale (nel pannello ‘center’) abbiamo annidato un secondo layout dello stesso tipo.
Ogni layout di tipo border può contenere 5 panneli (‘region’), detti north, center, east, west, south. Di questi solo ‘center’ è obbligatorio.
Ad ogni modo vi rimando all’esplorazione del sito di ExtJs per scoprire come complicare a piacimento i vostri layout. Il sito è molto ben fatto, pieno di tutorial ed esempi.

Passiamo ora alla mappa e ai mapfish widget.
Sempre all’interno del file myMapFish.js inseriamo questo pezzo di codice sotto al precedente:

	
//Mappa e Widget
//************************
	
function initMap(){
	
    //Creo la mappa e definisco alcuni controlli di base
    var map = new OpenLayers.Map('map',{controls:[
        new OpenLayers.Control.Navigation(),
        new OpenLayers.Control.PanZoomBar()
    ]});
	
    //Definisco l'extent che utilizzerò come vista iniziale
    var bounds = new OpenLayers.Bounds(5,36,21,50);
	
    //Definisco i layer WMS, due di base (alternativi) e uno di overlay
    var jpl_wms = new OpenLayers.Layer.WMS("NASA_Global_Mosaic",
"http://t1.hypercube.telascience.org/cgi-bin/landsat7",{layers: "landsat7"});
	
    var ol_wms = new OpenLayers.Layer.WMS("OpenLayers_WMS",
"http://labs.metacarta.com/wms/vmap0",{layers: 'basic'});
	
    var grass_users = new OpenLayers.Layer.WMS.Untiled("Utenti_grass",
"http://mapserver.gdf-hannover.de/cgi-bin/grassuserwms?",
        {layers: 'GRASS-Users',transparent:true, format:'image/png'},
        {isBaseLayer:false});
	
    //Aggiungo i layer alla mappa
    map.addLayers([jpl_wms,ol_wms,grass_users]);
	
    //Aggiungo il toolbar widget di MapFish:
    //**************************************
    //Creo la toolbar
    var toolbar = new mapfish.widgets.toolbar.Toolbar({map: map, configurable:true});
	
    //Scelgo di renderizzare la toolbar in un div con id = buttonbar
    toolbar.render('buttonbar');
	
    //Aggiungo i bottoni/controlli
    toolbar.addControl(new OpenLayers.Control.ZoomBox(), {iconCls: 'zoomin',toggleGroup: 'map'});
    toolbar.addControl(new OpenLayers.Control.ZoomOut(), {iconCls: 'zoomout',toggleGroup: 'map'});
    toolbar.addControl(new OpenLayers.Control.DragPan({isDefault: true}),{iconCls: 'pan', toggleGroup: 'map'});
	
    //Attivo la toolbar
    toolbar.activate();
	
    //Layer tree
    //***************************************
    //Creo un modello per il layer tree, distribuendo i layer in due nodi espandibili distinti (Mappe di base e Overlay)
    var model = [{
         text: "Mappe di base",
         expanded: true,
         children: [{
              checked:true,
              text:"Nasa Global Mosaic",
              layerName:"NASA_Global_Mosaic"
              },{
              checked:false,
              text:"OpenLayers WMS",
              layerName:"OpenLayers_WMS"
         }]},{
         text: "Overlay",
         expanded: true,
         children: [{
              checked:false,
              text:"Utenti GRASS",
              layerName:"Utenti_grass"
          }]
    }];
	
    //Inserisco il widget vero e proprio indicando
    var tree = new mapfish.widgets.LayerTree({
    map: map, el: 'tree',
    model: model,
    border:false, autoHeight:true
    });
    tree.render();
	
    //Centro la mappa sull'extent definito in precedenza
    map.zoomToExtent(bounds);
	
} //fine della funzione init()
	

Anche qui i commenti dovrebbero essere abbastanza chiari.
Abbiamo creato una mappa esattamente come se stessimo lavorando con buon vecchio OpenLayers e, in più, abbiamo inserito nel codice due MapFish widget.

Prima di vedere il risultato del nostro lavoro dobbiamo fare due piccole modifica al file index.html:
- inserire un evento onload a livello del tag per fare in modo che la mappa venga caricata all’apertura della pagina (esattamente come in OL);
- inseire alcune regole CSS necessarie per la corretta visualizzazione dei MapFish widget

Ecco come deve apparire index.html modificato a dovere:

	
<html>
<head>
<title>Esempio MapFish by TANTO</title>
	
<!-- link ai CSS della componente ExtJS
(è possibile scaricare temi dal sito di extjs e sostituire default.css con il foglio di stile del tema scaricato... ce ne sono un paio che meritano) -->
<link rel="stylesheet" type="text/css" href="MapFish-1.1/client/mfbase/ext/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="MapFish-1.1/client/mfbase/ext/resources/css/default.css" />
	
<!-- Inserisco i riferimenti agli script Javascript necessari al funzionamento del framework MapFish -->
<script type="text/javascript" src="MapFish-1.1/client/mfbase/openlayers/lib/OpenLayers.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/ext/ext-all.js"></script>
<script type="text/javascript" src="MapFish-1.1/client/mfbase/mapfish/MapFish.js"></script>
	
<!-- Inserisco il riferimento allo script Javascript myMapFish.js -->
<script type="text/javascript" src="myMapFish.js"></script>
</head>
<body onload="initMap()">
<!-- Nel body creo i div che faranno da contenitori per la mappa vera e propria, per la toolbar e per il layer tree -->
<div id="map"></div>
<div id="buttonbar"></div>
<div id="tree"></div>
</body>
</html>
	
<style type="text/css">
/* Icone dei bottoni della toolbar */
.zoomin {
background-image:url(MapFish-1.1/client/mfbase/mapfish/img/icon_zoomin.png) !important;
height:20px !important;
width:20px !important;
}
.zoomout {
background-image:url(MapFish-1.1/client/mfbase/mapfish/img/icon_zoomout.png) !important;
height:20px !important;
width:20px !important;
}
	
.pan {
background-image:url(MapFish-1.1/client/mfbase/mapfish/img/icon_pan.png) !important;
height:20px !important;
width:20px !important;
}
	
/* Dimensioni del Layer tree */
#tree {
height: 100%;
width: 100%;
}
</style>
	

Adesso apriamo index.html col borwser e il risultato dovrebbe essere questo.

;)

10 maggio, 2007 | di

Ecco un’altra chicca che vi prego di diffondere: un corso online dal titolo “Open Web Mapping“. E’ molto ben strutturato e copre gran parte degli argomenti propedutici per chi si voglia avvicinare a questo mondo. Lo trovo utile anche per chi voglia raccogliere del materiale per fare didattica. Questo è l’indice del corso:

  • Lesson 0: Orientation
  • Lesson 1: Introduction to Open Web Mapping
  • Lesson 2: Web Map Servers (WMS)
  • Lesson 3: Web Feature Servers (WFS)
  • Lesson 4: Extensible Markup Language (XML)
  • Lesson 5: Advanced Web Map Servers
  • Lesson 6: Geographic Markup Language (GML)
  • Lesson 7: WFS Revisited
  • Lesson 8: Building a Web Mapping Application
  • Lesson 9: Building a Thin Custom Web Mapping Client

Il corso è interamente scaricabile ed io lo sto archiviando con ScrapBook.


TANTO non rappresenta una testata giornalistica ai sensi della legge n. 62 del 7.03.2001, in quanto non viene aggiornato con una precisa e determinata periodicita'. Pertanto, in alcun modo puo' considerarsi un prodotto editoriale.