15 Anni di programmazione

Aneddoti e Codici di un inguaribile ottimista

February 2011 - Post

SharpMap: Shapefile sotto .NET

Mi è stato chiesto di sviluppare un’applicazione web nella quale selezionando una nazione da una mappa fosse possibile visualizzare sotto forma di Chart dei dati estratti da un database relazionale. La prima demo che ho realizzato utilizzava Yahoo Maps (preferito a Google per le minori limitazioni sull’uso commerciale). Tuttavia il cliente si è lamentato del fatto che la mappa fosse troppo sofisticata e che l’utente si sarebbe facilmente distratto a giocare con i vari tipi di visualizzazione disponibili. Mi ha dunque chiesto una mappa più basilare ma che fosse anche configurabile (ad esempio visualizzare una certa nazione con un dato colore) e rispondesse all’evento di click su di essa.

Dopo un po’ di studio la mia scelta è stata quella di utilizzare una mappa in formato Shapefile. Si tratta di un popolare formato vettoriale per sistemi informativi geografici, sviluppato e regolato all’inizio degli anni 90 dalla ESRI (leader mondiale nel campo dei software geografici). Di fatto è diventato uno standard per il dato vettoriale spaziale, e viene usato da una grande varietà di sistemi GIS.

Con Shapefile si indica di norma un insieme di file che hanno in comune il prefisso dei nomi (per es. "countries.*"). Tre file sono obbligatori, senza di essi uno Shapefile non è tale;

  • .shp - il file che conserva le geometrie
  • .shx - il file che conserva l'indice delle geometrie;
  • .dbf – il database degli attributi

Gli Shapefile registrano semplicemente i dati geometrici primitivi: punti, linee e poligoni. Da sole queste primitive, dette feature, non sono utili, mancando degli attributi che specificano cosa queste primitive rappresentino. Perciò una tavola di record registra proprietà e attributi per ogni primitiva (shape) dello Shapefile. Le shape, insieme ai dati attributari, possono creare infinite rappresentazioni di dati geografici, da cui a loro volta dipende la potenza e l'accuratezza delle analisi geo-spaziali che sono il fine dei GIS.

Partiamo con un semplice esempio. Al seguente indirizzo  è possibile scaricare uno Shapefile contenente le nazioni del mondo.

image 

Con Microsoft Office Access possiamo visualizzare il contenuto del file .dbf. Attenzione che per aprire il file bisogna rinominarlo con un nome al massimo di 8 caratteri (nel 2011 succedono ancora queste cose!): create quindi prima una copia del file originario e poi rinominatelo. Il file dbf è una tabella di questo tipo:

 

image

Senza entrare nel dettaglio, a noi interessa principalmente il campo contenente il nome della nazione e la sua posizione all’interno della tabella: quindi, NAME e 0.

Come possiamo accedere ad uno Shapefile sotto ambiente .NET? Su Codeplex (la community Open Source) troviamo un progetto chiamato SharpMap consistente in una libreria che fornisce accesso a molti tipi di dati GIS, Shapefile compreso. La libreria può essere usata sia per applicazioni desktop che web. E’ stata scritta in C# ed è basata sul framework .Net 2.0. Vi consiglio come primo approccio di scaricare la versione 0.9, lasciando stare per un po’ la più complessa versione 2.0.

Il primo progetto che andiamo ad esaminare è una semplice applicazione desktop. Una volta compresi gli aspetti base della libreria, costruiremo una pagina web.

L’oggetto base della libreria è la Map. Ad essa vengono aggiungi i cosiddetti Layer. Nel nostro caso abbiamo due Layer: il primo contenente lo Shapefile appena descritto e il secondo una collezione di punti che andremo ad aggiungere sulla mappa mediante click. Un Layer ha un datasource (nel nostro caso il percorso dello shapefile) e possiamo associare ad esso un Theme. Cos’è un Theme? Supponiamo di voler colorare in rosso l’Italia, lasciando in verde tutte le restanti nazioni.

clip_image002

Nella costruzione dell’oggetto tema, indichiamo una funzione delegata che agisce su tutte le shape contenute nel datasource. Nel nostro caso abbiamo 211 poligoni (uno per nazione). Ogni poligono ha come attributo il nome della nazione (nel campo 0). Con un semplice check sull’attributo possiamo quindi cambiare il colore di riempimento del poligono.

image

 

La Map, infine, viene posta come proprietà immagine di una PictureBox. Quando l’utente clicca col Mouse in un punto della PictureBox, abbiamo due coordinate X ed Y che vanno trasformate in coordinate geografiche. SharpMap esegue la trasformazione mediante il metodo ImageToWorld.

image

Il codice allegato mostra come eseguire lo Zoom e il centramento della mappa. Inoltre, viene indicato anche come aggiungere punti a un Layer dell’oggetto Mappa.

La libreria SharpMap è molto semplice da utilizzare e al tempo stesso garantisce allo sviluppatore tutto quanto gli occorre per realizzare progetti complessi quali, ad esempio, il collegamento di mappe a dati contenuti su database relazionali esterni.

In allegato troverete anche una semplice pagina aspx che carica lo stesso Shapefile appena mostrato. Il codice è basato su un progetto che ho trovato su CodeProject al seguente indirizzo. Nel caso di una pagina web entra in gioco il fattore ricaricamento della pagina ad ogni invocazione lato server. E’ dunque necessario conservare tramite una ViewState l’informazione relativa all’ultimo centro e zoom della mappa. La Mappa viene caricata come proprietà ImageUrl di un controllo ImageButton.

image

Occorre però aggiungere un httpHandler nella sezione system.web della Web.config del sito:

image

Concludo segnalandovi che da poco è nato sotto Codeplex un nuovo progetto, MapsUI,  basato su SharpMap ed ottimizzato per le seguenti piattaforme: Silverlight, WPF, MS Surface, WinForms, Compact Framework  e Windows Phone.

Ecco i due progetti in allegato: