OSM, QGis, PostGIS et SFCGAL en pratique
←
→
Transcription du contenu de la page
Si votre navigateur ne rend pas la page correctement, lisez s'il vous plaît le contenu de la page ci-dessous
OSM, QGis, PostGIS et SFCGAL
en pratique
Comment, avec quatre outil Open Source, ré- Création de la base de format est facilement interpréta-
soudre une question d’aménagement appar- ble : chaque nombre correspond
données à l’altitude d’une des cases de
emment anodine… mais pas autant que ça ! la grille dont les caractéristiques
La question que nous allons réso- (taille du maillage et position
udre consiste à évaluer la pente d’une des cases d’extrémité) sont
moyenne, kilomètre par kilomètre, données dans l’en-tête :
du tracé de l’extension de la ligne
ncols 1000
L
’offre Open Source en TGV est-européenne, longue
nrows 1000
géomatique, qu’elle concerne d’une trentaine de kilomètres, et xllcorner 974962.500000000000
les données (Open data ou réalisée partiellement en tunnel yllcorner 6750037.500000000000
Open Street Map) et les logiciels sous le massif vosgien. Nous cellsize 75.000000000000
(PostGIS, QGIS…), a atteint un considérerons les parties sous NODATA_value -99999
niveau de maturité qui permet tunnel comme étant horizontales
désormais de résoudre des prob- (ce qui constitue une hypothèse Nous savons ainsi que le fichier
lèmes assez délicats en quelques à peu près raisonnable, du moins élémentaire (ici, celui qui nous
manipulations, pourvu que l’on en première approximation). intéresse, baptisé BDALTIr_2-0_
maîtrise correctement chacun MNT_EXT_0975_6900_
des outils (ce qui n’est pas La première étape consiste à LAMB93_IGN69_20110929.
évident). Dans ce « mini-tutoriel », constituer une base de données asc) est composé d’une grille
nous allons détailler comment (nommons la, par exemple de mille points par mille points,
résoudre une problématique « LGV ») dans laquelle nous que les coordonnés précisées
simple, calculer la pente moyenne allons stocker nos deux couches sont celles du point sud-ouest
d’une voie ferrée, kilomètre par initiales : la BD Alti® 75 m et (ll : lower left) et que la maille
kilomètre, en n’utilisant que des le tracé de la ligne issue des mesure, on le savait déjà, soix-
ressources libres, à savoir la données OSM. ante-quinze mètres. Enfin la
BD Alti® de l’IGN au pas de 75 m valeur prétexte, -99 999 (utilisée
(disponible en téléchargement La BD Alti® 75 m, comme pour les points hors territoire),
sur le site de l’Institut), le tracé précédemment signalé, est libre- n’a pas d’importance ici puisque
issu de la base Open Street ment téléchargeable sur le site de l’intégralité de la dalle est située
Map, et les logiciels QGis 2.2 l’IGN dans sa partie profession- en France.
(dernière version publiée) ainsi nelle. Elle est fournie sous la forme
que PostGIS 2.1 accompagné de dalles .ASC compressées, La deuxième étape consiste à
de l’extension SFCGAL1. chacune d’environ 1 Mio. Le récupérer les données Open
1. SFCGAL est une bibliothèque d’interface entre PostGIS et la bibliothèque de « géométrie computationnelle » CGAL développée en grande
partie par l’INRIA. Cette bibliothèque enrichit PostGIS de nouvelles fonctions inédites, particulièrement dans le domaine de la 3D, mais pas
seulement.
30 Géomatique Expert|N° 97|Mars-Avril 2014Street Map. Théoriquement, Le processus d’importation, que l’on souhaite extraire (points,
ceci est directement faisable à depuis l’intégration de la fonc- lignes, polygones), et de sélec-
l’intérieur de QGis en utilisant, tionnalité OSM dans le cœur de tionner les attributs (tags) que
dans le menu Vecteur, l’entrée QGis, est assez complexe. Il faut l’on souhaite conserver (figure 3).
OpenStreetMap Ö Télécharger utiliser d’abord la fonction Vecteur Dans le cas qui nous intéresse, ce
des données. Malheureusement, Ö OpenStreetMap Ö Importer la sont les polylignes (tracés routiers
la plupart du temps, cette topologie depuis un XML pour et ferrés) que nous allons extraire,
option ne fonctionne pas (on créer, à partir des données OSM en sélectionnant les attributs
obtient un message d’erreur). brutes (XML), un fichier compat- name, railway et tunnel. Le
La façon la plus efficace, et la ible avec la base de données résultat est un maillage assez
plus fiable, de télécharger ces SpatiaLite qu’utilise QGis pour dense de polylignes (car même
données reste donc d’utiliser ses besoins propres. L’opération les tronçons sans attributs sont
la partie cartographique du site prend un certain temps, variable extraits) visible figure 4.
openstreetmap.fr, qui renvoie elle- selon l’importance des données
même vers openstreetmap.org. et la puissance de la machine qui
Là, sélectionner l’emprise d’intérêt exécute le script. Figure 3 :
Après la
sur le fond cartographique (ici, transformation
grossièrement, un rectangle Après quelques minutes, on des données
XML en tables
englobant les villes de Metz, obtient un fichier .db en sortie qu’il SpatiaLite, la
Nancy et Strasbourg) puis utiliser va falloir maintenant exploiter pour troisième fonc-
tion Exporter
le lien sur l’ « API passerelle », qui obtenir des couches affichables. la topologie
permet de rapatrier des quantités Pour cela, la troisième fonction en SpatiaLite
permet de créer
de données plus importantes que Exporter la topologie en SpatiaLite une couche
le site standard. permet de préciser le type d’objet géométrique et
de sélectionner
les champs à
conserver.
Figure 1 : Les fonctions
d’import des données
OSM sont toutes
situées sous l’entrée
OpenStreetMap du
menu Vecteur.
Figure 4 : Après importation, on se retrouve
Figure 2 : QGis propose avec l’ensemble des données filaires.
une fonction intégrée La consultation de la table des attributs
de téléchargement permet de trouver la valeur des tags que
des données OSM, l’on souhaite extraire.
mais qui ne fonctionne
malheureusement pas.
Il nous faut maintenant extraire les
données utiles dans ce réseau
extrêmement dense. Comme
on peut observer dans la table
attributaire affichée figure 4, il
semble que la ligne TGV soit,
dans le champ railway, affublée
de la valeur « construction ». Nous
Géomatique Expert|N° 97|Mars-Avril 2014 31allons donc générer une nouvelle À ce stade, il est expédient de du gestionnaire de bases de
couche en sélectionnant par constituer un base de données données QGis, il faut auparavant
attribut les tronçons portant le tag PostGIS et d’y injecter le tracé avoir défini les paramètres de
railway:construction. Le résul- et le MNT (grâce aux fonctions connexion en cliquant sur l’icône
tat correspond bien au futur tracé raster). On ne peut apparem- de chargement d’un couche
de la ligne nouvelle (figure 5). ment pas créer directement PostGIS, ce qui ouvre le dialogue
approprié.
Une fois la connexion créée et
vérifiée, on peut donc retourner
dans le gestionnaire de base
de données, sélectionner la
nouvelle base et injecter directe-
ment le tracé grâce à la fonction
« importer une couche ou un
fichier ». En revanche, le raster
ne peut pas être stocké dans
PostGIS depuis QGis, il faut donc
b Figure 6 : Après sélection par attribut
puis par rectangle englobant, on obtient
l’extrait du tracé de la ligne LGV dans la
zone d’intérêt.
a Figure 5 : Sélection par attribut (icône dans le menu
de la boîte d’affichage des données attributaires) de la valeur
construction du champ railway.
Nous créons donc une nouvelle
couche sous forme de fichier
Shapefile en utilisant l’option
Sauvegarder la sélection sous.
Nous la rechargeons, puis nous
utilisons l’outil de sélection rectan-
gulaire pour limiter le tracé à la
seule portion où nous disposons
des données d’altimétrie, puis
nous sauvegardons de nouveau la
sélection sous un nouveau fichier une nouvelle base de données utiliser l’utilitaire raster2pgsql,
Shapefile (il est également possible PostGIS à l’intérieur de QGis, fourni avec PostGIS. Par exemple,
de rassembler les deux sélections même en utilisant le gestionnaire sous Unix/Linux/OS X :
en une seule pour aller plus vite). de bases de données. Il faut donc
le faire, soit au travers de l’utilitaire
Quand on examine le tracé de d’administration PGAdmin III, raster2pgsql -s 2154 -b 1 -c
près, on s’aperçoit qu’il est en fait soit manuellement en ligne de -f geom -I -C BDALTIr_2-0_
MNT_EXT_0975_6900_LAMB93_
constitué des deux voies dessi- commande en tapant createdb IGN69_20110929.asc mnt | psql
nées l’une à côté de l’autre. Ceci , puis en -d LGV
va nous poser un souci, car il va injectant les différentes bases
falloir gérer une géométrie de type nécessaires au bon fonctionne-
multi- alors que nous souhaiteri- ment de la cartouche spatiale Il est conseillé d’utiliser un alias
ons obtenir un tracé « simple ». (ne pas oublier, dans ce cas, ni dans la commande raster2pg-
En outre, la couche comprend le module rtpostgis de gestion sql (le « mnt » juste avant le |)
également deux raccordements des raster, ni le module sfcgal.) de façon à éviter de créer une
d’accès que nous ne souhaitons Ici, nous choisirons LGV comme table portant le même nom que
pas prendre en compte. Il va donc nom de base. Pour pouvoir le fichier, ce qui ne serait pas du
falloir les éliminer. accéder à celle-ci à l’intérieur tout commode par la suite.
32 Géomatique Expert|N° 97|Mars-Avril 2014« squelettisation », c’est-à-dire
les axes rigides d’orientation. Le
calcul met en jeu la bibliothèque
CGAL et prend un certain temps
(quelques minutes). Le résultat
se présente sous la forme de
l’axe central du corridor, et de
multiples lignes qui connectent
perpendiculairement cet axe aux
limites du corridor aux endroits
où celui-ci change de direction
(figure 10).
Figure 7 : Exemple de création
d’une connexion PostGIS sur la
base LGV nouvellement créée. CREATE TABLE squelette AS
(SELECT ST_StraightSkeleton
TTraitement
it t dde lla ddonnée
é est réalisable à l’aide des outils (geom) AS geom FROM boudin);
Python fournis en standard avec
de voie QGIS (menu Vecteur ÖOutils de Il faut donc se débarrasser de ces
La donnée issue d’OSM néces- géotraitement), mais il vaut mieux segments perpendiculaires. Pour
site encore quelques pré-traite- la conduire directement dans ce faire, nous allons dessiner un
ments avant d’être utilisable. PostGIS. buffer autour de chaque segment.
Tout d’abord, il faut éliminer les Seul celui qui entoure l’axe central
tronçons partiellement hors-MNT, CREATE TABLE boudin AS (SELECT sera entièrement contenu dans
puis les tronçons de raccorde- ST_Union(ST_Buffer (geom, 200)) le boudin que nous avons créé
ment qui ne nous intéressent pas. AS geom FROM tracé); auparavant. Il suffit donc d’éliminer
Pour cela, le plus aisé est d’utiliser les segments dont le buffer n’est
QGis pour éditer la couche, de Le choix de deux cents mètres
sélectionner manuellement les comme largeur du buffer est
tronçons à ôter, puis de sauve- arbitraire, l’idée étant de retenir
garder le résultat (figure 8). une valeur suffisante pour couvrir
tous les écartements rencontrés.
Il faut ensuite « fusionner » les deux Le résultat est visible figure 9.
voies parallèles pour ne conserver
que l’axe du tracé. Cette opéra- Il faut maintenant trouver le
tion est un peu délicate et néces- moyen de recréer, à partir de
site du doigté. Pour commencer, ce corridor, un axe central.
il faut convertir les deux voies en Pour cela, la nouvelle fonction Figure 9 : Détail du corridor dessiné le long de la
une sorte de « boudin » polygo- ST_StraightSkeleton issue voie grâce à la fusion des deux zones tampon.
nal, en créant des buffers autour du module SFCGAL va nous
de chacun des axes, puis en aider. Son rôle est, en partant
les fusionnant. Cette opération d’un polygone, d’en calculer la
Figure 10 : Résultat de la « squelletisa-
tion ». L’axe central est relié à la péri-
Figure 8 : tracé de la voie après phérie par des tronçons correspondant
ajustements manuels aux « ruptures de pente » élémentaires.
Géomatique Expert|N° 97|Mars-Avril 2014 33pas entièrement contenu dans détaillé dans le cadre ci-après,
le boudin, de regrouper tous prend comme paramètre la table
les segments restants grâce à contenant la ligne à segmenter,
la fonction ST_Union. Bémol et rend en sortie une nouvelle
préliminaire toutefois : le résultat table baptisée du même nom
de la requête précédente, donc affublé du suffixe _tronçons,
la table squelette, est fourni constitué d’une série de tron-
sous forme d’une géométrie çons élémentaires, chacun d’un
Multi-. Il faut donc préalablement kilomètre de long. Moyennant
la découper en tronçons élémen- des améliorations cosmétiques,
taires, ce que fait la fonction il est possible de transmettre la
ST_Dump (). longueur du tronçon élémentaire
en paramètre et de se constituer
CREATE TABLE axe AS (WITH sqlt ainsi une fonction très générique
AS (SELECT (ST_Dump (geom)).
de segmentation linéaire.
geom AS geom FROM squelette) Figure 12 : Élimination de la « fourche »
SELECT s.geom AS geom FROM en bout de ligne. CREATE OR REPLACE FUNCTION découpe
sqlt AS s, boudin AS b WHERE
(voie VARCHAR) RETURNS VOID AS $$
ST_Contains (b.geom, ST_Buffer Une fois ce petit nettoyage
(s.geom, 30)));
accompli, il faut regrouper tous
DECLARE
les segments en une ligne unique.
pk INTEGER := 0;
La clause WITH qui précède Pour cela, on va les réunir dans
pkf DOUBLE PRECISION;
la vraie requête de sélection une multi-géométrie grâce à la
long DOUBLE PRECISION;
réalise le découpage en tronçons, fonction ST_Union, puis on va
tronçons qui sont ensuite triés « recoudre » tous les segments voie_t VARCHAR := voie ||
‘_tronçons’;
individuellement selon la méthode de cette multi-géométrie en une
tmp RECORD;
précédemment décrite. La valeur seule ligne grâce à la fonction
du buffer, 30, est arbitraire : suff- ST_LineMerge.
BEGIN
isante pour éviter les éventuelles
CREATE TABLE ligne AS (SELECT EXECUTE ‘SELECT CAST ((ST_Length
ambiguïtés géométriques, mais ST_LineMerge (ST_Union (geom)) (geom) + 1) / 1000 AS INTEGER)
évidemment inférieure à la largeur AS geom FROM axe); FROM ‘|| voie INTO long;
du corridor (ici 200). Après cette RAISE NOTICE ‘Longueur du tracé :
requête, on se retrouve dans la Il ne reste maintenant qu’une %’, long;
situation de la figure 11. opération à réaliser, mais de taille.
Il s’agit de découper ce nouveau EXECUTE ‘SELECT true FROM pg_
tables WHERE tablename = ‘’’ ||
tracé unique et « médian » en tron-
voie_t || ‘’’’ INTO tmp;
çons d’un kilomètre de longueur
(PK). Il n’existe pas, à l’heure IF (tmp.bool) THEN
actuelle, de fonction PostGIS qui EXECUTE ‘DROP TABLE “’
permette de réaliser cette opéra- || voie_t || ‘”’;
tion (ST_Cut ? ST_Carve ?) END IF;
En revanche, il est possible de
EXECUTE ‘CREATE TABLE “’
réaliser une « extraction » entre
|| voie_t || ‘” (‘ ||
tel et tel PK en utilisant la fonction
Figure 11 : Après élimination des segments ‘pk INTEGER,’ ||
« latéraux », il ne reste plus que l’axe du corridor. ST_Line_Substring (pk1, pk2)
‘pente DOUBLE PRECISION,’ ||
où les PK doivent être exprimés
‘geom GEOMETRY)’;
L’extrémité ouest doit faire l’objet en fraction de la longueur totale
d’un traitement particulier. On se (0,5 correspond, par exemple, FOR pk IN 0..long-1 LOOP
trouve avec un phénomène « de au point situé à mi-chemin des RAISE NOTICE ‘Calcul du
fourche » dû au fait que les deux extrémités). tronçon %’, pk;
voies ne se terminent pas stricte- pkf := CAST (pk AS DOUBLE
ment au même niveau. On élimine Il n’y a pas donc d’autre solu- PRECISION);
cette fourche à la main avec les tion que d’écrire un script en EXECUTE ‘INSERT INTO “’ ||
outils d’édition de PostGIS déjà langage pl/pgsql pour réal- voie_t || ‘” SELECT ‘
évoqués. iser ce découpage. Ce dernier, || pk || ‘, 0, ‘ ||
34 Géomatique Expert|N° 97|Mars-Avril 2014‘(SELECT ST_LineSubstring de la ligne moins un (long-1), WITH moyennes AS (WITH zone
(geom, ‘ || pkf / long et pour chacune d’entre-elles on AS (SELECT ST_DumpAsPolygons
|| ‘, ‘ || insère dans la table _tronçons la (pente, 1) AS mixed FROM pentes)
(pkf + 1) / long || ‘) valeur courante du pk, 0 – valeur SELECT avg ((zone.mixed).val),
FROM “’ || voie || ‘”)’; pk FROM zone, ligne_tronçons
conventionnelle pour la pente – et WHERE ST_Intersects ((zone.
enfin la géométrie correspondant mixed).geom, ligne_tronçons.
END LOOP;
à la section de ligne comprise geom) GROUP BY pk) UPDATE
entre les PK pk et pk+1. ligne_tronçons SET pente =
PERFORM Populate_geometry_ moyennes.avg FROM moyennes
columns (); WHERE moyennes.pk = ligne_tron-
çons.pk;
Association finale
END;
$$ LANGUAGE plpgsql;
Il ne reste plus qu’une opération Cette requête, passablement
à réaliser : associer à chaque complexe, est composée en
Cette fonction n’est pas aisée tronçon la valeur moyenne de réalité de deux sous-requêtes
à comprendre, en raison de la pente correspondante. Pour de type WITH et d’une requête
l’utilisation systématique de cela, il faut en premier… calculer principale de type UPDATE. La
clauses EXECUTE qui permettent la pente ! Pour cela, nous dispo- plus imbriquée (WITH zone AS
d’exécuter un texte comme s’il sons de la fonction ST_Slope qui (SELECT… FROM pentes))
s’agissait d’une requête SQL fait partie des fonctions offertes crée une table appelée zone
directe. Cette syntaxe peu explic- par PGRaster. contenant la vectorisation de la
ite est néanmoins nécessaire à couche raster pentes. Celle-ci
partir du moment où l’on souhaite CREATE TABLE pentes AS (SELECT se compose d’une colonne de
ST_Slope (geom, 1, ‘32BF’,
réaliser une fonction flexible, qui ‘PERCENT’, 1.0, FALSE) AS pente
type mixte (structure) composée
puisse travailler sur une table au FROM mnt); d’un champ geom contenant
nom quelconque. la géométrie et d’un champ
Les différents paramètres passés val contenant la valeur du pixel
Le bloc DECLARE sert à déclarer à la fonction ST_Slope, à part (donc ici la pente). Autrement dit,
les variables qui seront utilisées la colonne géométrique, corre- dans la table zone, on trouve,
par la suite. spondent à la bande (il n’y en a pour chaque valeur de la pente
qu’une dans notre cas), le type de possible, un (multi-)polygone
Les premières lignes du bloc codage utilisé pour représenter correspondant à la réunion de
BEGIN calculent et affichent la l’altitude (ici : réels simple préci- tous les pavés de la grille ayant
longueur de la ligne stockée dans sion), le type d’unité souhaité cette valeur.
la table dont le nom est passé (degrés, radians ou ici pourcent-
en paramètre, et l’affectent à la age), un facteur d’échelle et Cette table est utilisée dans la
variable long. enfin un booléen qui indique s’il seconde prérequête WITH.
faut interpoler là où les données Celle-ci isole toutes les intersec-
La requête suivante regarde si manquent. tions entre les différents tronçons
la table suffixée par _tronçons et les (multi-)polygones d’iso-
existe déjà2. Si oui (dans ce cas, Il serait souhaitable de pouvoir pente, et, pour chaque intersec-
la variable tmp.bool vaut TRUE), réaliser le calcul de la pente tion, note la valeur de pente et
on l’efface. Puis, dans tous les moyenne en récupérant direct- le PK correspondants, avant de
cas, on la crée (ou on la recrée), ement la valeur des cases moyenner les valeurs de pente
en la structurant en trois champs : situées « en-dessous » de la par PK (avg ((zone. mixed).
le PK, la pente et la géométrie du voie. Cela n’est malheureuse- val) … GROUP BY pk;), puis
tronçon kilométrique. ment pas encore possible dans de stocker les résultats dans la
cette version de PostGIS. Il faut table moyennes.
Enfin, la boucle FOR réalise donc « contourner » cette impos-
l’opération de découpage. La vari- sibilité en « vectorisant » la couche Juste avant la requête finale, on
able pk prend toutes les valeurs raster grâce à la fonction ST_ se trouve donc avec une table
entières entre 0 et la longueur DumpAsPolygon. moyenne contenant deux
2. La suite de quatre apostrophes ’’’’, un peu surprenante, correspond à un caractère ’ lui-même entre apostrophes. La norme SQL précise
que si l’on souhaite placer une apostrophe dans une chaîne de caractères, qui doit être elle-même délimitée par des apostrophes, alors il
faut redoubler l’apostrophe médiane. ’’’’ équivaut donc à ‘ ’’ ’.
Géomatique Expert|N° 97|Mars-Avril 2014 35Figure 13 : Résultat de l’affectation de la pente moyenne sous-tendant chaque tronçon kilométrique du tracé.
champs, l’un donnant le PK, et correction et forcer la pente à zéro
l’autre la pente moyenne à ce PK. sous les tunnels, il suffit de repérer
Conclusion
Il ne reste plus qu’à mettre à jour les tronçons qui intersectent les Nous avons donc parcouru rapi-
l’information de pente stockée parties désignées comme tunnel, dement quelques unes des
dans la table ligne_tronçons moyennant le fait que notre axe possibilités offertes par l’utilisation
précédemment créée en effectuant se trouve légèrement décalé par conjointe des logiciels libres que
une jointure par l’intermédiaire du rapport au tracé original (bi-voie). sont QGis et PostGIS avec les
PK. Le résultat apparaît figure 13. différentes bibliothèques sur
UPDATE ligne_tronçons SET pente lesquelles ils s’appuient : GDAL,
= 0 FROM “LGV” WHERE ST_
Nouveau bémol toutefois : notre Intersects (ST_Buffer (ligne_
SFCGAL et CGAL. Dans un
couche ne prend pas en compte tronçons.geom, 30), “LGV”.geom) prochain opus, nous nous inté-
les passages sous les tunnels. AND “LGV”.tunnel ILIKE ‘yes’; resserons aux problématiques
Cette information est contenue 3D et à l’installation du plug-in
dans la table originale (tag tunnel La figure 14 montre le résultat final QGis baptisé Horao, également
à la valeur yes). Pour effectuer la après reclassification du tronçon. développé par OSLandia. |
Figure 14 : Prise en compte du passage en tunnel (pente nulle). On voit clairement
que les tunnels correspondent à la traversée de la « Ligne bleue des Vosges ».
36 Géomatique Expert|N° 97|Mars-Avril 2014Vous pouvez aussi lire