Come creare un mapfile per MapServer con QGIS

Una delle difficoltà principali per chi vuole usare MapServer è sicuramente la scrittura del mapfile. Scrivere a mano un mapfile usando un normale text-editor e rispettare tutte le regole sintattiche non è sempre semplice. MapServer non include alcun tool di supporto per la creazione di un mapfile, ma esistono alcuni software di terze parti (editor di mapfile forniti di GUI)  che ci aiutano in questa operazione.

Una comoda soluzione  è disponibile per coloro che usano QGIS desktop, perchè esiste un plugin che, partendo da un progetto caricato e salvato, permette di ricavare un corrispondente mapfile  per MapServer. Il suo nome è RT MapServer Exporter  e in questa pagina potete trovare tutte le informazioni che lo riguardano; vi dico tra l’altro che è un plugin proposto e finanziato dalla regione Toscana e sviluppato con l’importante contributo di amici italiani.
In questo articolo vi presento una guida per usarlo correttamente ed anche alcuni avvertimenti pratici.

Per usarlo dobbiamo, ovviamente, installarlo su QGIS; non vi tedio su come dovete fare, sicuramente lo sapete! Vi ricordo solamente che il plugin è al momento ancora in fase sperimentale (ad oggi l’ultima release è la 0.5.0 rilasciata il 5/11/15), quindi se volete trovarlo nell’elenco dei plugin disponibili, dovete abilitare la relativa opzione (in Settings) per vedere questo tipo di plugin.

exp_qgis_plugin

Installare il modulo python-mapscript

Come viene segnalato anche nella paginetta di presentazione del plugin,  per poter funzionare è richiesto che nel vostro sistema sia installato  il modulo python-mapscript.
Se avete già  MapServer insieme con MapScript, questo modulo dovrebbe già essere presente; comunque un modo empirico per controllare, consiste semplicemente nel lanciare l’esecuzione del plugin: se tutto va liscio si aprirà la sua finestra di avvio, se invece ottenete un messaggio di “errore python”, vuol dire che manca.

RT Mapserver exporter

Per installare il modulo python-mapscript su Windows, possiamo usare OSGeo4W  e precisamente scegliere la modalità “advanced install” quindi andare nella sezione “Web” e selezionare il modulo in questione; quindi cliccare su “Avanti” per avviare l’installazione.

osgeo4w_pyt_mapscript

Se invece avete QGIS installato come applicazione stand-alone, allora per installare i singoli moduli python (nel nostro caso python-mapscript) si può usare il package manager  “pip” (python index package); questo si trova dentro la cartella di python in cui è installato QGIS e precisamente, supponendo che la cartella di QGIS è C:\Programmi\QGIS xxx, al seguente percorso:

Se non lo trovate, vuol dire che dovete installarlo. E’ molto semplice e comunque sul web trovate diverse guide che spiegano come fare. Inoltre per eseguire pip, evitando di scrivere tutto il suo path, vi consiglio di impostare le  variabili di sistema PYTHONHOME e PYTHONPATH (prompt dei comandi):

fatto ciò, per installare python-mapscript basta scrivere:

Su sistemi Debian/Ubuntu è ancora più semplice, basta usare il comando :

Componiamo la mappa : il progetto QGIS

Componiamo in QGIS la mappa che vogliamo esportare per MapServer, aggiungendo e arrangiando i layer, definendo simboli ed etichette, personalizzando i colori, quindi salviamo il progetto. Questo è importante, perchè il plugin non opera sul contenuto corrente (vista mappa e vista legenda) di QGIS, ma su un progetto salvato. Inoltre se volete eliminare un layer non basta deselezionarlo dalla “legenda layer” ma bisogna proprio rimuoverlo dal progetto, altrimenti il plugin continua a considerarlo.

Per quanto riguarda i tipi di layer (raster e vettoriali) che potete usare, sono inclusi tutti quelli più diffusi: geoTiff e tutti i gli altri tipi raster supportati nella libreria GDAL,  shapefile, postGIS, SpatiaLite e Oracle Spatial. Una precisazione: nel caso in cui si usino dati vettoriali su geoDB (come postGIS e SpatiaLite) non basta che questi siano caricati come layer (infatti QGIS consente di prelevarli direttamente dal browser) ma è necessario che venga aperta una connessione tramite il DB manager.

qgis_db_manager

Altrimenti, il plugin RT Mapserver Exporter non conosce la connessione al geoDB e quindi non riesce a trovare i file origine di tali vettori, generando un errore.

Altri layer che possono essere usati per comporre la mappa, sono quelli forniti da server remoti WMS e WFS; un mapfile infatti prevede anche layer che siano originati da tali servizi OGC (… MapServer funge pure da client WMS o WFS !).
Invece non si possono usare mappe fornite da gestori web come OSM, Bing e Google Maps (per es. quelli che si aggiungono con il plugin OpenLayer); se usate tali mappe, quando provate a creare il mapfile verrà generato un errore python.

no_openlayers

Esecuzione di RT MapServer Exporter

Quando il plugin è installato, trovate la sua voce  sotto il menù Web .

RT_exporter_menu

Una volta che il vostro progetto è completo, potete cliccare su Export project to mapfile e si apre la finestra del plugin che è composta da tre schede: General, Template e Advanced.

RT_MS_exp_1win

La scheda fondamentale è la General e qui  dobbiamo specificare i seguenti parametri:

  • Map file: il nome con cui vogliamo chiamare il mapfile e dove lo vogliamo salvare;
  • Name: il nome che vogliamo dare alla mappa (viene proposto di default lo stesso nome del progetto QGIS);
  • Image type: il tipo di immagine che deve essere generata per la mappa (png, gif, tiff, … etc);
  • Widht e Height: le dimensioni in pixel della finestra entro cui verrà visualizzata la mappa;
  • Shapepath: è il percorso assoluto della cartella che contiene i geodati (shapefile o raster) che compongono i layer della mappa.

Tutti questi sono  attributi fondamentali dell’oggetto MAP del mapfile; al limite si può omettere Shapepath. Tra l’altro, anche quando  viene esplicitato, il plugin per indicare l’origine dei LAYER (attributo DATA) scrive in ogni caso il path assoluto e non quello relativo a SHAPEPATH (se volete, poi lo potete modificare a mano).

Oltre a questi, abbiamo un’altro gruppo di parametri che riguardano l’oggetto WEB del mapfile:

  • Online resource URL: è l’URL del modulo CGI di MapServer sul  web server che vogliamo usare (localhost se il nostro sistema locale);
  • Image path: il percorso assoluto della cartella dove vengono salvati le immagini e i file temporanei generati da MapServer per rappresentare la mappa ed altri oggetti (legenda, barra di scala, … etc) poi richiamati nel template file HTML;
  • Image URL: è l’ URL da usare nel browser per visualizzare le immagini contenute nella precedente cartella; esso è relativo cioè espresso rispetto alla homeDir del nostro web server;
  • Temporary path:  il percorso assoluto della cartella in cui MapServer va a salvare alcuni files temporanei che genera in determinate situazioni (da non confondersi con Image path), quindi deve essere una cartella sulla quale MapServer ha i permessi di lettura e scrittura; se non viene specificata, viene usata la cartella TMP di default del sistema;
  • External graphic regexp: se  per la vestizione dei layer (simbologia) sono stati usati degli oggetti grafici esterni (SVG, PNG o altro), allora bisogna specificare una regular expression per la loro validazione. Questo pero funziona solo se la vostra versione di MapServer supporta la SLD external graphics validation. 

Tutti questi parametri andranno a valorizzare i corrispondenti attributi dell’oggetto WEB, come mostrato nell’esempio seguente:

Esportare gli stili

Alla fine della scheda “General”  c’è il quadro Export method for vector layer styles  per  scegliere che metodo usare per esportare gli stili usati in QGIS  in un formato compatibile con MapServer. Cliccando sul link Help me decide compare un’altra finestra con una spiegazione del come e il perché; qui di seguito vi riporto il succo della questione.

Innanzitutto una premessa: qualsiasi metodo scegliete, non è detto che la visualizzazione della mappa con MapServer coinciderà con  quella che avete impostato in QGIS !
Il motivo è semplice: la codifica degli stili e la simbologia di QGIS, specie quando è  complessa e/o dipende da regole e condizioni, non sempre è traducibile in un formato adatto a MapServer. Vi ricordo anche che la rappresentazione grafica (o vestizione) di un layer vettoriale nel mapfile, viene fatta specificando l’oggetto CLASS e a sua volta specificando all’interno gli oggetti LABEL e STYLE (vd.: mapserver.org/mapfile/class.html).

Il primo dei due metodi implementati nel plugin, fa uso del formato SLD (Styled Layer Descriptor) che è uno standard OGC  riconosciuto sia da QGIS che da MapServer, quindi viene usato come formato di passaggio. Tuttavia lo SLD è implementato solo parzialmente (sia da QGIS che da MapServer) pertanto la conversione degli stili potrebbe risultare difettosa.
Il secondo metodo  (più recente) è invece un modulo scritto in python appositamente per il  plugin e dovrebbe garantire una maggiore fedeltà di conversione degli stili supportati da QGIS, rispetto al metodo basato su SLD. Tra l’altro questo metodo sarà aggiornato con le future versioni del plugin, mentre il primo è indipendente (dipende da come e quando QGIS e MapServer miglioreranno il supporto di SLD).

Cosa scegliere allora? Dipende dagli stili che state usando; il secondo dovrebbe garantire una maggiore compatibilità, ma a priori non è detto. Quindi in conclusione, vi conviene fare delle prove !

Dopo aver compilato la scheda General  si può  fare click sul bottone OK e produrre già un mapfile che funziona; infatti le impostazioni presenti nelle altre due schede (Template e Advanced) aggiungono almapfile altri parametri man non sono indispensabili.

Il template file

La scheda Template contiene  informazioni riguardanti il template file da usare associato al mapfile. Dovremmo sapere bene cos’è un template file ed il modo in cui viene usato dal modulo CGI di MapServer; comunque ricordiamo che si tratta di un file HTML che implementa l’interfaccia web tramite la quale l’utente può visualizzare la mappa definita nel mapfile (insieme con tutti i comandi per interagire con essa: spostare, zoommare, … etc) ed i risultati delle sue eventuali interrogazioni (queries).
Il plugin RT MapServer exporter, ci da due possibilità:

  • indicare il template file (templatepath) che  noi abbiamo già preparato a parte (il tasto […] ci permette di cercarlo);
  • autogenerare un template file relativamente ai layer che compaiono nella tabella sottostante;

RT_MS_exp_2win

Ma come è fatto il template file che viene prodotto quando si sceglie l’opzione autogenerate ?
A tal proposito, ricordiamo che MapServer CGI, oltre a funzionare nel modo browse  (effettuare il rendering della mappa rappresentata nel mapfile su una pagina web) può funzionare anche in altri modi e tra questi c’è il modo query (ci sono più varianti). Il modo di funzionamento del modulo CGI, si imposta tramite la variabile mode che prevede diversi valori, tra cui appunto:

  • BROWSE (è quello di default, se non viene specificato);
  • diversi modi query: QUERY, FEATUREQUERY,  ITEMQUERY, INDEXQUERY,  … etc

Nel modo query l’utente ha la possibilità di interrogare (fare delle query) MapServer sui geodati rappresentati nella mappa, precisamente dei layer vettoriali, cioè cercare/filtrare quelli che soddisfano determinati criteri. Sono possibili sia query spaziali (basate sulla posizione geografica) sia query sugli attributi. Per restituire i risultati delle query, MapServer usa dei template file HTML (query template) costruiti ad hoc in base a cosa devono rappresentare e comunque diversi da quelli adatti per il modo browse.

Senza stare qui ad approfondire l’argomento (… tra l’altro sarebbe più semplice da spiegare con esempi che a parole!) e tornando al nostro plugin, esso autogenera un query template per restituire risultati in forma tabellare, cioè relativi agli attributi di uno o più layer della mappa. Per capirci meglio, è un template che produce una pagina web simile a quella qui illustrata: query_templ

Questo template file viene salvato nella stessa directory che abbiamo scelto per il mapfile ed ha anche lo stesso nome, con aggiunta l’estensione .html.tmpl, per esempio:
– mapfile: mia_mappa.map 
– template: mia_mappa.map.html.tmpl
e nel mapfile viene registrato in corrispondenza dell’attrbuto TEMPLATE (dentro l’oggetto WEB) l’intero suo percorso:

Naturalmente, trattandosi di un file HTML, per poter essere utilizzato bisogna togliere l’estensione .tmpl  (anche dentro il mapfile). Questo template poi naturalmente possiamo modificarlo o integrarlo a nostro piacimento, andando ad editarlo a mano (e qui la conoscenza di HTML e di CSS è fondamentale !).

Ancora una nota sulla funzione di autogenerazione del template.
Nel caso in cui tra i layer che compongono la mappa, abbiamo anche un layer raster, non funziona e viene generato un errore python con la seguente indicazione:

e non viene neanche creato il mapfile !
E’ evidente che, poichè un raster non ha attributi, esso dovrebbe essere automaticamente escluso da quelli da usare per la generazione del template. Quindi molto probabilmente si tratta di un bug del plugin che potrebbe essere risolto nelle successive versioni !
Ad oggi allora, se volete creare un mapfile che contiene anche layer raster, non dovete utilizzare l’opzione di autogenerazione.

Altri due elementi che normalmente vengono adoperati in query mode per restituire i risultati sono l’ header ed il footer template; essi sono adoperati in combinazione col template file principale e definiscono rispettivamente l’intestazione (header) e il piè di pagina (footer) della pagina HTML con i risultati dell’interrogazione. Questi  li dobbiamo preparare noi (anche se scegliamo l’opzione autogenerate) e poi indicare il loro path nelle apposite caselle.head_foot_opz

Inutile dire che i template files (anche header e footer) per poter essere adoperati, devono essere messi in una cartella  accessibile al web server che, interagendo con MapServer CGI, pubblica sul web le pagine con la mappa ed i risultati delle interrogazioni. Allora dopo averli sistemati al posto giusto, dobbiamo controllare ed eventualmente correggere i path  che li riguardano indicati all’interno del mapfile.

Impostazioni avanzate: Fontset

L’ultima scheda di impostazioni per questo plugin è la Advanced che al momento  contiene solo informazioni relative al Fontset da utilizzare. Ma non escludo (… visto tutto lo spazio vuoto rimasto) che in sviluppi futuri saranno aggiunti altri parametri utili per definire il mapfile.

RT_MS_exp_3win

Ricordiamo che FONTSET è un attributo dell’oggetto MAP  contenente il percorso (assoluto o relativo rispetto alla posizione del mapfile) del file .txt che contiene l’elenco di tutti i font truetype adoperati per scrivere le etichette dei layer. Ogni oggetto LAYER, per il quale sono state definite delle etichette, contiene l’oggetto LABEL che prevede in particolare l’indicazione di due attributi:
– TYPE che può essere: bitmap o truetype;
– FONT che, quando è TYPE=truetype, contiene il nome del font da usare (es. Arial, Verdana, MSSansSerif, … etc).

Bene, il file .txt (lo potete chiamare come vi pare, per es.: my_fonts.txt) è un semplice file di testo che contiene un elenco di tutti i nomi dei caratteri truetype adoperati e accanto il percorso assoluto dei file che, nel sistema in cui viene eseguito MapServer, contengono la rispettiva definizione. Qui di seguito vediamo un esempio nel caso di  sistema Linux (ma sarà analogo per sistemi Windows):

Tornando alle impostazioni consentite nel nostro plugin, abbiamo due possibilità:

  • indicare il path del file .txt (che abbiamo preparato a parte) contenente le indicazioni sui font adoperati nelle etichette;
  • fargli generare automaticamente un file font.txt;

nel secondo caso, diciamo però che si tratta di una generazione parziale, in quanto il file font.txt prodotto contiene solo un elenco dei font adoperati senza i corrispondenti percorsi dei file di definizione; quindi dovremo completarlo aggiungendoli a  mano.

Per quanto detto prima, il Fontset va specificato solo se nei layer abbiamo usato delle etichette, altrimenti non è necessario. Tuttavia il plugin genera comunque nel mapfile  una riga che contiene il parametro FONTSET (senza valore) :

questa riga andrà cancellata, altrimenti  MapServer segnala un errore (non trovato il Fontset !).

Verifica e modifiche del mapfile

L’utilità di questo plugin nel generarci un mapfile, evitando di scriverlo tutto a mano, è indubbia. Tuttavia, come già accennato, esso non sarà perfetto, quindi andrà ritoccato, corretto ed eventualmente integrato. Se però il mapfile ci serve solo per essere distribuito tramite richieste WMS standard, allora dovrebbe già andare bene com’è; il plugin tra l’altro aggiunge i “metadati” necessari per rendere il nostro servizio web compatibile con le specifiche WMS.

Per verificare cosa produce il mapfile, una comoda utility  (installata insieme con MapServer) per controllare come viene rappresentata la mappa impostata in un mapfile ancor prima di usarla con MapServer, è shp2img che produce una immagine statica (png, tiff, jpg, .. etc). Se ci mettiamo nella stessa cartella del mapfile e scriviamo (uso le opzioni base):

otteneniamo un’immagine mia_mappa.tiff che riproduce la mappa con tutti i suoi layer.

Oppure possiamo fare delle verifiche richiamando direttamente il modulo CGI nel nostro browser. Supponendo che il nostro mapfile (mia_mappa.map) si trova nella cartella /var/www/html/ (mi sto riferendo a un sistema Linux), invochiamo MapServer CGI nel modo MAP scrivendo il seguente URL:

e otterremo una pagina web che mostra la mappa con tutti i suoi layer.
Se invece vogliamo controllare le sue capabilities quando distribuiamo la mappa come servizio WMS, allora scriviamo l’ URL :

Alcuni degli aggiustamenti da fare li abbiamo già indicati prima, ma per esempio, bisogna certamente correggere  l’ordine con cui sono scritti i layer (oggetti LAYER) dentro il mapfile. Infatti QGIS produce (rendering) la mappa leggendo i layer dall’ultimo al primo, invece Mapserver opera al contrario; quindi per vedere i layer sovrapposti nel giusto modo, dobbiamo invertire il loro ordine dentro il mapfile.
Qui di seguito un esempio in cui un layer che rappresenta delle strade (vettore di linee) deve essere rappresentato sopra a un layer che rappresenta delle province (vettore di poligoni).

layer_order

Poi, come abbiamo già accennato, non è neanche garantito che MapServer riproduca esattamente gli stili e le etichette impostate in QGIS; anche in questo caso dovremo fare un pò di lavoro manuale per sistemare le cose, usando le regole sintattiche previste per il mapfile (a questo proposito riferirsi sempre alla documentazione ufficiale della versione di MapServer in uso).

Detto questo, possiamo concludere che comunque, grazie a questo plugin di QGIS, riusciamo ad ottenere un mapfile che, nonostante i limiti, è un buon punto di partenza che ci permette di risparmiare un sacco di tempo. Quindi, ci auguriamo che il suo sviluppo prosegua !

condividi: