Comparaison des données OpenStreetMap et des données Urbis

  • UrbIS
  • OSM
  • OpenStreetMap
  • PostGIS
  • QGIS

Les données Urbis publiées par la Région de Bruxelles capitale ont été intégrée à l'automne 2013 dans la base de donnée d'OpenStreetMap. Cependant, depuis la publication initiale, une nouvelle version a été publiée chaque trimestre. Les mises à jour n'ont pas toujours été intégrée à OSM, par manque d'outils notamment. Cet article explore une méthode pour détecter les bâtiment à mettre à jour dans OpenStreetMap à partir d'une comparaison entre les données d'OpenStreetMap et de celles d'UrbIS.

La première partie de l'article présente la méthode en général, le résultat et les perspectives. La seconde partie de l'article explique les détails techniques.

Présentation de la méthode

Pour ce travail nous allons utiliser PostGIS un extension de PostgreSQL qui permet la manipulation d'informations géographiques.

Les données d'OSM sont téléchargée à partir du service metro extracts de Mapzen. Ce service propose des exports d'OSM à l'échelle des villes. Une fois les données téléchargées, elles sont intégrées à la db via l'outil Osmosis.

Pour les données d'UrbIS. Nous nous sommes intéressés au shapefile UrbAdm_Bu de la suite UrbAdm. Cette suite peut être téléchargée via la page de téléchargement d'UrbIS. Les données sont injectées dans la db via l'outil shp2pgsql qui est fourni avec PostGIS.

Ensuite, nous avons lancé une requête sql sélectionnant les couples de bâtiments d'OpenStreetMap et d'UrbAdm tels que les deux bâtiments s'intersectent et que leur distance d'Hausdorff soit supérieure à 0.0015. De manière simple la distance d'Hausdorff entre deux géométries indique la similirité (ou non) de deux objects géomatriques.

A partir de ce résultat, nous créons un shapefile que JOSM peut ouvrir grâce au plugin OpenData.

Voici le shapefile créé.

Analyse des résultats

La méthode actuelle a détecté 133 polygones qui diffèrent entre OSM et Urbis. Dans beaucoup de cas, il est très dur de dire quel encodage est correct. Mais il semble que de temps en temps OSM est plus précis qu'Urbis.

En creusant l'analyse, il nous semble tout de même que beaucoup de différences ne sont pas détectées. C'est à améliorer.

Améliorations à apporter

Les multi-polygones ne sont pas gérés par la procédure. Pour ce point nous n'avons pas pour l'instant de solution.

Les bâtiments non existants dans OSM ne sont pas non plus détectés par la procédure. Pour détecter ces cas, c'est assez facile à faire : il suffit de créer un énorme multipolygone avec tous les bâtiments d'OSM, si un bâtiment d'UrbIS a une intersection nulle avec ce multipolygone, il ne se trouve pas dans OSM.

Aussi, il faudrait pouvoir automatiser la procédure pour analyser en direct les données d'OSM et ainsi indiquer aux mappeurs les points à régler.

Finalement, dans certains cas, la différence d'encodage peut être discutée longuement. Il serait bon d'avoir un moyen pour signaler que cette différence n'est pas à corriger. Nous pensons que si un bâtiment OSM et un bâtiment Urbis ont le même urbisid et urbisversion, cela peut indiquer qu'ils ont été vérifiés par un mappeur et que les différences sont acceptables.

Explications techniques

Import des données d'OSM dans PostGIS

$ createdb osm_urbis -O gis
$ psql -d osm_urbis -c "CREATE EXTENSION postgis; CREATE EXTENSION hstore;"
$ psql -d osm_urbis -U gis -f /usr/local/Cellar/osmosis/0.44.1/libexec/script/pgsnapshot_schema_0.6.sql 
$ psql -d osm_urbis -U gis -f /usr/local/Cellar/osmosis/0.44.1/libexec/script/pgsnapshot_schema_0.6_linestring.sql
$ osmosis --read-pbf file=/Users/marcu/Downloads/brussels_belgium.osm.pbf --tag-filter accept-ways building=* --tag-filter reject-relations --used-node --write-pgsql database=osm_urbis user=gis password=gis 

Transformation des lignes en polygones

--DROP TABLE osm_buildings CASCADE;

CREATE TABLE osm_buildings
(
    id bigint Not NULL,
    verion integer NOT NULL,
    user_id integer NOT NULL,
    tags hstore,
    polygon geometry(Geometry,4326),
    polygon_shrinked geometry(Geometry,4326),
    CONSTRAINT pk_osm_buildings PRIMARY KEY (id)
);

INSERT INTO osm_buildings 
    SELECT
        w.id, w.version, w.user_id, w.tags,
        ST_MakePolygon(w.linestring),
        ST_Buffer(ST_MakePolygon(w.linestring), -0.00001)
    FROM ways AS w WHERE ST_NumPoints(w.linestring) >= 4 AND ST_IsClosed(w.linestring);

La colonne polygon_shrinked est le polygone du batiment qui a été un peu rétréci. Ces polygones seront utilisés par la suite afin d'être sûr de bien comparer des polygones semblables.

Import des données UrbIS ADM dans PostGIS

$ shp2pgsql -s 31370:4326 Downloads/UrbAdm_21004_SHP/UrbAdm_Bu.shp UrbAdm_Bu | psql -h localhost -d osm_urbis -U gis


$ shp2pgsql -s 31370:4326 Downloads/UrbAdm_SHP/shp/UrbAdm_Re.sh UrbAdm_Re | psql -h localhost -d osm_urbis -U gis

La table UrbAdm_Bu contient les polygones des bâtiments d'UrbIS. La table UrbAdm_Re contient le polygone de la région de Bruxelles. Ce polygone va être utilisé pour ne sélectionner que les bâtiments d'OSM de la région.

Sélection des bâtiments d'OSM se trouvant dans la région de Bruxelles

-- DROP TABLE osm_buildings_RE CASCADE;

CREATE TABLE osm_buildings_RE
(
    id bigint Not NULL,
    verion integer NOT NULL,
    user_id integer NOT NULL,
    tags hstore,
    polygon geometry(Geometry,4326),
    polygon_shrinked geometry(Geometry,4326),
    CONSTRAINT pk_osm_buildings_re PRIMARY KEY (id)
);

INSERT INTO osm_buildings_RE SELECT b.* FROM osm_buildings AS b, UrbAdm_Re 
    WHERE UrbAdm_Re.id = 1
    AND ST_Intersects(b.polygon, UrbAdm_Re.geom);

Créer des index

Sans cette étape tous les polygones de UrbAdm_Bu sont comparés avec tous les polygones de osm_buildings_re et l'algo ne répond pas...

CREATE INDEX index_urbadm_geom  ON UrbAdm_Bu USING GIST (geom);
CREATE INDEX index_osm_b_re_poly  ON osm_buildings_re USING GIST (polygon);
CREATE INDEX index_osm_b_re_poly_shrinked  ON osm_buildings_re USING GIST (polygon_shrinked); 

Calcul des endroits posant problème

-- DROP TABLE results;

CREATE TABLE IF NOT EXISTS results
(
   osm_building geometry(Geometry,4326),
   osm_id bigint,
   osm_tags  hstore,
   urbis_building geometry(MultiPolygon,4326),
   urbis_id integer,
   urbis_versionid integer,
   hausdorff_distance numeric,
   CONSTRAINT pk_results_osm_urbis_id PRIMARY KEY (osm_id, urbis_id)
);

INSERT INTO results
    SELECT
    osm_b.polygon,
    osm_b.id,
    osm_b.tags,
    ua.geom,
    ua.id,
    ua.versionid,
    ST_HausdorffDistance(ST_Transform(ua.geom,4326),ST_Transform(osm_b.polygon,4326)) 
        FROM UrbAdm_Bu AS ua INNER JOIN osm_buildings_re as osm_b
            ON ST_Intersects(ua.geom, osm_b.polygon_shrinked)
            WHERE ST_HausdorffDistance(ua.geom,osm_b.polygon) > 0.0015;

Création du shapefile

Ouvrir la table avec QGIS et l'exporter en shapefile.