Cartographier des numéros d’autoroutes multiples dans OpenStreetMap

J'ai eu dernièrement à extraire les numéros d'autoroutes des segments de géométries du réseau routier de OpenStreetMap. Il arrive régulièrement que des segments aient plus d'un numéro d'autoroute. Dans ce cas, les numéros seront listés dans le champ 'ref' de la géométrie. Par exemple:
SELECT type, oneway, CHAR_LENGTH(ref) AS reflen,ref
     FROM osm_roads
     WHERE type IN ('motorway', 'trunk')
       AND (ref IS NOT NULL AND ref != '')
AND ref like '%;%'
limit 10;
   type   | oneway | reflen |       ref
----------+--------+--------+-----------------
 trunk    |      1 |      9 | US 412;84
 motorway |      1 |     10 | I 72;US 36
 motorway |      1 |     10 | I 72;US 36
 trunk    |      0 |      9 | NH947;SH6
 motorway |      1 |      9 | I 55;I 69
 trunk    |      1 |     11 | US 10;WI 13
 motorway |      1 |     15 | I 55;I 70;US 40
 trunk    |      0 |     11 | US 278;MS 6
 motorway |      1 |     15 | I 55;I 70;US 40
 motorway |      1 |     11 | I 69;MS 304
(10 rows)
En utilisant un Regex et des array dans la base de données Postgresql/PostGIS, il sera possible d'isoler et multiplier les numéros sur autant de lignes que de numéros trouvés (NOTE: on retrouve une expression régulière semblable dans plusieurs scripts de traitement de données OSM sur le Web): Dans cet exemple ref = 'I 39;I 90'
SELECT 'segment 1' as id,
(regexp_matches('I 39;I 90',
                '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
                'g'))[1] as shield_class,
(regexp_matches('I 39;I 90',
                '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
                'g'))[3] as shield_no;

    id     | shield_class | shield_no
-----------+--------------+-----------
 segment 1 | I            | 39
 segment 1 | I            | 90
(2 rows)
Dans cet autre exemple ref = 'I 39- 90'
SELECT 'segment 2' as id,
(regexp_matches('I 39- 90',
                '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
                'g'))[1] as shield_class,
(regexp_matches('I 39- 90',
                '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
                'g'))[3] as shield_no;

    id     | shield_class | shield_no
-----------+--------------+-----------
 segment 2 | I            | 39
 segment 2 |              | 90
(2 rows)
Et enfin ref = 'I 39;US 90/S 109'
SELECT 'segment 3' as id,
(regexp_matches('I 39;US 90/S 109',
               '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
               'g'))[1] as shield_class,
(regexp_matches('I 39;US 90/S 109',
                '([a-z,A-Z]+)?(\s|\-)?([0-9]+)[^;|/|\s]*',
                'g'))[3] as shield_no;

    id     | shield_class | shield_no
-----------+--------------+-----------
 segment 3 | I            | 39
 segment 3 | US           | 90
 segment 3 | S            | 109
(3 rows)
En utilisant cette astuce, il sera donc possible de cartographier plusieurs numéros sur un même segment de route

2 comments — post a comment

benoit

tu associes à un segment d’autoroute un ou plusieurs numéros d’autoroutes
mais comment faire pour que ces numérs ne se chevauchent pas sur la carte?

Simon Mercier

Si vous utilisez TileMill, ce n’est pas possible. J’ai essayé quelques options mais ça elles ne fonctionnent pas vraiment: http://gis.stackexchange.com/questions/47985/tilemill-label-and-shield-are-overlapping-how-can-this-be-solved. La solution que j’ai utilisé avec cette requête est relativement plus complexe que montrée ici. Elle conciste à découper les segements à numéros multiples en autant de numéros que contient la valeur texte (dans PostGIS avec ST_Line_Substring()).

Si vous utilisez Mapserver, vous pouvez utiliser MINDISTANCE et un REPEATDISTANCE plus grand que MINDISTANCE, l’alternance devrait bien fonctionner. Comme c’est souvent le cas, c’est BEAUCOUP plus simple avec Mapserver.


LABEL
...
MINDISTANCE 50
REPEATDISTANCE 250
...
END

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current month ye@r day *