Un essai avec Vagrant et osmbase

Update le 30 décembre 2013
Suite à un billet de @alanboudrault, sur l'utilisation d'un environnement virtuel pour développer avec Mapserver, j'ai testé l'utilisation de Vagrant pour améliorer notre processus interne de tests unitaires sur nos projets Open Street Map.   J'ai tout de suite aimé la simplicité de l'outil et la rapidité qu'il me donne pour monter un environnement jettable à l'aide de quelques lignes de commandes.  Il faut voir Vagrant comme un outil exploitant un moteur de machine virtuel comme Virtual Box ou VMware Fusion.  Sa force sera d'être rapidement configurable et réutilisable avec un Vagrantfile.

Considérons que vous avez déjà installé Vagrant et VirtualBox. Dans une fenêtre terminale (Mac, Ubuntu ou Windows), on commence par télécharger une box vagrant de type Ubuntu et on va l'initialiser:

mkdir vagrant
cd vagrant
vagrant box add precise32 http://files.vagrantup.com/precise32.box
vagrant init precise32

L'initiation de la VM avec Vagrant, vient de créer un fichier Vagrantfile.  Je garde ce config hyper simple pour l'instant. Il me permettra de me connecter au besoin sur ma VM avec pgAdmin au serveur "localhost" sur le port 5555, et d'accéder au serveur Web localhost via le port 8080 (  http://localhost:8080):

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "precise32"

# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
config.vm.network :forwarded_port, guest: 5432, host: 5555
config.vm.network :forwarded_port, guest: 80, host: 8080
...
end
On va démarrer la VM et s'y connecter:
vagrant up
vagrant ssh
Utilisateur Windows: J'utilise ici un client ssh par défaut sur mon macbook. Pour les utilisateurs Windows, je conseille toujours d'utiliser le client ssh MobaXtrem parce qu'il est très pratique pour les moins habitués. L'utilitaire Putty peut aussi être utilisé. Vagrant donnera ce genre d'information (après vagrant up) pour faire la connexion avec MobaXtrem:
Host: 127.0.0.1
Port: 2222
Username: vagrant
Private key: C:/Documents and Settings/mapgears/.vagrant.d/insecure_private_key

J'utilise toujours le user par défaut de vagrant. Un fois connecté au serveur, configurer la langue du nouveau serveur dans le profile vagrant. Ça reste une étape toujours importante pour supporter convenablement les accents dans votre base de données Postgresql:

export LANGUAGE=en_CA.UTF-8
export LANG=en_CA.UTF-8
export LC_ALL=en_CA.UTF-8
sudo localedef -i en_CA -f UTF-8 en_CA
sudo locale-gen en_CA.UTF-8
sudo update-locale
sudo sudo dpkg-reconfigure locales
On doit maintenant faire la mise à jour du serveur avec un script VirtualBox et brancher le dépôt logiciels géomatiques UbuntuGIS (version precise):
sudo sh postinstall.sh
sudo apt-get update
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:ubuntugis/ppa
sudo apt-get update
Installation de Postgresql/PostGIS
sudo apt-get install -y postgresql-9.1 postgresql-server-dev-9.1 postgresql-contrib-9.1 postgis
Installation d'outils
sudo apt-get install -y apache2 binutils gdal-bin checkinstall git vim screen make python-virtualenv python-pip python-all-dev osm2pgsql osmosis 
Installation Mapserver / Mapcache
sudo apt-get install -y cgi-mapserver mapserver-bin libmapcache mapcache-cgi mapcache-tools libapache2-mod-mapcache
sudo mkdir /tmp/ms_tmp
sudo chown www-data:www-data /tmp/ms_tmp
NOTE: Pour faire toutes les opérations en une seule étape, créer un fichier init.sh avec vi à l'aide de ce Gist init.sh

Par la suite on installe un nouvelle BD Postgresql/PostGIS OSM avec un encodage UTF-8 (voir ce billet pour instructions):

Ne reste plus qu'à faire un peu de magie avec ce repo osmbase. Le makefile contenu dans ce projet va télécharger les données requises et lancer imposm avec notre petit fichier OSM préféré de la Nouvelle-Calédonie pour construire ma carte QA et de plus j'active un environnement virtuel python. Enfin, simplement modifier les variables de départ du makefile pour vos besoins.

virtualenv venv
source venv/bin/activate
pip install imposm
git clone https://github.com/smercier/osmbase.git
cd osmbase
make
make imposm
Si l'installation se passe sans erreur, la URL suivante devrait fonctionner! http://localhost:8080/cgi-bin/mapserv?map=/home/vagrant/osmbase/osmbase.map&LAYERS=default&template=openlayers Une fois le QA terminé, on a qu'a détruire la VM et recommencer le processus à nouveau pour un autre besoin.  Très simple, j'aime vraiment :-)

GEOTRANSFORM et Mauve Nanane …

En début de semaine, j'ai pris connaissance des travaux de mon collègue @AlanBoudreault sur une nouvelle fonctionnalité vraiment intéressante qui sera ajoutée dans la version Mapserver 6.4.  Le RFC-89  ajoutera de nouvelles fonctions de simplification, qui seront effectuées directement par le moteur cartographique Mapserver sans intermédiaire.

J'en ai profité en même temps pour faire une critique cinglante (à l'interne mais c'était humoristique quand même  :-) ) sur l'horrible Mauve nanane du site Web officiel de mapserver.org. Je sais, tout est question de goût, reste que je pense qu'il y trop de mauve dans la mise en page et qu'on devrait faire disparaître tous ces en-têtes mauves qui me font toujours sursauter un peu.

Ce qui m'a valu un retour tout aussi cinglant de la part de bon ami @dmorissette, qui m'a proposé un nouveau titre pour mon blog! Pour ma défense, c'est un paramètre par défaut de mon thème WordPress, mais promis je vais chercher à solutionner ladite chose.

Cartographie d’un réseau routier avec MapServer: savoir gérer l’ordre d’affichage

Lorsqu’on veut cartographier un réseau routier, l’ordre d’affichage des routes est important pour que les voies les plus importantes ne soient pas coupées par des voies secondaires, par exemple.

Image 1 - résultat désiré

Image 2 - résultat brut

L'ordre d'affichage dépend de plusieurs facteurs.  Cet article explique le comportement de MapServer face à l'ordre d'affichage des entités géographiques afin de vous permettre d'obtenir un résultat "propre" dans l'affichage de votre réseau routier.  Il est important de noter que certaines des règles qui suivent ne s'appliquent qu'aux LAYERs de type LINE.

1) Premier lu - Premier dessiné

Le premier élément à considérer est, qu'à l'intérieur d'un même layer, les éléments sont dessinés selon l'ordre de lecture de la donnée indépendamment de la CLASS à laquelle ils appartiennent. En d'autres mots, le premier segment du réseau routier lu sera le premier dessiné. Il est donc nécessaire de classer la source. Par exemple, avec une BD Postgresql/PostGIS, on peut classer les données selon un z-index (z_order dans Open Street Map) et selon la longueur du segment :

DATA "geometry from (select osm_id, geometry, name, type
      from osm_roads
      where type in ('secondary', 'tertiary', 'residential')
      order by z_order asc, st_length(geometry) asc)
      as foo using unique osm_id using srid=900913"

Si vous utilisez un shapefile, l'utilitaire sortshp pourrait être très utile. 

NOTE: Cette règle s'applique à tous les types de layers.

2) Nombre de style dans la classe

Le nombre de STYLE dans une CLASS influence l'ordre d'affichage. Lorsqu'à l'intérieur d'un LAYER, des CLASS comprennent plus qu'un STYLE, le premier STYLE de chaque CLASS est dessiné avant de procéder au 2e STYLE des CLASS et ainsi de suite.

3) Outline en premier

Lorsque les premiers STYLE des CLASS comportent un OUTLINEWIDTH, les outlines de toutes les CLASS sont dessinés avant l'intérieur.  Cet aspet spécifique n'est pas le fruit du hasard et a été implanté dans la version 5.4 et documenté dans la RFC-49.

Exemple: mapfile incorrect

CLASS  # routes secondaires
  EXPRESSION /secondary/
  STYLE
    WIDTH 12
    COLOR 255 0 0 # rouge
    OUTLINEWIDTH 2
    OUTLINECOLOR 153 111 57 # brun
  END
  STYLE
    WIDTH 11
    COLOR 223 197 124 # orange
  END
END

CLASS # routes tertaires
  EXPRESSION /tertiary/
  STYLE
    WIDTH 11
    OUTLINEWIDTH 1
    OUTLINECOLOR 193 188 157 # gris
    COLOR 255 253 139 # jaune
  END
END

CLASS # routes résidentielles
  STYLE
    WIDTH 11
    OUTLINEWIDTH 1
    OUTLINECOLOR 103 181 157  # vert
  END
  STYLE
    WIDTH 11
    COLOR  238 225 226  # rose
  END
END

En considérant que la source a été triée dans cet ordre: résidentielles, tertiaires, secondaires, l'ordre d'affichage se déroule comme suit:

  1. Outline (vert) des routes résidentielles
  2. Outline (gris) des routes tertiaires
  3. Outline (brun) des routes secondaires
  4. Premier style (uniquement un outline) des routes résidentielles
  5. L'unique style (jaune) des routes tertiaires
  6. Premier style (rouge) des routes secondaires
  7. Deuxième style (rose) des routes résidentielles
  8. Deuxième style (orange) des routes secondaires
 

Exemple: mapfile correct

CLASS  # routes secondaires
  EXPRESSION /secondary/
  STYLE
    WIDTH 12
    COLOR 255 0 0 # rouge
    OUTLINEWIDTH 2
    OUTLINECOLOR 153 111 57 # brun
  END
  STYLE
    WIDTH 11
    COLOR 223 197 124 # orange
  END
END

CLASS # routes tertaires
  EXPRESSION /tertiary/
  STYLE
    WIDTH 11
    OUTLINEWIDTH 1
    OUTLINECOLOR 193 188 157 # gris
  END
  STYLE
    WIDTH 11
    COLOR 255 253 139 # jaune
  END
END

CLASS # routes résidentielles
  STYLE
    WIDTH 11
    OUTLINEWIDTH 1
    OUTLINECOLOR 103 181 157  # vert
  END
  STYLE
    WIDTH 11
    COLOR  238 225 226  # rose
  END
END

Produire un effet de “couleur dégradée” avec Mapserver

Nous avons  travaillé sur un projet de Web mapping dernièrement dans lequel on voulait produire un effet de "couleur dégradée" (fade to white) entre la terre ferme et l'océan. J'ai trouvé dernièrement une superbe carte dans l'"Atlas of Design" (que je recommande fortement pour les maniaques comme moi) de la NACIS (North American Cartographic Information Society).

À la page 64 on trouvera le genre d'effet de "couleur dégradée" en question:

On a l'habitude de voir ce genre d'effet dans un atlas et il s'agit la plupart du temps d'une retouche "photoshop". Il est par contre possible de reproduire l'effet avec une suite de buffers "concentrique" ou "excentrique" autour des entités d'une classe de provinces ou de continents par exemple pour "dégrader" la couleur de l'eau. Je me suis inspiré de d'une recette sur le forum SIG pour le faire dans PostGIS.

La méthode pourrait certe être plus optimale et performante si elle était gérée nativement dans Mapserver (nous acceptons volontier le financement pour le faire), par contre le résultat est superbe.

Donc première étape: chargement... shp2pgsql -s 3163 -c -g the_geom -I -W "latin1" QUARTIER_POLYGON.shp nc_noumea | psql -d nc -h 192.168.6.20 -p 5432 -U nc

Pour créer les anneaux "excentriques" j'ai utilisé ces suites de requêtes SQL. On devra jouer avec la largeur du buffer si on doit afficher le "fade effect" à plusieurs échelles et créer plus d'anneaux. Dans l'exemple suivant (de 0 a 35 mètres) on comprendra que l'effet ne sera visible qu'à très petite échelle. Si on veut appliquer la recette à plus grande échelle, il suffira simplement d'ajouter des anneaux supplémentaires ET à des intervalles plus larges.

NOTE: Merci à Vincent Picavet de la firme Oslandia pour le conseil de l'incroyable commande generate_series(), que je connaissais pas! Vraiment bien cette commande. Cette instruction SQL très compacte, va même créer la table pour moi! drop table nc_noumea_step; create table nc_noumea_step as select 0 as gid,0 as step,the_geom from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 1 as gid,5 as step,ST_Difference(ST_Buffer(st_multi,5),ST_Buffer(the_geom,0)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 2 as gid,10 as step,ST_Difference(ST_Buffer(st_multi,10),ST_Buffer(the_geom,5)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 3 as gid,15 as step,ST_Difference(ST_Buffer(st_multi,15),ST_Buffer(the_geom,10)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 4 as gid,20 as step,ST_Difference(ST_Buffer(st_multi,20),ST_Buffer(the_geom,15)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 5 as gid,25 as step,ST_Difference(ST_Buffer(st_multi,25),ST_Buffer(the_geom,20)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 6 as gid,30 as step,ST_Difference(ST_Buffer(st_multi,30),ST_Buffer(the_geom,25)) from nc_noumea; insert into nc_noumea_step (gid,step,the_geom) select 7 as gid,35 as step,ST_Difference(ST_Buffer(st_multi,35),ST_Buffer(the_geom,30)) from nc_noumea;
SELECT i as step, ST_Difference(ST_Buffer(st_multi,i),ST_Buffer(st_multi,i-5))
INTO nc_noumea_step
FROM nc_noumea n, generate_series(5,35,5) AS i;

On pourra utiliser un buffer négatif pour produire le même effet mais en dégradant la couleur vers l'intérieur (anneaux concentriques):

...
insert into communes_50_step (gid,cod_commun,step,the_geom) select gid,cod_commun,200 as step,ST_Difference(ST_Buffer(the_geom,-100),ST_Buffer(the_geom,-200)) as the_geom from communes_50;
insert into communes_50_step (gid,cod_commun,step,the_geom) select gid,cod_commun,300 as step,ST_Difference(ST_Buffer(the_geom,-200),ST_Buffer(the_geom,-300)) as the_geom from communes_50;
...

J’ai fait plusieurs essais dont des buffers successifs qui embarquent les uns sur les autres, mais l'effet est moins propre et le résultat moins prévisible. Le meilleur résultat et le plus flexible est vraiment une suite d'anneaux (buffers polygone) successifs qui n'empiètent pas les uns sur les autres. De cette façon on peut gérer la transparence avec couleur de fond pour chaque classe ET/OU des couleurs uniques ET/OU une orthophoto en fond de carte, tout est possible.

Enfin, dans le mapfile j'ai cartographié dans plusieurs CLASS chacun des anneaux désirés avec une transparence spécifique en dégradé :

LAYER
    TYPE POLYGON
    STATUS ON
    GROUP "zone"
    NAME "nc_contour_2_16"
    PROJECTION
        "init=epsg:3163"
    END
    MINSCALEDENOM 4096
    MAXSCALEDENOM 8192
    DATA "DATA_VDN/nc_noumea_step.shp"
    CLASSITEM "step"
    CLASS
        EXPRESSION "0"
        STYLE
            COLOR 255 255 255
        END
    END
    CLASS
        EXPRESSION "5"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 80
        END
    END
    CLASS
        EXPRESSION "10"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 60
        END
    END
    CLASS
        EXPRESSION "15"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 50
        END
    END
    CLASS
        EXPRESSION "20"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 40
        END
    END
    CLASS
        EXPRESSION "25"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 30
        END
    END
    CLASS
        EXPRESSION "30"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 20
        END
    END
    CLASS
        EXPRESSION "35"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 10
        END
    END
END
LAYER
    TYPE POLYGON
    STATUS ON
    GROUP "zone"
    NAME "nc_contour_1_17"
    PROJECTION
        "init=epsg:3163"
    END
    MINSCALEDENOM 2048
    MAXSCALEDENOM 4096
    DATA "DATA_VDN/nc_noumea_step.shp"
    CLASSITEM "step"
    CLASS
        EXPRESSION "0"
        STYLE
            COLOR 255 255 255
            OUTLINECOLOR "#3fc1b7"
            WIDTH 0.4
        END
    END
    CLASS
        EXPRESSION "5"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 50
        END
    END
    CLASS
        EXPRESSION "10"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 30
        END
    END
    CLASS
        EXPRESSION "15"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 10
        END
    END
END
LAYER
    TYPE POLYGON
    STATUS ON
    GROUP "zone"
    NAME "nc_contour_1_18"
    PROJECTION
        "init=epsg:3163"
    END
    MINSCALEDENOM 1500
    MAXSCALEDENOM 2048
    DATA "DATA_VDN/nc_noumea_step.shp"
    CLASSITEM "step"
    CLASS
        EXPRESSION "0"
        STYLE
            COLOR 255 255 255
            OUTLINECOLOR "#3fc1b7"
            WIDTH 0.4
        END
    END
    CLASS
        EXPRESSION "5"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 50
        END
    END
    CLASS
        EXPRESSION "10"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 20
        END
    END
END
LAYER
    TYPE POLYGON
    STATUS ON
    GROUP "zone"
    NAME "nc_contour_1_18"
    PROJECTION
        "init=epsg:3163"
    END
    MINSCALEDENOM 0
    MAXSCALEDENOM 1500
    DATA "DATA_VDN/nc_noumea_step.shp"
    CLASSITEM "step"
    CLASS
        EXPRESSION "0"
        STYLE
            COLOR 255 255 255
            OUTLINECOLOR "#3fc1b7"
            WIDTH 0.4
        END
    END
    CLASS
        EXPRESSION "5"
        STYLE
            COLOR "#3fc1b7"
            OPACITY 50
        END
    END
END

Transférer une symbologie “ArcGIS font Symbol” à Mapserver

Voici donc une procédure toute simple pour transformer une symbologie complexe d'une ligne basée sur l'utilisation de font dans ArcGIS vers un mapfile pour Mapserver. Partant de votre panorama de "Symbol Property Editor" dans ArcGIS:   on trouvera un symbole utilisant deux symboles de font. Cliquer sur "Symbol...", pour avoir accès à plus d'options. Dans ce panorama, on pourra récupérer le "Unicode" du symbole dans le fichier de font. Dans cet exemple on pourra donc utiliser le code 99 de la font "MapGenFont" Ce code est l'identifiant unique permettant d'identifier le symbole dans cette font. Toujours dans cet exemple, l'autre caractère utilisé dans cette symbologie complexe est dans la font "ESRI Default Marker" unicode 181. Pour utiliser cette font avec Mapserver on devra copier les fichiers de font dans l'arborescence de fichiers de configuration Mapserver. On trouvera facilement le fichier en naviguant dans le répertoire de fonts Windows "C:/Windows/Fonts". Ensuite on va ajouter la font dans le fichier fontset.
  #FONTSET File
mgfont                ./fonts/MGfont.ttf
esri_default_marker   ./fonts/esri_11.ttf
...
Enfin on va créer le symbole de cette façon:
 #symbolset File
  SYMBOL
    NAME       "rock-1"
    TYPE       TRUETYPE
    FONT       "mgfont"
    CHARACTER  "c"
    GAP        3
  END
  SYMBOL
    NAME       "rock-2"
    TYPE       TRUETYPE
    FONT       "esri_default_marker"
    CHARACTER  "µ"
  END
  #Mapfile
  ...
    TYPE                    LINE
    CLASS
      NAME                  "Sand"
      STYLE
        SYMBOL              "rock-1"
        COLOR               78 78 78
        SIZE                7
      END
      STYLE
        SYMBOL              "rock-2"
        COLOR               78 78 78
        SIZE                7
        OFFSET              3 3
      END
    END
   ...

Investissements du Québec en santé

english version follow...
Nous avons réalisé dernièrement une nouvelle application de visualisation de données sur les "Investissements du Québec en santé".  Nous avons trouvé l'application vraiment "cool" alors on a décidé de la diffuser durant la présente campagne électorale 2012 parce qu'il est intéressant de pouvoir visualiser la taille de ces investissements.
Pour cette application, nous avons utilisé l'information publique du "Ministère de la Santé et des Services sociaux" diffusée via le site de données ouvertes du gouvernement du Québec, et des outils Web de visualisation de données pour mettre en relief le poids des investissements en santé versus la population et le budget total de la province de Québec.
Pour réaliser cette application, nous avons utilisé la librairie d3.js, Leaflet, puis Mapserver pour tuiler ( Mapcache ) et diffuser notre carte.
------------------------------
We recently launched our new data vizualisation application "Investissement du Québec en santé".  We find it cool so we decided to publish it.  It's interesting to visualize the size of these investments in this Quebec election campaign.
For this Web application, we used public data from the Government of Quebec Opendata Web site. We used data from "Ministery of Health and Social Services" and data visualization tools to highlight the amount of investments in health versus population of Quebec and the total budget of the province of Quebec.
To build this application, we used d3.jsLeaflet, and we used Mapserver to tiled (Mapcache) and served our map.

MS4W et Oracle Spatial

Même si en principe, l'installation et la configuration pour connecter un layer Oracle Spatial d'un mapfile est vraiment simple,  j'ai passé quelques jours dernièrement à chercher une erreur de configuration un peu stupide!  J'ai cru bon en faire un résumé en lien avec la documentation Mapserver sur le sujet.

À mon avis, la façon la plus simple d'utiliser MS4W avec Oracle Spatial sur votre Windows, est d’utiliser le Instant Client basic light.  Pas besoin de polluer votre setup avec la grosse installation du client complet.  La procédure qui suit montre comment créer à partir de zéro  1) une table avec un champ SDO_GEOMETRY sur Oracle, 2) l’enregistrer dans le catalogue Oracle, 3) installer le client Oracle, 4) créer le mapfile et 5) des astuces pour tester votre config.

Chargement d'un jeux de données test

Il sera très utile d'avoir un jeux de données testes sur votre serveur Oracle.  J'utilise régulièrement ce script pour charger des données rapidement et sans effort.

Installer le InstantClient Oracle

0) Le package MS4W est un build 32bit.  Il est très important de télécharger le InstantClient-basiclight 32bits sur le site d’Oracle même si votre serveur Windows est de type 64bit.   Pour installer le client Oracle, simplement décompresser le fichier et placer dans le répertoire de son choix.  Pour cet exemple utilisons:

 c:instantclient_11_2

1) Il est IMPÉRATIF de placer ce répertoire dans la Variable d’Environnement  PATH du système.  C’est la SEULE variable d’environnement que vous devez configurer.   Les variables ORACLE_HOME, ORACLE_BASE, TNS_ADMIN, ORACLE_SID ou LD_LIBRARY_PATH ne sont pas requises pour MS4W.

2)  On doit déplacer le fichier libmap.dll dans le répertoire cgi-bin de Apache et le fichier ogr_OCI.dll dans le répertoire de gdalplusgins.  NOTE: Il serait préférable d’arrêter le service MS4W Apache sur votre serveur s’il est déjà en route avant de faire la copie des fichiers:

c:ms4wApachecgi-binignored-libmaporacle11glibmap.dll --> c:ms4wApachecgi-bin
c:ms4wgdalpluginsignoredoracle-11gogr_OCI.dll --> c:ms4wgdalplugins
Ne reste plus qu’à redémarrer Apache via un Prompt DOS ou dans le gestionnaire de services Windows: c:ms4wapache-restart
IMPORTANT:

Je suggère ici de vous assurer que le PATH contient bien votre répertoire du client Oracle.  On peut regarder dans un Prompt DOS avec la commande set mais vous devez aussi vérifier qu’elle sera aussi disponible dans Apache.  Vous pouvez valider avec la commande phpinfo.php.  On doit trouver à la rubrique “Environment” la valeur de la variable PATH qui doit inclure le répertoire du client Oracle.  Il se peut très bien que la valeur de PATH du système Windows ne soit pas la même dans Apache et dans DOS.

ogrinfo

Avant de faire des essais avec Mapserver, il est fortement recommandé de tester la connexion Oracle avec ogrinfo parce que moins de composantes sont requises.  J'utilise une connexion sans TNSNAMES.ORA parce que c'est plus propre et plus simple.  Ouvrir un Prompt Dos et faire les commandes suivantes: 

C:ms4w>setenv
C:ms4w>set PATH=C:instantclient_11_2;%PATH%
C:ms4w>ogrinfo OCI:user/pw@my_serveur_name_or_ip:port/my_sid_db_name
-----
INFO: Open of `OCI:user/pw@my_serveur_name_or_ip/my_sid_db_name'
using driver `OCI' successful.
1: ZZ_EOLIENNES_P
2: ZZ_VILLE_S 
IMPORTANT:

En cas de problème, utiliser cette astuce pour avoir un log complet des problèmes potentiels.

C:ms4w>set CPL_DEBUG=on
C:ms4w>ogrinfo OCI:user/pw@my_server_name_or_ip:port/my_sid_db_name

mapfile

J'ai ici mon layer très simple pour me connecter à Oracle.
   LAYER
     NAME "zz_ville_s"
     TYPE POLYGON
     CONNECTIONTYPE oraclespatial
     CONNECTION "user/pw@my_server_name_or_ip:port/my_sid_db_name"
     DATA "GEOM FROM (SELECT geom FROM ZZ_VILLE_S)"
     PROCESSING "CLOSE_CONNECTION=DEFER"
     CLASS
       NAME "Ville"
       STYLE
         COLOR 25 200 20
         OUTLINECOLOR 80 80 80
       END
     END
   END

shp2img

Par la suite on peut produire un mapfile très très simple pour tester un layer Oracle.   Encore une fois on peut essayer avec l’utilitaire shp2img qui a l’avantage de ne pas passer par la composante Apache.  Ça peut être fort utile pour débuger un service qui ne veut pas démarrer.

C:ms4w>setenv
C:ms4w>set PATH=C:instantclient_11_2;%PATH%
C:ms4w>shp2img -m C:/view-oracle2.map -i png -o C:/temp/test-oracle.png -map_debug 5 -e -67.7 48.7 -67.5 48.8 -l ZZ_VILLE_S
----------
msDrawMap(): rendering using outputformat named png (AGG/PNG).
msDrawMap(): WMS/WFS set-up and query, 0.000s
msDrawMap(): Layer 0 (ZZ_EOLIENNES_P), 0.674s
msDrawMap(): Drawing Label Cache, 0.000s
msDrawMap() total time: 0.677s
msSaveImage(C:/temp/test-oracle.png) total time: 0.079s
msFreeMap(): freeing map at 020BC200.

mapserv via Apache

Sous Windows avec MS4W, il n’y a pas vraiment de configuration à faire.  Le fait d’ajouter dans la Variable d’Environnement PATH, le répertoire du client Oracle ferra en sorte que  celle-ci se retrouvera dans la Variable d’Environnement PATH de Apache.

http://127.0.0.1/cgi-bin/mapserv.exe?map=C:/view-oracle2.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=ZZ_VILLE_S&STYLES=&SRS=EPSG:4326&BBOX=-67.7,48.7,-67.5,48.8&WIDTH=400&HEIGHT=300&FORMAT=image/png

mapserv via commande DOS

Autre astuce, on peut aussi utiliser la commande mapserv pour tester la URL avec l'option QUERY_STRING.

C:ms4w>setenv
C:ms4w>set PATH=C:instantclient_11_2;%PATH%
C:ms4w>mapserv “QUERY_STRING=map=C:/view-oracle2.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=ZZ_VILLE_S&STYLES=&SRS=EPSG:4326&BBOX=-67.7,48.7,-67.5,48.8&WIDTH=400&HEIGHT=300&FORMAT=image/png”
Simon Mercier (smercier at mapgears.com)

Oracle NSL_LANG variable

Vous utilisez Apache comme moteur Web avec Mapserver ou GeoServer et vous voulez avez des problèmes d'accents dans votre application. 1) Identifier votre encodage de BD; SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET' or PARAMETER = 'NLS_LANGUAGE'; ------------------------------------------------- PARAMETER VALUE NLS_LANGUAGE CANADIAN FRENCH NLS_CHARACTERSET WE8ISO8859P1 2) Identifier votre code de langue http://download.oracle.com/docs/cd/A84870_01/doc/nt.816/a73010/appc.htm Dans mon cas il sera: "CANADIAN FRENCH_CANADA.WE8ISO8859P1" 3) On peut spécifier ce code dans une variable d'environnement sur le serveur export NLS_LANG="CANADIAN FRENCH_CANADA.WE8ISO8859P1" ou l'ajouter dans le profile de tous les user sudo vim /etc/profile 4) Spécifier votre encodage de langue Oracle correctement dans Apache On doit placer une variable d'environnement dans le fichier de configuration d'Apache. Attention, cette conf NE DOIT PAS être placée dans un balise <VirtualHost> </VirtualHost> ... sudo vim /etc/apache2/httpd.conf ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory /usr/lib/cgi-bin/ >    AllowOverride None    Options ExecCGI -MultiViews +SymLinksIfOwnerMatch    Order allow,deny    Allow from all </Directory> #spécifier le client Oracle et la langue <Location "/cgi-bin/">    SetEnv ORACLE_HOME "/opt/oracle/clients/10.2.0.1"    SetEnv NLS_LANG "CANADIAN FRENCH_CANADA.WE8ISO8859P1" </Location> #Rep temp pour mapserver Alias /ms_tmp/ "/var/www/ms_tmp/" <Directory "/var/www/ms_tmp/">    Options Indexes MultiViews FollowSymLinks    AllowOverride None    Order allow,deny    Allow from all </Directory>

Nouveaux OUTPUTFORMAT de Mapserver 6.0

Une des nouveautés de Mapserver 6.0 est l’ajout de nouveaux formats de sortie liés aux requêtes GetFeature via WFS. Attention par contre, on doit obligatoirement installer GDAL/OGR 1.8. Dans mon cas test sur mon serveur Debian, je devais utiliser une connexion Oracle. J'ai donc compilé GDAL/OGR avec le support Oracle et compilé Mapserver pour lire ce format via GDAL/OGR. J'ai aussi préparé un fichier regroupant les formats de sortie suivant: OUTPUTFORMAT   NAME "SHAPEZIP"   DRIVER "OGR/ESRI Shapefile"   MIMETYPE "application/shapefile"   FORMATOPTION "STORAGE=filesystem"   FORMATOPTION "FORM=zip"   FORMATOPTION "FILENAME=result.zip" END OUTPUTFORMAT   NAME "MIDMIF"   DRIVER "OGR/MapInfo File"   FORMATOPTION "STORAGE=filesystem"   FORMATOPTION "FORM=multipart"   FORMATOPTION "DSCO:FORMAT=MIF"   FORMATOPTION "FILENAME=result.mif" END OUTPUTFORMAT   NAME "MultiMIDMIF"   DRIVER "OGR/MapInfo File"   FORMATOPTION "STORAGE=filesystem"   FORMATOPTION "FORM=multipart"   FORMATOPTION "DSCO:FORMAT=MIF"   FORMATOPTION "FILENAME=result" END OUTPUTFORMAT   NAME "CSV"   DRIVER "OGR/CSV"   MIMETYPE "text/csv"   FORMATOPTION "LCO:GEOMETRY=AS_WKT"   FORMATOPTION "STORAGE=filesystem"   FORMATOPTION "FORM=simple"   FORMATOPTION "FILENAME=result.csv" END OUTPUTFORMAT   NAME "CSVSTREAM"   DRIVER "OGR/CSV"   MIMETYPE "text/csv; streamed"   FORMATOPTION "LCO:GEOMETRY=AS_WKT"   FORMATOPTION "STORAGE=stream"   FORMATOPTION "FORM=simple"   FORMATOPTION "FILENAME=result.csv" #-- If “stream” then the datasource will be created with a name “/vsistdout” as an attempt to write directly to stdout. Only a few OGR drivers will work properly in this mode (ie. CSV, perhaps kml, gml) END OUTPUTFORMAT   NAME "OGRGML"   DRIVER "OGR/GML"   MIMETYPE "text/xml; subtype=gml/2.1.2; driver=ogr"   FORMATOPTION "STORAGE=memory"   FORMATOPTION "FORM=multipart"   FORMATOPTION "FILENAME=result.gml" END OUTPUTFORMAT   NAME kml   DRIVER "KML"   MIMETYPE "application/vnd.google-earth.kml+xml"   IMAGEMODE RGB   EXTENSION "kml"   FORMATOPTION 'ATTACHMENT=result.kml'   FORMATOPTION "maxfeaturestodraw=100" END OUTPUTFORMAT   NAME kmz   DRIVER "KMZ"   MIMETYPE "application/vnd.google-earth.kmz"   IMAGEMODE RGB   EXTENSION "kmz"   FORMATOPTION 'ATTACHMENT=result.kmz' END OUTPUTFORMAT   NAME "geojson"   DRIVER "TEMPLATE"   MIMETYPE "application/json; subtype=geojson"   FORMATOPTION "FILE=../template/geojson.txml" END OUTPUTFORMAT   NAME "customxml"   DRIVER "TEMPLATE"   FORMATOPTION "FILE=mon_template.xml" END J'ai testé avec ce Mapfile WFS plusieurs de ces formats. Pour le type “SHAPEZIP” par exemple, on fait simplement cette requête URL: http://sigtest.gouc.qc/cgi-bin/extract?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&typename=SMDTS_TERR&OUTPUTFORMAT=SHAPEZIP NOTE 1: Je n'ai pas ajouter de clause FILTER pour mon test mais c'est possible. Voir ici pour plus d'explications NOTE 2: J'ai n'ai pas fait d'essais avec le format de sortie TEMPLATE qui nous permet de personnaliser un format de sortie texte comme geojson par exemple. Cette option est très puissante et mérite d'être mieux connue. Imaginer utiliser Mapserver pour générer du code javascript pour jQuery par exemple...! NOTE 3: Par comparaison, avec Geoserver qui support déjà ce type de format de sortie (SHAPEFILES) depuis plus longtemps: http://sigtest.gouv.qc:8180/geoserver/wfs?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&typename=SMDTS_TERR&OUTPUTFORMAT=SHAPE-ZIP

Database-driven mapfile

Avez-vous déjà essayé de construire une mapfile qui serait dynamiquement contrôlé par la base de données? À l'occasion, cette astuce peut aider à produire des services Web cartographiques basés sur des données dynamiques d'un système d'envergure. Voici une description de table provenant de Postgesql: Table "public.om_users" Column      | Type                   | Modifiers ------------+------------------------+------------------------------------- om_id       | integer                | not null longitude   | numeric(12,9)          | latitude    | numeric(12,9)          | color       | character varying(11)  | default '255 0 0'::character varying label       | character varying(100) | the_geom    | geometry               | feature     | character varying(32)  | default 'circle'::character varying size        | integer                | default 5 outline     | character varying(11)  | default '0 0 0'::character varying Indexes: "om_users_pkey" PRIMARY KEY, btree (om_id) Check constraints: "enforce_dims_the_geom" CHECK (st_ndims(the_geom) = 2) "enforce_geotype_the_geom" CHECK (geometrytype(the_geom) = 'POINT'::text OR the_geom IS NULL) "enforce_srid_the_geom" CHECK (st_srid(the_geom) = 4326) On place simplement les champs de données au bon endroit dans le mapfile. Pour chacun des enregistrements, mapserver prendra les données de la table pour cartographier l'entité. LAYER   NAME "UsersLayers"   INCLUDE "ec/ec_connec_db_pg.map"   DATA "the_geom from om_users using srid=4326"   TYPE POINT   METADATA     "wms_name" "UsersLayer"     "wms_title" "UsersLayer"     "wms_server_version" "1.1.1"     "wms_srs" "EPSG:4326 EPSG:900913"     "gml_featureid" "oid"     "gml_include_items" "all"   END   PROJECTION     "init=epsg:4326"   END   CLASSITEM "om_id"   CLASS   NAME "Status"   STYLE     SYMBOL [feature]       COLOR [color]       OUTLINECOLOR [outline]       SIZE [size]     END   END END