Accueil / Blog / Métier / 2013 / Utiliser les topologies PostGIS pour nettoyer un filaire de voirie

Utiliser les topologies PostGIS pour nettoyer un filaire de voirie

Par Mathieu Leplatre publié 18/10/2013
Cet article présente les bases pour démarrer avec l'utilisation de l'extension topology de PostGIS.
Utiliser les topologies PostGIS pour nettoyer un filaire de voirie

Dans Geotrek, les objets géométriques sont décrits à partir d'un réseau topologique de tronçons, en utilisant la segmentation dynamique. Lors de l'import initial de la BD Topo® IGN ou des filaires de voiries spécifiques, nous procédons à un nettoyage topologique des données.

Cet article présente les bases pour démarrer avec l'utilisation de l'extension topology de PostGIS.

Nous allons tirer parti des topologies pour nettoyer un réseau réel : le filaire de voirie mis à disposition sur le portail OpenData du Grand Toulouse.

/blog/metier/toulouse-voirie/image/

Topologique

Une topologie est un concept très général, où les objets sont définis par leurs relations plutôt que par leurs géométries. Au lieu des lignes, on manipule des arrêtes, des noeuds et des faces : cela doit vous rappeler les fondamentaux de la théorie des graphes.

Un réseau topologique est supposé avoir ses lignes (arrêtes) connectés à des points uniques (noeuds).

Dans ce jeu de données, le validateur JOSM détecte pas moins de 1643 erreurs :) Connexions cassées, lignes qui se croisent ...

/blog/metier/toulouse-voirie-error/image/ /blog/metier/toulouse-voirie-error2/image/ /blog/metier/toulouse-voirie-error3/image/

Aller, nettoyons tout ça !

Installation

Sur Ubuntu 12.04, il suffit d'installer PostGIS :

sudo apt-add-repository -y ppa:ubuntugis/ppa
sudo apt-get update
sudo apt-get install -y postgresql postgis

L'extension topologique est installée par défaut. On l'active juste dans la base :

CREATE DATABASE "roadsdb";
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;
SET search_path = topology,public;

Import des données

Charger le shapefile (avec la ligne de commande) comme d'habitude :

schema="public."
db="roadsdb"
user="postgres"
password="postgres"
host="localhost"
ogr2ogr -f "PostgreSQL" PG:"host=${host} user=${user} dbname=${db} password=${password}" -a_srs "EPSG:2154" -nln ${schema}roads -nlt MULTILINESTRING ROAD_SHAPEFILE.SHP

Créer et associer la topologie PostGIS:

SELECT topology.CreateTopology('roads_topo', 2154);
SELECT topology.AddTopoGeometryColumn('roads_topo', 'public', 'roads', 'topo_geom', 'LINESTRING');

Convertir les lignes brisées en noeuds et arrêtes au sein de la topologie :

-- Layer 1, avec une tolérance de 1.0 mètre
UPDATE roads SET topo_geom = topology.toTopoGeom(wkb_geometry, 'roads_topo', 1, 1.0);

À partir de maintenant, nous avons un réseau topologique, où les imperfections ont été corrigées. Il a fusionné les jonctions imparfaites, où les défauts font moins d'un mètre de large.

/blog/metier/toulouse-voirie-clean/image/

( en vert, version corrigée )

Il est possible de rencontrer des problèmes à l'insertion : l'outil d'import échoue [1] et abandonne alors la transaction complète.

On peut utiliser ce bout de code pour passer outre les erreurs et poursuivre avec les enregistrements suivants:

DO $$DECLARE r record;
BEGIN
  FOR r IN SELECT * FROM roads LOOP
    BEGIN
      UPDATE roads SET topo_geom = topology.toTopoGeom(wkb_geometry, 'roads_topo', 1, 1.0)
      WHERE ogc_fid = r.ogc_fid;
    EXCEPTION
      WHEN OTHERS THEN
        RAISE WARNING 'Loading of record % failed: %', r.ogc_fid, SQLERRM;
    END;
  END LOOP;
END$$;

C'est plutôt frustrant d'avoir des erreurs topologiques à l'insertion ! Parfois, réduire la tolérance règle certains soucis. Il convient aussi de vérifier que les enregistrements ont des géométries valides. Toute clarification ou aide sur ce côté obscure du module topology sont les bienvenus :)

Visualiser et exporter

Pour visualiser les arrêtes de la topologie dans QGIS, parcourir la liste des tables, et ajouter les couches suivantes : roads_topo.edge_data and roads_topo.node.

/blog/metier/toulouse-voirie-topology/image/

On peut aussi exporter les géométries résultants (propres) vers une nouvelle table :

CREATE TABLE roads_clean AS (
    SELECT ogc_fid, topo_geom::geometry
    FROM roads
);

Ou récupérer notre Shapefile chéri :

ogr2ogr -f "ESRI Shapefile" ROAD_CLEAN.SHP PG:"host=${host} user=${user} dbname=${db} password=${password}" -sql "SELECT topo_geom::geometry FROM roads"

Si, comme Amit , on veut obtenir les lignes découpées aux intersections, tout en ajoutant les attributs de la table originale, on peut faire une jointure entre roads_topo.edge_data et la table roads:

SELECT r.lib_off, r.ogc_fid, e.geom
FROM roads_topo.edge e,
     roads_topo.relation rel,
     roads r
WHERE e.edge_id = rel.element_id
  AND rel.topogeo_id = (r.topo_geom).id

Aller plus loin...

Grace aux topologies, il a été possible de fusionner les lignes et de nettoyer les jonctions afin d'obtenir un réseau joli et propre.

Oui mais (hum hum), nous n'avons pas pu réparer automatiquement toutes les erreurs topologiques de ce jeu de données officiel. Certaines incohérences, comme celle ci-dessous, font 6 mètres de large ! À noter, que la même zone est décrite parfaitement dans OpenStreetMap :

/blog/metier/toulouse-voirie-error4/image/

On pourrait aussi jouer avec les simplifications topologiques présentées par Sandro Santilli SimplifyEdgeGeom [2], qui fusionnerait les arrêtes avec une tolérance itérative ...

SELECT SimplifyEdgeGeom('roads_topo', edge_id, 1.0) FROM roads_topo.edge;

N'hésitez pas à partager vos idées et retours. Les exemples et cas d'utilisations du module topology sont très rares! Contactez-nous sur twitter !

[1]SQL/MM Spatial exception, geometry intersects edge, side location conflict, ...
[2]Exécuter le code SQL de la fonction. C'est une routinge élégante autour ST_ChangeEdgeGeom et ST_Simplify.
ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
Geotrek - 1ère rencontre des utilisateurs 21/12/2016

La communauté Geotrek, regroupant environ 60 personnes, s'est retrouvée le 18 octobre 2016 à ...

Geotrek, bilan de deux années pleine de nouveautés 23/09/2016

Nos retours sur cette année de travail avec la communauté

Importer une couche de tronçons dans Geotrek Importer une couche de tronçons dans Geotrek 08/09/2014

Un tutoriel pour charger des tronçons dans la base de données PostGIS de Geotrek avec QGIS

Découvrez les sentiers de randonnées du Parc national des Écrins Découvrez les sentiers de randonnées du Parc national des Écrins 25/07/2013

Faites de la randonnée dans le Parc national des Écrins, avec le nouveau portail en ligne, ...

Formation PostgreSQL / PostGIS du 27 au 29 septembre à Paris Formation PostgreSQL / PostGIS du 27 au 29 septembre à Paris 06/07/2016

Découvrez les outils Libres pour gérer vos données spatiales.