UMN MapServer est un serveur cartographique prenant en charge un grand nombre de formats de fichier. Il est possible de l'utiliser en mode CGI ou à travers des langages de script tels que PHP, Ruby, Java, C#, etc à l'aide de mapScript. MapServer constitue donc un environnement de développement d'outils plus qu'un outil en lui même prêt à être installé et à être utilisé directement.
Cet article a pour but de présenter les différentes nouveautés et corrections importantes de cette nouvelle version. Cette présentation n'est pas forcément exhaustive et il est préférable de se tourner vers le site officiel de MapServer. Ce document est composé de diverses traductions des RFC et documentation écrite suite à ces changements. Il se peut que certaines parties n'aient pas été développées, la documentation n'ayant pas encore été mise à jour !
D'autres améliorations sont également présentes :
- amélioration des performances pour la prise en charge des gros shapefile ;
- amélioration des performances pour le rendu d'AGG (d'une manière assez important dans certain cas) ;
- contour des étiquettes floues pour AGG ;
- opacité au niveau des styles pour AGG ;
- gestion de la quantification et des palette pour les modes PNG et RGBA ;
- gestion de SOS 1.0.0 ;
- gestion de WFS 1.1.0 ;
- gestion de l'authentification par proxie et http pour les requêtes WMS en cascade ;
- calcul des points des étiquettes pré-découpées (aide dans la génération de tuile) ;
- prise en charges des attributs des balises des templates étendue (par exemple shpext, mapext).
Date des sorties versions intermédiaires
- Sortie prévue : 17-07-2008
- Versions béta : 14-06-2008, 18-06-2008, 02-07-2008
- Prochaine version : 5.4, 2009
Nouveautés
Simplification des templates pour la gestion des rendu des requêtes
- RFC 36
- Développeur : Steve Lime
Deux constats ont été fait :
- Pour l'instant un pilote comme GML n'est pas disponible au CGI pour représenter des résultats de requête ;
- Le schéma de template (HEADER/TEMPLATE/FOOTER) pour les requêtes n'est pas "user friendly" ni ne permet la génération multiple de formats. Nous avons une couche => une définition de template.
Les solutions sont les suivantes :
<code mapserver>
OUTPUTFORMAT
NAME 'gml3'
DRIVER GML3
MIMETYPE 'text/xml; subtype=gml/3.2.1'
END
</code>
3. Permet également des modes applicable (par exemple §WFS, WMS, SOS) pour utiliser les formats de type DRIVER/TEMPLATE (c'est à dire avertir dans les réponses GetCapabilities, géré à travers l'API [e.g. request=GetFeature&outputFormat=text/xml; subtype=gml/3.2.1]), mappé à partir de OUTPUTFORMAT/MIMETYPE. Pour l'instant le pilote WCS nécessite que le développeur définisse explicitement les formats de sortie gérés, les autres services peuvent faire la même chose et peuvent référencer les sorties en template.
<code mapserver>
OUTPUTFORMAT
NAME 'kml'
DRIVER TEMPLATE
MIMETYPE 'application/vnd.google-earth.kml+xml'
TEMPLATE 'myTemplate.kml'
END
OUTPUTFORMAT
NAME 'geojson'
DRIVER TEMPLATE
MIMETYPE 'application/json; subtype=geojson'
TEMPLATE 'myTemplate.js'
END
</code>
<code javascript>
[include src="templates/header.html"]
[resultset name=lakes]
... contenu des anciennes couches HEADER, si une couche n'a pas de résultat ce bloc disparaitra ...
[feature]
... répéter ce bloc pour chaque objet dans le pool de résultat ...
[join name=join1]
...répéter ce bloc pour chaque ligne de jointure ...
[/join]
[/feature]
... contenu des anciennes couches FOOTER vient ici ...
[/resultset]
[resulset name=streams]
... contenu des anciennes couches HEADER, si une couche n'a pas de résultat ce bloc disparaitra ...
[feature]
...répéter ce bloc pour chaque objet dans le pool de résultat ...
[/feature]
... contenu des anciennes couches FOOTER vient ici ...
[/resultset]
[include src="templates/footer.html"]
</code>
Un exemple spécifique à GML 3 donnerait :
<code xml>
<?xml version="1.0" encoding="ISO-8859-1"?>
[resultset layer=mums]
<MapServerUserMeetings xmlns="http://localhost/ms_ogc_workshop" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost/ms_ogc_workshop ./mums.xsd">
<gml:description>This is a GML document which provides locations of all MapServer User Meeting that have taken place</gml:description>
<gml:name>MapServer User Meetings</gml:name>
<gml:boundedBy>
<gml:Envelope>
<gml:coordinates>-93.093055556,44.944444444 -75.7,45.4166667</gml:coordinates>
</gml:Envelope>
</gml:boundedBy>
[feature]
<gml:featureMember>
<Meeting>
<gml:description>[desc]</gml:description>
<gml:name>[name]</gml:name>
<gml:location>
<gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:pos>[x] [y]</gml:pos>
</gml:Point>
</gml:location>
<year>[year]</year>
<venue>[venue]</venue>
<website>[url]</website>
</Meeting>
</gml:featureMember>
[/feature]
<dateCreated>2007-08-13T17:17:32Z</dateCreated>
</MapServerUserMeetings>
[resultset]
</code>
Un exemple GeoJSON donnerait :
<code javascript>
[resultset layer=foo] {
"type": "FeatureCollection",
"features": [
[feature trim=',']
{
"type": "Feature",
"id": "[id]",
"geometry": {
"type": "PointLineString",
"coordinates": [
{
"type": "Point",
"coordinates":
}
]
},
"properties": {
"description": "[description]",
"venue": "[venue]",
"year": "[year]"
}
},
[/feature]
]
}
[/resultset]
</code>
<note>
Il est souvent problématique d'avoir des caractères finaux de séparation d'enregistrement après l'enregistrement final. Par exemple, dans le template JSON ci-dessus la virgule finale dans le bloc //[feature]// cause des problèmes avec Internet Explorer. Un attribut "trim" permettra de demander au processeur de template de supprimer cette chaîne à la fin de la sortie pour le dernier objet calculé.
</note>
<note>
Une balise //resultset// peut être appliquée à de nombreuses couches l'attribut //name// prendra une liste de couches séparées par des virgules. L'ordre de la liste est l'ordre dans lequel ils seront représentés. Il est possible que des groupes soient utilisés mais il semble que cela soit un cas d'utilisation assez rare.
</note>
<note>
Une balise //resultset// prendra également un attribut //maxresults// afin que le nombre d'objets récupérés puisse être limité.
</note>
Ajout et l'amélioration des Références Spatiales
- RFC 37
- Développeur : Howard Butler
1 Objectif
Ces améliorations sont disponible en option et n'interfèrent pas avec les méthodes des définitions précédente de PROJECTION.
2 Historique des Références Spatiales dans MapServer
Le dispositif de reprojection de MapServer ignore le fait que l'objet PROJECTION des objets LAYER est différent de celle de l'objet MAP. Lorsque c'est le cas, MapServer reprojète les données de l'objet LAYER vers la projection définie dans l'objet MAP pendant la création de la carte. Les services OGC interagissent aussi ici, et lorsqu'une référence spatiale est définie comme "disponible" en utilisant le mécanisme des METADATA, un client peut demander des cartes dans une référence spatiale différente que celle définie par défaut, ce qui démarre le dispositif de reprojection.
2.1 Définition
<code mapserver>
PROJECTION
"init=epsg:4326"
END
</code>
et les définitions formatées en proj-4 de la forme :
<code mapserver>
PROJECTION
"proj=cea"
"lon_0=0"
"lat_ts=45"
"x_0=0"
"y_0=0"
"ellps=WGS84"
"units=m"
"no_defs"
END
</code>
2.2 Observations des performances
Alternativement, la définition des codes EPSG/ESRI des références spatiales de MapServer permet à celui-ci de se décharger de la description proj4 sur proj4 lui-même, avec une simple recherche de fichier des tables. Cependant, ce mécanisme est actuellement un goulot d'étranglement, puisque chaque recherche nécessite un passage sur un fichier pour rechercher les correspondances de l'identifiant données et de retourner la définition proj4.
2.3 Usage
De plus, un site Internet((http://spatialreference.org)) a été développé pour faciliter ce travail mais est clairement une solution de dépannage et non une solution permanente au problème. Il n'est pas pratique de développer les références spatiales pour chaque couche dans un mapfile pour chaque carte dessinée à partir d'un site Internet. spatialreference.org fournit des outils de conversions pour permettre aux utilisateurs de copier leur WKT et de recevoir un bloc PROJECTION de MapServer, mais cette approche rejette encore le travail sur les utilisateurs.
3 Définition de la fonctionnalité
<code mapserver>
PROJECTION
TYPE TYPEENUM
VALUE "Une définition"
END
</code>
Les énumérations de TYPE suivantes seraient gérées :
- NATIVE
- PROJ4
- EPSG
- FILE
- OGCWKT
- ESRIWKT
<code mapserver>
# Utilise la projection de la définition de couche comme définition de projection
# Cela peut ne pas être disponible pour toutes les sources de données ou types de couche
# (shapefile, SDE, OGR, etc.).
PROJECTION
TYPE NATIVE
END
</code>
<code mapserver>
# Utilise une définition de proj4 (c'est essentiellement le même que d'habitude sauf
# qu'il est définie d'une autre manière)
PROJECTION
TYPE PROJ4
VALUE "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
END
</code>
<code mapserver>
# Utilisez un code EPSG
PROJECTION
TYPE EPSG
VALUE "4326"
END
</code>
<code mapserver>
# lit la définition à partir d'un fichier
PROJECTION
TYPE FILE
VALUE "../myfile.prj"
END
</code>
<code mapserver>
# Utilise une définition WKT de l'OGC (des échappements peuvent être nécessaire)
PROJECTION
TYPE OGCWKT
VALUE 'GEOGCS["WGS 84",
DATUM["WGS_1984",
SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,
AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]]'
END
</code>
<code mapserver>
# Utilise une définition WKT d'ESRI (des échappements peuvent être nécessaire)
PROJECTION
TYPE ESRIWKT
VALUE 'GEOGCS["GCS_WGS_1984",
DATUM["D_WGS_1984",
SPHEROID["WGS_1984",6378137,298.257223563]],
PRIMEM["Greenwich",0],
UNIT["Degree",0.017453292519943295]]'
END
</code>
Gestion native de Microsoft SQL Server 2008
- RFC 38
- Développeur : Howard Butler
1 Objectif
2 Contexte
3 Détails d'utilisation
<code mapserver>
LAYER
NAME "Routes"
CONNECTIONTYPE PLUGIN
PLUGIN "C:ms4wpluginsmsplugin_mssql2008.dll"
CONNECTION "server=mysqlserver2008.com;uid=dbusername;pwd=dbpassword;database=Roads Database;Integrated Security=false"
DATA "the_geom from roads"
TYPE LINE
STATUS ON
PROJECTION
"init=epsg:4326"
END
CLASS
STYLE
COLOR 0 0 255
WIDTH 8
END
END
END
</code>
Gestion du webservice WCS 1.1.x
- RFC 41
- Développeur : Frank Warmerdam
Aperçu
Limitations du protocole WCS 1.1
- Seulement un <Field> peut être associé avec le domaine de couverture lorsqu'il est servit par MapServer.
- Seulement deux types d'Axe seront gérés, un axe "Bands" et un axe "Time".
Usage
4.1 GetCapabilities
SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCapabilities
4.2 DescribeCoverage
SERVICE=WCS&VERSION=1.1.0&REQUEST=DescribeCoverage&IDENTIFIER=spaceimaging
4.3 GetCoverage
- //VERSION=version// : version demandée ;
- //REQUEST=GetCoverage// : nom demandé ;
- //IDENTIFIER=coverage_name// : nom d'une couverture disponible, comme affiché dans la réponse du ''GetCapabilities'' ;
- //BOUNDINGBOX=minx,miny,maxx,maxy,crs// : coins de la //bounding box// ('le plus bas' 'à gauche', 'le plus haut' 'à droite'), et le //CRS// dans lequel ils sont. Le //CRS// est décrit en utilisant un //URN//, voir plus bas pour plus d'information.
- //FORMAT=output_format// : format de sortie (type mime) d'une produit de grille, comme définie dans la réponse du ''GetCapabilities''.
- //GRIDBASECRS=crs// : la grille de base du //CRS// (//URN//).
- //GRIDCS=crs// : la grille du //CRS// (//URN//).
- //GridType=urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs// : c'est la seule valeur gérée par MapServer.
- //GridOrigin=x_origin,y_origin// : le point d'échantillon pour le pixel en haut à gauche.
- //GridOffsets=xstep,ystep// : La taille des écarts x et y pour l'échantillonnage des grilles (résolution). Les deux sont positifs.
//RangeSubset=selection: //Sélectionne un sous ensemble de domaine, et une méthode d'interpolation. Actuellement seulement un sous-ensemble sur les bandes sont permis. En fonction des noms de l'ensemble des domaines, cela peut prendre la forme de //"BandsName[bands[1]]"// pour sélectionner la bande 1, ou //"BandsName:bilinear[bands[1]]"// pour sélectionner la bande 1 avec une interpolation bilinéaire.
Une simple requête ''GetCoverage'' pourrait donc ressembler à ceci :
SERVICE=WCS&VERSION=1.1.0&REQUEST=GetCoverage&IDENTIFIER=dem&FORMAT=image/tiff
&BOUNDINGBOX=43,33,44,34,urn:ogc:def:crs:EPSG::4326
Une plus complexe à cela :
SERVICE=WCS&VERSION=1.1.0&REQUEST=GetCoverage&IDENTIFIER=dem&FORMAT=image/tiff
&BOUNDINGBOX=33,43,34,44,urn:ogc:def:crs:EPSG::4326
&GridBaseCRS=urn:ogc:def:crs:EPSG::4326&GridCS=urn:ogc:def:crs:EPSG::4326
&GridType=urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs
&GridOrigin=33,44&GridOffsets=0.01,0.01
&RangeSubset=BandsName:bilinear[bands[1]]
4.4 URN
urn:ogc:def:crs:EPSG::4326
urn:ogc:def:crs:EPSG:27700
urn:ogc:def:crs:OGC::CRS84
BOUNDINGBOX=34,-117,35,-116,urn:ogc:def:crs:EPSG::4326
Gestion de la redirection des cookies
- RFC 42
- Développeur : Julien-Samuel Lacroix
Contexte
Une méthode d'authentification dans un environnement de serveur distribué est d'utiliser des cookies HTTP. Les cookies HTTP sont utilisés par les serveurs web pour différencier les utilisateurs et pour maintenir les données liées à l'utilisateur pendant sa navigation, éventuellement à travers plusieurs visites et pour des statistiques. Techniquement, les cookies sont des morceaux arbitraires de données choisies par le serveur web et envoyés au navigateur. Le navigateur les renvois non changés au serveur. L'amélioration de MapServer permet à l'application de renvoyer n'importe quel cookie HTTP ( d'une requête //http// ou //https// pour les méthodes //get// ou //post//) reçu d'un client à n'importe quel serveur ou service auquel MapServer pourrait récupérer des informations.
Cela nécessite que MapServer puisse recevoir et renvoyer des cookies au nouveau service pendant la requête pour les opérations (cascades) tels que (mais non limité à) les requêtes WMS : GetMap, GetFeatureInfo et les requêtes WFS pour GetFeature.
Méthodologie d'implémentation
Exemple de //ows_http_cookie// dans METADATA :
<code mapserver>
LAYER
...
METADATA
"ows_http_cookie" "forward" # cela fera suivre le cookie envoyé à MapServer
END
...
</code>
<code mapserver>
LAYER
...
METADATA
"ows_http_cookie" "cookie1=my_value; cookie2=myvalue; " # cela fera suivre la valeur de la méta-donnée
END
...
</code>
Problèmes d'implémentation
Puisque MapServer actuellement n'a pas de mécanisme pour associer des informations d'un état d'une application dans un objet map, il n'y a actuellement aucun meilleur mécanisme en place pour stocker les données du cookie reçues du client et envoyées au code de rendu qui appel le WMS distant. Dû à l'absence d'une meilleur solution, pour le moment il faut utiliser la méta-données //http_cookie_data// en sachant que ce n'est pas la meilleur solution et que dès qu'il y en aura une meilleur pour stocker et envoyer l'état de l'application dans un objet map alors cette méda-donnée sera obsolète et remplacée par un nouveau mécanisme. Les développeurs d'application MapScript définissant cette méta-donnée //http_cookie_data// doivent être conscient de cela et être préparé à faire évoluer leur application lors d'une future révision de MapServer.
Un autre problème est qu'aucun encodage n'est actuellement réalisé avec la méta-donnée //http_cookie_data//. Les méta-données mal formatés peuvent casser l'en-tête HTTP d'une requête. Curl n'encode pas la valeur du cookie, seul les caractères avec une valeur entre 32 et 126 (caractère ASCII imprimable) sont autorisés.
MapScript
<code php>
foreach($_COOKIE as $szKey => $szValue)
{
$szHTTPCookies .= "$szKey=$szValue; ";
}
$oMap->setMetadata("http_cookie_data", $szHTTPCookies);
$oMap->setMetadata("ows_http_cookie", "forward");
$oMap->draw();
</code>
Génération des tuiles directe pour l'API de Google Map
- RFC 43
- Développeur : Paul Ramsey
Aperçu
Solution technique
http://host/tile?x={X}&y={Y}&z={Z}.png
Voyez
http://code.google.com/apis/maps/documentation/reference.html#GTileLayer
Pour MapServer, le motif simple de l'URL sera :
http://host/cgi-bin/mapserv?map=/the.map&layers=foo,bar&mode=tile&tilemode=gmap&tile={X}+{Y}+{Z}
Le résultat permettra de réaliser une carte Google avec Mapserver aussi facilement que :
<code javascript>
var url = "http://host/cgi-bin/mapserv?";
url += "map=/the.map&";
url += "layers=parcels&";
url += "mode=tile&";
url += "tilemode=gmap&";
url += "tile={X}+{Y}+{Z}";
var myLayer = new GTileLayer(null,null,null,
{
tileUrlTemplate:url,
isPng:true,
opacity:0.5
}
);
var map = new GMap2(document.getElementById("map"));
map.addOverlay(new GTileLayerOverlay(myLayer));
</code>
Une carte Virtual Earth avec MapServer ressemblera à :
<code javascript>
var url = "http://host/cgi-bin/mapserv?";
url += "map=/the.map&";
url += "layers=parcels&";
url += "mode=tile&";
url += "tilemode=ve&";
url += "tile=%4";
map = new VEMap("map");
map.LoadMap();
var tileSourceSpec = new VETileSourceSpecification( "myLayer", url );
tileSourceSpec.Opacity = 0.3;
map.AddTileLayer(tileSourceSpec, true);
</code>
Une requête avec ''tilemode '' à //gmap// implique les paramètres suivants :
- Le paramètre //tile// sera de la forme : x y zoom.
- Le CRS en sortie sera définie à "spherical mercator" (EPSG:900913).
- Les limites du service sera d'étendue global. Le niveau de "zoom" maximal (0) aura une seule tuile.
- Les niveaux de "zoom" partiront de 0.
- L'axe des "y" des coordonnées des tuiles débuteront du haut vers le bas.
- L'axe des "x" des coordonnées des tuiles débuteront de la gauche vers la droite.
- Les tuiles en sortie auront une taille de 256x256.
- Chaque niveau de zoom sera lié à leur parent et enfant par une puissance de deux.
Une requête avec ''tilemode'' à //ve// implique les paramètres suivants :
- Le paramèter //tile// utilisera le schéma de numérotation des tuiles de VE, par exemple "//0312//". Lisez la page http://msdn.microsoft.com/en-us/library/bb545006.aspx pour plus de détails.
- Le CRS en sortie sera définie à "spherical mercator" (EPSG:900913).
- Les limites du service sera d'étendue global. Le niveau maximal aura 4 tuiles ((0, 1, 2, 3).
- Les tuiles en sortie auront une taille de 256x256.
- Chaque niveau de zoom sera lié à leur parent et enfant par une puissance de deux.
L'API du mode tile de MapServer ne tentera pas explicitement de s'intéresser aux problèmes des étiquettes en méta-tuilage ou en cross-tuilage. Cependant, les étapes suivantes seront prises en compte pour tenter de minimiser ces problèmes :
- les phases futures auront un rendu légèrement plus grande que la tuile et donc couperont les pixels des bords en trop.
Site officiel : MapServer
Autres Liens : Les tests sur le blog de Guillaume Sueur (Mapserver, toujours plus vite ...)