- Introduction -
Ce tutoriel vous permettra d'appréhender au mieux la notion de serveur WFS puis de la mettre en application au moyen d'un exemple concret en vous basant sur MapServer et OpenLayers.
- Qu'est-ce que la norme WFS et comment elle fonctionne
- Faire de MapServer un serveur WFS
- Afficher une carte WFS avec OpenLayers
- Qu'est-ce que la norme WFS et comment elle fonctionne -
Contrairement au format WMS (Web Map Service) orienté image (carte), le format WFS (Web Feature Service) permet au moyen d'une URL formatée d'interroger des serveurs cartographique afin de manipuler des objets géographiques.
Ce protocole initié par l'Open Géospatial Consortium (OGC) est devenu un standard implémenté par la quasi-totalité des serveurs cartographiques. L'objectif du WFS est de permettre un accès en édition aux données géographiques afin de pouvoir les modifier, les créer ou les supprimer.
L'interrogation d'un serveur WFS se fait via une URL envoyée au serveur à laquelle sont passés des arguments bien définis. Ces mots-clés une fois mis bout à bout forment un ensemble compréhensible par le serveur cartographique.
Pour un serveur cartographique le seul paramètre obligatoire est (associé à une opération de type GetFeature) :
- NAME : nom de la couche à interroger.
Mais il en existe d'autres telles que :
- BBOX : Etendue des données
- VERSION : version du protocole
- SERVICE : Type de service à utiliser (WFS)
- SRS : Projection utilisée
Les différentes opérations qu'il est possible de réaliser sont les suivantes :
- GetCapabilities : Description des capacités du serveur WFS. Il indiquera les type de données ainsi que les opérations supportées sur chacune d'entre elles.
- DescribeFeatureType : Description de la structure de la donnée.
- GetFeature : Récupère un (ou les) objet géographique de la couche. Il est également possible de spécifier l'objet désiré au travers de requête attributaire ou spatiale.
- GetGmlObject : A web feature service may be able to service a request to retrieve element instances by traversing XLinks that refer to their XML IDs. In addition, the client should be able to specify whether nested XLinks embedded in returned element data should also be retrieved.
- Transaction : Support des requêtes transactionnelles. Une transaction peut être composée d'un ensemble d'opérations sur les objets (création, modification, mise à jour, suppression).
- LockFeature : Possibilité de bloquer l'accès à un objet géographique durant une transaction par la pose d'un verrou.
En se basant sur les opérations ci-dessus, il est possible de classer les serveurs WFS en 3 catégories :
- Basic WFS : Celui-ci doit, au moins, implémenter les opérations suivantes : GetCapabilities, DescribeFeatureType and GetFeature operations.
- XLink WFS : Celui-ci doit, en plus des opérations d'un Serveur WFS basique, supporter l'opération GetGmlObject
- WFS Transactionnel : Celui-ci doit, en plus des opérations d'un Serveur WFS basique, apporter un support transactionnel. Même si cela n'est pas obligatoire, il pourra également être capable de réaliser des opérations de type GetGmlObject et/ou LockFeature opérations
Voici un exemple d'URL :
http: //localhost/cgi-bin/mapserv?map=/var/www/html/wms/africa.map&typename=Africa&SERVICE=WFS&VERSION=1.0.0&
REQUEST=GetFeature&SRS=EPSG%3A4326&BBOX=-67.851625,-85.0776875,107.929625,108.2816875
Une application WFS est composée de 3 parties essentielles : le serveur cartographique, les données et le client.
Un exemple de requête serait la suivante : une requête de type "GetFeature" est envoyée par le navigateur au serveur cartographique. Celui-ci, en fonction de sa configuration et des données vérifie la validité de cette requête en fonction de sa configuration et des données qu'il possède; ensuite, celui-ci retourne le ou les objets géographiques demandés.
- Faire de MapServer un serveur WFS -
Cette partie suppose que vous soyez déjà familier de l'environnement MapServer et que vous sachiez comment est constitué un MapFile. Dans le cas contraire, je vous invite à lire auparavant ce tutoriel : Tutorial MapServer.
Pour spécifier à MapServer de fonctionner en tant que serveur WMS, il sera nécessaire d'ajouter différents attributs à votre MapFile. Les blocs à modifier sont les suivants :
- Un dans le bloc Web
- Trois dans le bloc Layer
- Le bloc Metadata
- Le bloc Projection
- L'attribut Dump
Pour le bloc Web il faut ajouter un sous bloc nommé METADATA qui est composé des éléments ci-dessous :
WEB METADATA "wfs_title" "WFS Demo Server" "wfs_onlineresource" "localhost/cgi-bin/mapserv?map=/pathToMapFile/africa.map&?" ## Recommended "wfs_srs" "epsg:4326" ## Recommended END END
Ensuite pour chaque couche il faudra ajouter deux blocs, le premier est obligatoire contrairement au second qui est optionnel mais fortement recommandé ainsi qu'un troisième attribut DUMP :
LAYER METADATA ### WFS "wfs_title" "Africa" "gml_featureid" "NAME" "gml_include_items" "all" END PROJECTION "init=epsg:4326" ##recommended END DUMP TRUE ... END
Pour un aperçu plus global vous pouvez également télécharger le MapFile qui a servi pour ce tutoriel.
- Afficher une carte WFS avec OpenLayers -
Pour interroger un serveur WFS vous devrez utiliser la classe OpenLayers.Layer.WFS.
Celle-ci prend en arguments obligatoires l'URL du serveur cartographique ainsi que le nom de la couche. Cela se fait de la manière suivante :
africaWFS = new OpenLayers.Layer.WFS( "Africa WFS", "http://pathToMapServ/cgi-bin/mapserv?map=/pathToMapFile/africa.map&", {typename: 'Africa'}, { extractAttributes: true} );
A noter que si vous désirez pouvoir utiliser les données attributaires de la couche vous devrez ajouter la propriété extractAttributes (true)
- Exemple avec une carte de l'Afrique -

Bonjour et merci pour ces
Bonjour et merci pour ces infos.
Je ne sais pas si je dois poster ici ou dans la section Android mais j'aurai besoin de récupérer un flux WFS à destination d'un Android.
Saurais-tu comment ouvrir le flux WFS avec un système Android ? Pour ce qui est de positionner un item, je sais faire, donc positionner une liste d'item ne doit pas être très compliqué, même en fonction d'un zoom ou autre. Ce qui m'intéresse est vraiment la lecture de ce flux WFS car j'aimerai avoir monFlux.mesItems grossièrement.
Si tu ne sais pas, aurais-tu une idée d'où trouver l'info ?
Merci.
Bonjour, un flux WFS n'est
Bonjour,
un flux WFS n'est rien d'autre que du XML.
Donc il suffit de parser ce flux dans Android - il doit bien y avoir une classe Java qui fait ça.
Fabien
En effet, merci. J'ai
En effet, merci.
J'ai commencé à récupérer ce fichier XML mais avant de le parser manuellement, j'ai trouvé une lib qui le fait déjà, alors autant ne pas réinventer la roue. Il s'agit de GeoTools que l'on peut trouver gratuitement ici sous forme de projet d'essai ou de fichier jar (zippé) tout simplement.
Pour ma part, j'ai eu besoin du fichier << net.opengis.wfs-2.7.0.1.jar >>.
Encore merci et bonne continuation !
Bonsoir, je suis assez
Bonsoir,
je suis assez nouveau dans le monde du sig, et cette article est intéressant.
j'aurai besoin de faire ceci avec un serveur mapserver + openlayers :
afficher une image, pouvoir me déplacer dedans, zoomer, replacer, les bases en fait.
Mais aussi pouvoir activer/désactiver l'affichage de layers.
pas d'édition donc.
Seulement, avec wms, il renvoie une image, donc, une activation/désactivation de layers ne serait possible.
avec wfs alors ? mais comment procéder ?
Pouvez-vous m'aiguiller sur comment je dois m'orienter ?
Merci d'avance.
Bonjour, Je viens de lire
Bonjour,
Je viens de lire dans la doc de OpenLayers qu'ils comptaient supprimer la classe OpenLayers.Layer.WFS à la prochaine mise à jour majeure (la 3.0) : http://dev.openlayers.org/apidocs/files/OpenLayers/Layer/WFS-js.html. Ils conseillent d'utiliser OpenLayers.Layer.Vector à la place.
Je me serais bien contenté de la méthode présentée ici mais comme elle a l'air d'avoir une espérance de vie plutôt courte, je ne sais pas si c'est un si bon choix que ca. Par contre, j'ai beau eu chercher, je n'ai pas trouvé d'infos sur la façon dont utiliser la classe OpenLayers.Layer.Vector avec MapServer...
Bonjour, Le WFS est un
Bonjour,
Le WFS est un protocole. Protocole qu'implémente ensuite divers clients, dont OpenLayers.
Si c'est la partie code qui vous freine, vous pouvez directement utiliser la classe Vector à la place.
Cela sera complètement transparent.
En tout cas merci pour l'info, je ne savais pas que la classe WFS allait être à terme supprimée.
Arnaud
Bonjour, Merci de votre
Bonjour,
Merci de votre réponse. J'avais laissé le sujet de côté pendant quelque temps, d'où le temps de ma réponse.
Cependant, c'est remplacer la classe WFS par la classe Vector qui me pose problème.
Quelques bouts de code :
Ceci ne fonctionne pas :
new OpenLayers.Layer.Vector( "estran", { strategies: [new OpenLayers.Strategy.BBOX()], protocol: new OpenLayers.Protocol.WFS( { url: "http://localhost/cgi-bin/mapserv?", featureType: "lanildut", version: "1.1.0", srsName: "EPSG:27582", featureNS: "http://127.0.0.1" }), projection: new OpenLayers.Projection("EPSG:27582"), } )Alors que avec ceci, aucun problème :
new OpenLayers.Layer.WFS( "lanildut", "http://localhost/cgi-bin/mapserv?", { map: MAPFILE, typename: "lanildut", projection: "EPSG:27582", extractAttributes: true, transparent: true }, {style: featureStyle(1, "#000000", "#339933", 0.5)} )Il y a sans doute quelque chose que j'ai mal saisi avec les nouveaux paramètres qui se rajoutent tels que "FeatureNS"...
Des suggestions ?
Bonjour, J'ai une petite
Bonjour,
J'ai une petite question idiote à laquelle j'ai du mal à trouver une réponse :
Est-il possible de "poster" des features via MapServer dans une base PostGIS ou bien est-on obliger de passer par FeatureServer ou autre ?
Bonjour, Non il n'est pas
Bonjour,
Non il n'est pas possible à d'utiliser MapServer comme un serveur WFS-T (cf site de MapServer).
GeoServer le permet.
Arnaud
Merci beaucoup, je n'avais
Merci beaucoup, je n'avais pas vu la dernière section :
"This is just a basic WFS (read-only): transaction requests are not supported and probably never will given the nature of MapServer. GeoServer is recommended for those needing WFS-T support."
arrivez-vous à reprojeter la
arrivez-vous à reprojeter la couche WFS en epsg:900913 (google mercator) dans openlayers ?
moi je lutte et je n'y arrive pas !!!!!!!!!!!!!!!!!!!!
Bonjour, Je n'utilise que
Bonjour,
Je n'utilise que très rarement les cartes Google Maps.
Néanmoins, je vous propose de vous joindre à cette discussion sur le forumSIG où l'auteur a également les mêmes soucis.
Arnaud
Bonjour, Quelle est la
Bonjour,
Quelle est la syntaxe pour réaliser une telle carte avec php mapscript s'il vous plaît ?
OpenLayers et php Mapscript
OpenLayers et php Mapscript sont deux technologies différentes (Javascriopt / PHP) ayant des objectifs différents. Il n'est pas possible de réaliser ce genre de traitements avec PHP Mapscript.
Merci pour votre réponse. Je
Merci pour votre réponse.
Je voulais dire qu'elle est la syntaxe pour construire le mapfile avec mapscript.
Depuis j'ai réussi avec des données issues du format EDIGéO :
<?php $table = 'edigeo'; $con = pg_connect('dbname = mabase user = monuser password = monpass'); $map = ms_newMapObj(''); $extent = pg_query($con, 'select xmin(extent(the_geom)), ymin(extent(the_geom)), xmax(extent(the_geom)), ymax(extent(the_geom)) from '.$table); $extent = pg_fetch_row($extent); $map->setextent($extent[0], $extent[1], $extent[2], $extent[3]); $map->set('width', 530); $map->set('height', 400); $map->set('units', MS_METERS); $map->web->set('imagepath', 'tmp/'); $map->web->set('imageurl', '/tmp/'); $map->setMetadata('wfs_title', $table); $map->setMetadata('wfs_onlineresource', 'mapserver/cgi-bin/mapserv?map=/monpath/tmp/'.$table.'.map&?'); $map->setMetadata('wfs_srs', 'epsg:4326'); $layer = ms_newLayerObj($map); $layer->set('data', 'the_geom from '.$table.''); $layer->set('connection', 'host=localhost dbname=mabase user=monuser password=monpass'); $layer->set('connectiontype', MS_POSTGIS); $layer->set('status', MS_ON); $layer->set('type', MS_LAYER_POLYGON); $layer->set('name', $table); $layer->setMetadata('wfs_title', $table); $layer->setMetadata('gml_featureid', 'GID'); $layer->setMetadata('gml_include_items', 'all'); $layer->set('dump', TRUE); $img = $map->draw(); $url = $img->saveWebImage(); $map->save('./tmp/'.$table.'.map'); pg_close($con); ?> <html> <head> </head> <body> <?php echo '<img border=0 src='.$url.' width='.$map->width.' height='.$map->height.'/>' ?> </body> </html>Maintenant, je cherche comment optimiser l'affichage en fonction du nombre d'entité (j'ai plus de 3900 features) côté client. Si vous avez des pistes...
Ici votre image est générée
Ici votre image est générée dynamiquement depuis PhpMapScript. Pourquoi n'avoir pas simplement utilisé un simple mapfile? En effet, avec MapScript comment allez-vous utilisez OpenLayers?
Si vous utiliser toujours OpenLayers le mieux est de s'orienter vers la classe strategy.
Bonjour, Le phpmapscript
Bonjour,
Le phpmapscript génére dynamiquement le mapfile (format WFS) que j'appelle depuis OpenLayers comme vous le décrivez dans le tuto.. Je génère l'image uniquement pour vérifier que le script fonctionne.
Je vais regarder la classe strategy.
Merci !
Bonjour, je suis entrain de
Bonjour,
je suis entrain de réaliser votre tuto très bien réalisé; Cependant quand je passe ma souris sur la carte d'Afrique la surbrillance reste des fois sur les pays.
Merci
Peut-être un petit temps de
Peut-être un petit temps de latence. Le javascript n'est pas connu pour son optimisation :)
Vivement TraceMonkey
Voila comme promis mais avec
Voila comme promis mais avec un peu de retard le tutoriel pour afficher les données dans un popup
> http://geotribu.net/node/86
J'ai configuré un WFS et
J'ai configuré un WFS et j'arrive à récupérer les infos dans OpenLayer.
Par contre je voudrais pouvoir afficher dans une info bulle (popup) les valeurs des attributs de la couche WFS : comment accède t-on à ces valeurs ? (j'ai bien configuré avec extractAttributes: true dans la création du layer et "gml_include_items" "all" dans le mapfile).
ça doit être au niveau de l'objet feature mais dans la doc openlayer je ne trouve pas d'explication.
Merci d'avance si vous pouvez me renseigner
Bonjour, Pour accéder aux
Bonjour,
Pour accéder aux données vecteur openlayers utilise feature.attributes.
Par exemple pour l'exemple ci-dessus voici le code utilisé :
options = {
hover: true,
onSelect: function(feature) {OpenLayers.Util.getElement('name').innerHTML = " Pays : " + feature.attributes.NAME},
selectStyle :feature_style
};
sf = new OpenLayers.Control.SelectFeature(africaWFS, options)
J'ai donc déclaré un nouveau control qui se déclenche lorsque l'objet est sélectionne. Vous pouvez faire exactement la même chose mais en ajoutant à l'intérieur de la fonction onSelect l'ouverture du Popup avec les infos rattachés.
J'essayerai de donner un exemple concret cette semaine.
Arnaud
Bonjour, J'essaye de suivre
Bonjour,
J'essaye de suivre votre tutoriel, mais j'obtiens des carrés rose à la place de ma carte.
Voici mon Mapfile
..............................................................................................;
# Map file created from QGIS project file C:/Essai/test.qgs
# Edit this file to customize for your map interface
# (Created with PyQgis MapServer Export plugin)
MAP
NAME "essai"
# Map image size
SIZE 1024 768
UNITS meters
EXTENT 823426.170040 1855953.400000 1000161.829960 1975552.600000
FONTSET 'C:/essai/fonts.txt'
SYMBOLSET 'C:/essai/symbols.txt'
PROJECTION
"init=EPSG:27571"
END
# Background color for the map canvas -- change as desired
IMAGECOLOR 255 255 255
IMAGEQUALITY 95
IMAGETYPE png
OUTPUTFORMAT
NAME png
DRIVER 'GD/PNG'
MIMETYPE 'image/png'
IMAGEMODE RGBA
EXTENSION 'png'
END
# Legend
LEGEND
IMAGECOLOR 255 255 255
STATUS ON
KEYSIZE 18 12
LABEL
TYPE BITMAP
SIZE MEDIUM
COLOR 0 0 89
END
END
# Web interface definition. Only the template parameter
# is required to display a map. See MapServer documentation
WEB
# Set IMAGEPATH to the path where MapServer should
# write its output.
IMAGEPATH 'C:/ms4w/Apache/htdocs/mapserver/tmp/'
# Set IMAGEURL to the url that points to IMAGEPATH
# as defined in your web server configuration
IMAGEURL '/mapserver/tmp/'
# WMS server settings
METADATA
'ows_title' 'essai'
'ows_onlineresource' 'http://localhost/cgi-bin/mapserv.exe?map=C:/essai/essai.map'
'ows_srs' 'EPSG:27571'
END
#Scale range at which web interface will operate
# Template and header/footer settings
# Only the template parameter is required to display a map. See MapServer documentation
TEMPLATE 'fooOnlyForWMSGetFeatureInfo'
END
LAYER
NAME 'Dep'
TYPE POLYGON
DUMP true
TEMPLATE fooOnlyForWMSGetFeatureInfo
EXTENT 823426.170040 1855953.400000 1000161.829960 1975552.600000
DATA 'C:/essai/Dep.shp'
METADATA
'ows_title' 'Dep'
END
STATUS ON
PROJECTION
"init=EPSG:27571"
END
CLASS
NAME 'Dep'
STYLE
SYMBOL 0
SIZE 7.0
OUTLINECOLOR 0 0 0
COLOR 1 144 50
END
END
END
END
..............................................................................................
et mon HTML
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <style type="text/css"> #map { width: 800px; height: 475px; border: 1px solid black; } </style> <script src="http://openlayers.org/dev/lib/OpenLayers.js"></script> <script type="text/javascript"> <!-- var map, layer; function init(){ map = new OpenLayers.Map( 'map' ); layer = new OpenLayers.Layer.MapServer( "OpenLayers WMS", "http://localhost/cgi-bin/mapserv", {map: 'C:/essai/essai.map&'} ); map.addLayer(layer); map.zoomToMaxExtent(); } // --> </script> </head> <body onload="init()"> <div id="map"></div> </body> </html>________________________________________________________________________________________