====== MapServer ====== ===== Link documentazione ===== * **[[http://www.mapserver.org/documentation.html|Indice documentazione]]** * **[[http://biometry.gis.umn.edu/tutorial/index.html|MapServer 5.x Tutorial]]** * **[[http://www.rigacci.org/mapserver/|Esempi Rigacci.org]]** ===== Scaletta ===== * Pacchetto e dipendenze * Architettura cgi-bin * Il file .map * Estensione * Proiezione * Unità di misura * Formato immagini * Layer * Tipo * Sorgente * Label * Scala * Modo map e modo browse * Template HTML * File temporanei * Server WMS ===== Note sui file .map ===== ==== LAYER STATUS ==== ^ DEFAULT | Il layer è sempre attivo (attivo per default), non può essere spento. | ^ ON/OFF | Il layer è attivo o meno e può essere cambiato a "runtime", ad esempio in modalità browse con l'opportuno template. | ==== WFS con layer in diversi SRS ==== È possibile configurare un WFS con diversi layer, ciascuno in un differente SRS. Lo standard WFS non consente di annunciare un layer con più di un SRS. Se si esplicita la proiezione in **''MAP.PROJECTION''** o **''MAP.WEB.METADATA.wfs_srs''**, questa (e solo questa) viene annunciata per tutti i layer. La **''LAYER.PROJECTION''** è comunque necessaria per calcolare correttamente la '''' del layer. Tale misura viene annunciata dalla ''GetCapabilities'' e deve essere espressa in WGS84. Mescolare layer con proiezioni differenti crea un grosso problema nel definire la **''MAP.EXTENT''** (ancora più evidente se si mescolano SRS in proiezione metrica e SRS in lat/lon). La richiesta ''GetFeature'' viene limitata dalla ''MAP.EXTENT'', affinché siano restituite tutte le feature di tutti i layer bisogna quindi considerare l'extent di tutti i layer come numeri puri e trovare il min/max fra tali numeri. Ad esempio se abbiamo due layer con le seguenti EXTENT: EXTENT 1680955 4846472 1687816 4852211 UNITS meters EXTENT 11.128482 43.626412 11.553594 43.829166 UNITS dd è necessario dichiarare una MAP.EXTENT di questo tipo: EXTENT 11.128482 43.626412 1687816 4852211 ==== Limitare i formati offerti da un WMS ==== Questa configurazione non funziona con MapServer 5.0.3, funziona invece con la **5.6.3**. È possibile limitare il tipo di immagine offerto da un WMS, cioè il valore viene restituito dalla GetCapabilities in ''''. L'impostazione predefinita è quella di annunciare tutti i formati grafici supportati dal MapServer (lanciare **''mapserv -v''**), non solo quelli per cui è definito il **''MAP.OUTPUTFORMAT''**. Ecco le sezioni rilevanti da mettere in un mapfile per limitare - ad esempio - al formato PNG/24 bit e JPEG: MAP ... IMAGETYPE aggpng24 ... OUTPUTFORMAT NAME "aggpng24" DRIVER AGG/PNG IMAGEMODE RGB END OUTPUTFORMAT NAME "jpeg" DRIVER "GD/JPEG" IMAGEMODE RGB END ... WEB METADATA ... wms_getmap_formatlist "image/png; mode=24bit,image/jpeg" END ... END ... END ===== Sistemi di riferimento ===== ^ Nome ^ Codice EPSG ^ | **Cartografia italiana** || | Gauss-Boaga Roma40 (Italia Monte Mario) zona 1 | 3003 | | Gauss-Boaga Roma40 (Italia Monte Mario) zona 2 | 3004 | | **Cartografia internazionale GPS** || | WGS84 | 4326 | ===== Tool GDAL/OGR ===== ==== ogrinfo ==== Per avere informazioni su un file OGR (formati vettoriali; es. shapefile, gpx, ecc.) si usa il programma **''ogrinfo''** (fornito dal pacchetto gdal-bin). Prima lo si esegue sul file stesso, per avere **informazioni sui layer** contenuti: ogrinfo track.gpx Had to open data source read-only. INFO: Open of `track.gpx' using driver `GPX' successful. 1: waypoints (Point) 2: routes (Line String) 3: tracks (Multi Line String) 4: route_points (Point) 5: track_points (Point) Si vede che esistono diversi **layer** al suo interno, a noi interessa quello di nome **tracks**. Per avere informazioni sul layer si esegue: ogrinfo -summary track.gpx tracks Had to open data source read-only. INFO: Open of `track.gpx' using driver `GPX' successful. Layer name: tracks Geometry: Multi Line String Feature Count: 5 Extent: (11.128482, 43.626412) - (11.553594, 43.829166) Layer SRS WKT: GEOGCS["WGS 84", DATUM["WGS_1984", ... Utilissimo ad esempio per avere la **''EXTENT''**. ==== gdalinfo ==== Il programma **''gdalinfo''** (fornito dal pacchetto gdal-bin) è analogo a ''ogrinfo'', consente di avere informazioni su file raster supportati dalla libreria GDAL: gdalinfo 1353.tif Driver: GTiff/GeoTIFF Files: 1353.tif Size is 5071, 8851 Coordinate System is `' Origin = (1670696.939930999884382,4707728.060069000348449) Pixel Size = (2.120138000000000,-2.120138000000000) ... Corner Coordinates: Upper Left ( 1670696.940, 4707728.060) Lower Left ( 1670696.940, 4688962.719) Upper Right ( 1681448.160, 4707728.060) Lower Right ( 1681448.160, 4688962.719) ... ===== Path relativi ===== **Mai usare path assoluti nei file map!** Nella peggiore delle ipotesi l'unico path assoluto può essere contenuto in **''SHAPEPATH''**. ^ SHAPEPATH | Directory in cui sono memorizzati gli shapefile, compresi i tileindex (indici) per i raster. Si intende **relativa alla directory del file map**. | ^ TILEINDEX | In generale i file raster potrebbero trovarsi in sottodirectory della ''SHAPEPATH'', tuttavia conviene che i file indice siano tutti direttamente nella ''SHAPEPATH''. | ^ tileindex.shp | L'indice contiene il path dei file raster, MapServer interpreta il percorso come **relativo allo ''SHAPEPATH''**, non relativo alla posizione del file indice stesso. | Ad esempio nella directory **''/usr/local/share/shape/''** abbiamo la sottodirectory **''toscana/ctr25/''** con i raster della Carta Tecnica Regionale. Il file map contiene: SHAPEPATH "/usr/local/share/shape" LAYER TYPE RASTER TILEINDEX "toscana_ctr25k_tindex.shp" END L'indice deve contenere il percorso relativo ''toscana/ctr_25k/'' e quindi deve essere costruito in questo modo: cd /usr/local/share/shape gdaltindex toscana_ctr_25k_index toscana/ctr_25k/*.tif ===== Tool per tiles ===== ==== tile4ms ==== Il programma **''tile4ms''** fornito dal pacchetto ''mapserver-bin'' serve a creare un **indice di shapefile**. Prima di usare **''tile4ms''** bisogna creare un elenco dei file che devono essere indicizzati, può tornare utile il comando **''find''** o simili. L'elenco creato viene dato in pasto a ''tile4ms'' che produce l'indice. In questo esempio si cercano tutti gli shapefile relativi alla medesima feature //elementi lineari//, contraddistinti dal nome **''%%*el.shp%%''** e contenuti in varie sottodirectory, l'elenco viene scritto in un //metafile//. Il comando ''tile4ms'' crea l'indice leggendo dal metafile: cd /usr/local/share/gisdata find shape/geofesta2008/firenze10k/ -name "*el.shp" > firenze10k_el_metafile tile4ms firenze10k_el_metafile firenze10k_el_index La porzione di mapfile corrispondente è del tipo: SHAPEPATH "/usr/local/share/gisdata" LAYER NAME "EL entità lineari" STATUS DEFAULT TYPE LINE TILEINDEX "firenze10k_el_index" TILEITEM "Location" CLASS COLOR 120 120 120 END END ==== gdaltindex ==== Il programma **''gdaltindex''** fornito dal pacchetto ''gdal-bin'' serve per creare un **indice di raster**. cd /usr/local/share/gisdata gdaltindex toscana_ctr25k_index.shp raster/toscana_ctr25k/*.tif Il file indice è uno shapefile, analogamente a quanto visto con ''tile4ms''. Va indicato con la direttiva **''TILEINDEX''** che si intende **relativa a ''SHAPEPATH''**. L'indice deve contenere il percorso dei file raster relativi a ''SHAPEPATH'', non al file indice. Con **''OFFSITE''** si indica quale colore deve essere considerato trasparente: SHAPEPATH "/usr/local/share/gisdata" LAYER NAME "ctr25k" STATUS DEFAULT TYPE RASTER TILEINDEX "toscana_ctr25k_index.dbf" TILEITEM "Location" PROCESSING "RESAMPLE=AVERAGE" OFFSITE 255 255 255 END ==== gdalbuildvrt ==== In alternativa all'indice di raster si può creare un **virtual raster** (che può essere agevolmente aperto con tutti i programmi che utilizzano una moderna libreria GDAL, come QGIS): cd /usr/local/share/gisdata gdalbuildvrt toscana_ctr25k.vrt raster/toscana_ctr25k/*.tif In questo caso il mapfile ha questa forma: SHAPEPATH "/usr/local/share/gisdata" LAYER NAME "ctr25k" STATUS DEFAULT TYPE RASTER DATA toscana_ctr25k.vrt PROCESSING "RESAMPLE=AVERAGE" OFFSITE 255 255 255 END ==== gdal_merge.py ==== Come mosaicare diverse tile troppo piccole per riassemblare un unico raster. L'immagine viene inizializzata bianca (valore 255 per ognuna delle tre bande RGB) gdal_merge.py -v -o /tmp/075k.tif -init 255 *.tif Si sarebbe tentati di aggiungere il parametro **''-n 255''** per indicare che il bianco è trasparente. In realtà si ottiene che un valore 255 in una qualunque delle bande origine diventa trasparente rispetto al valore di ''-init''. ==== gdal_retile.py ==== Si vuole cambiare la mattonellatura. Se ad esempio le tile originali sono troppe (**79 tile** 242x181, per un raster totale di **2420x1991**), si vorrebbe ottenere solo **4 tile 1210x996**. Si crea anche il nuovo tileindex (questa operazione potrebbe essere svolta da ''gdal_retile.py'' stesso). gdal_retile.py -v -co COMPRESS=LZW -ps 1000 1000 -targetDir 1k_retiled 1k/*.tif gdaltindex 1k_retiled_index.shp 1k_retiled/*.tif Manca la possibilità di inizializzare l'immagine con un colore di sfondo (vedi parametro **''-init''** di ''gdal_merge.py''). Se è necessario si può provare ad assemblare tutto in un unico raster e successivamente suddividere. In questo caso le mattonelle le facciamo quadrate 1024x1024. gdal_merge.py -v -o 25k_merged/25k.tif -init 255 25k/*.tif gdal_retile.py -v -ps 1024 1024 -targetDir 25k_retiled/ 25k_merged/25k.tif gdaltindex 25k_retiled_index.shp 25k_retiled/*.tif ===== Ricetta per creazione di un servizio WMS ===== - Creare indice (quadro d'unione) dei raster:gdaltindex 2002_index.shp 2002/*.tif - Creare le piramidi (overview). Per un singolo file .tif: gdaladdo --config USE_RRD YES 287050.tif 2 4 8 16 32 64 - Oppure per tutti i .tif in una directory: ls *.tif | xargs -I nome_file gdaladdo --config USE_RRD YES nome_file 2 4 8 16 32 64 - Con GDAL > 1.6.0 vedere ''man gdaladdo'' per il parametro **''%%-ro%%''** e **''%%-r gauss%%''** per creare file esterni e fare il resample di qualità migliore. - Creare il file .map: - Controllare l'estensione complessiva ogrinfo 2002_index.shp -summary 2002_index - Verificare che esistano almeno i seguenti parametri MAP.EXTENT 1672800 4843801 1688801 4856418 MAP.IMAGETYPE jpeg MAP.PROJECTION "+init=epsg:3003" WEB.METADATA.wms_title "WMS Ortofoto" WEB.METADATA.wms_onlineresource "http://192.168.2.10/cgi-bin/mapserv?map=..." WEB.METADATA.wms_srs "EPSG:3003" LAYER.STATUS OFF LAYER.PROJECTION "+init=epsg:3003" LAYER.METADATA.wms_title "Ortofoto 2001" LAYER.METADATA.wms_srs "EPSG:3003" ===== Legende ===== * **Font**: sono supportati i caratteri TrueType. * **Etichette**: viene utilizzato il contenuto del tag **''LAYER.CLASS.NAME''**. * **Codifica caratteri**: si indica con il tag **''ENCODING''**, fortemente consigliato **''UTF-8''**. Per il corretto funzionamento delle **''LABEL''** sono necessarie diverse librerie, tra cui **freetype** e **iconv**. Per vedere se MapServer è stato compilato con il supporto FreeType digitare: /usr/lib/cgi-bin/mapserv -v MapServer version 5.0.3 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS INPUT=EPPL7 INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE ===== Ottimizzazione ===== Ad ogni esecuzione di MapServer CGI vengono consumate molte risorse per inizializzare l'ambiente. La modalità **FastCGI** permette di mantenere un'istanza del programma sempre in esecuzione, risparmiando molto su ciascuna connessione. Ad esempio per 100 richieste GetCapabilities di un layer WMS si può passare da 8 a 2 secondi di attesa. Installare il pacchetto Debian **libapache2-mod-fastcgi**. La configurazione predefinita prevede di passare al modulo FastCGI tutte le richieste per eseguibili con estensione .fcgi. Con MapServer si può creare un link simbolico **''%%/usr/lib/cgi-bin/mapserv.fcgi -> mapserv%%''** da utilizzare al posto dell'originale **''mapserv''**. Tra i processi in esecuzione si noterà un'istanza di **''mapserv.fcgi''** anche in assenza di richieste da parte dei client. Se un file .map ha diversi layer provenienti dallo **stesso database** può essere utile aprire una sola connessione per tutto il mapfile, invece di aprire e chiudere la connessione per ogni layer. Nei layer interessati si aggiunge la direttiva **''PROCESSING''**: LAYER CONNECTIONTYPE POSTGIS PROCESSING "CLOSE_CONNECTION=DEFER" ...