Dernière modification
Résumé : Tracer les limites administratives d'un territoire avec Gnuplot à partir de données d'OpenStreeMap. Cette page est obsolète, voir plutôt Tracé de frontières avec gnuplot(2)
Ajouté(e) :
> '''Cette page est obsolète, voir plutôt [[Tracé de frontières avec gnuplot(2)]]'''
Cette page est obsolète, voir plutôt Tracé de frontières avec gnuplot(2)
Dans les données d'OpenStreetMap, les limites administratives des territoires sont des routes comme les autres, composées de noeuds. L'objectif est ici de rassembler en un fichier les coordonnées (latitude et longitude) de ces points, de manière à pouvoir les visualiser avec gnuplot.
Exemple avec la Belgique.
D'abord obtenir le fichier osm de la frontière belge, qu'on peut visualiser sur http://www.openstreetmap.org/browse/relation/52411.
wget -O 52411.osm http://www.openstreetmap.org/api/0.6/relation/52411
On pourrait obtenir tous les noeuds en un seul fichier en ajoutant /full à cette url, mais je préfère rapatrier les données de chaque membre séparément pour m'assurer qu'ils soient ordonnés1.
<?xml version="1.0" encoding="UTF-8"?> <osm version="0.6" generator="OpenStreetMap server"> <relation id="52411" visible="true" timestamp="2009-10-28T23:30:32Z" version="295" changeset="2977966" user="Ldp" uid="48796"> <member type="way" ref="24718735" role="enclave"/> <member type="way" ref="25417004" role="enclave"/> <member type="way" ref="25418377" role="enclave"/> (etc.) <member type="way" ref="43312486" role=""/> <tag k="admin_level" v="2"/> <tag k="boundary" v="administrative"/> <tag k="ISO3166-1" v="be"/> <tag k="name" v="België - Belgique - Belgien"/> <tag k="name:da" v="Belgien"/> <tag k="name:de" v="Belgien"/> <tag k="name:el" v="Βέλγιο"/> <tag k="name:en" v="Belgium"/> <tag k="name:es" v="Bélgica"/> <tag k="name:fr" v="Belgique"/> <tag k="name:nl" v="België"/> <tag k="native_name:da" v="Kongeriget Belgien"/> <tag k="native_name:de" v="Königreich Belgien"/> <tag k="native_name:el" v="Βασίλειο του Βελγίου"/> <tag k="native_name:en" v="Kingdom of Belgium"/> <tag k="native_name:es" v="Reino de Bélgica"/> <tag k="native_name:fr" v="Royaume de Belgique"/> <tag k="native_name:nl" v="Koninkrijk België"/> <tag k="timezone" v="Europe/Brussels"/> <tag k="TMC:cid_58:tabcd_1:Class" v="Area"/> <tag k="TMC:cid_58:tabcd_1:LCLversion" v="8"/> <tag k="TMC:cid_58:tabcd_1:LocationCode" v="3"/> <tag k="type" v="boundary"/> </relation> </osm>
On va ensuite rapatrier les fichers correspondant à chaque membre mentionné au moyen de ce script Perl. On utilise XML::Simple qui permet de transformer des données xml en une structure arborescente de type hashref2 :
#! /usr/bin/perl use LWP::Simple; use XML::Simple; $filename = $ARGV[0]; my $ref = XMLin($filename); @members = @{$ref->{'relation'}->{'member'}}; foreach (@members) { my $id = $_->{'ref'}; print "# $id\n"; # l'id de chaque segment sera incorporé dans # le fichier comme un commentaire. my $content = get("http://api.openstreetmap.org/api/0.6/way/$id/full"); my $ref = XMLin($content, ForceArray => 1, KeyAttr => []); foreach $node (@{$ref->{node}}) { print " $node->{lat} $node->{lon}\n" } print "\n\n"; # gnuplot demande une double ligne vide pour séparer } # les données
Le fait de séparer les données permettra éventuellement d'en tracer une sélection avec gnuplot (avec l'option index n, voir la documentation de gnuplot[1]).
gv@fantasio:~/travaux/openstreetmap$ ./getways.pl 52411.osm > Belgique.dat
Le fichier obtenu contient bien les données sous cette forme:
# 24718735 50.5971521 6.2465063 50.5968143 6.2480513 50.5977787 6.2484375 50.5981764 6.2469527
# 25417004 50.5565244 6.2175382 50.5562626 6.2181133 (etc.)
On peut déjà les visualiser avec gnuplot
gnuplot> plot 'Belgique.dat' using 2:1 with lines
La frontière ainsi dessinée ne comprend pas la ligne côtière, mais bien la limite des eaux territoriales.
Pour obtenir cette ligne côtière, je n'ai pas trouvé de relation unique qui la synthétise. Mais en zoomant sur un fragment de la carte et en exportant les données xml, j'ai repéré des routes non visibles dotées de ces attributs:
<tag k="natural" v="coastline"/>
J'ai donc rapatrié les données de ce type en précisant une BoundingBox correspondant à la côte belge:
gv@fantasio:~/travaux/openstreetmap$ wget -O coastline.osm http://osmxapi.hypercube.telascience.org/api/0.6/way[natural=coastline][bbox=2.48,51.08,3.38,51.38]
et modifié légèrement le premier script pour qu'il rapatrie les noeuds de toutes les routes mentionnées dans ce fichier osm:
#! /usr/bin/perl use LWP::Simple; use XML::Simple; $filename = $ARGV[0]; my $ref = XMLin($filename, ForceArray => 1, KeyAttr => []); @ways = @{$ref->{'way'}}; foreach (@ways) { my $id = $_->{'id'}; print "# $id\n"; my $content = get("http://api.openstreetmap.org/api/0.6/way/$id/full"); my $ref = XMLin($content, ForceArray => 1, KeyAttr => []); foreach $node (@{$ref->{node}}) { print " $node->{lat} $node->{lon}\n" } print "\n\n"; }
gv@fantasio:~/travaux/openstreetmap$ ./coastline.pl coastline.osm > coastline.dat
On peut alors dessiner la carte avec gnuplot3, et l'exporter en format bitmap (png par ex.) ou postscript:
gnuplot> plot 'Belgique.dat' using 2:1 with lines lt 9 gnuplot> replot 'coastline.dat' using 2:1 with lines lt 7 gnuplot> set term postscript eps solid color Terminal type set to 'postscript' Options are 'eps noenhanced defaultplex \ leveldefault color colortext \ solid dashlength 1.0 linewidth 1.0 butt \ palfuncparam 2000,0.003 \ "Helvetica" 14 ' gnuplot> set output 'carte.eps' gnuplot> replot
Le résultat est présent à cette adresse, au format eps.
ForceArray => 1, KeyAttr => []
est très importante; gràce à cela, les noeuds restent ordonnés dans une liste de type array, en respectant l'ordre existant dans les données osm. Sinon, chacun serait intégré dans une structure de tableau, avec son id comme clé. Or l'ordre des éléments d'un tableau n'est pas controllable. Et par conséquent, en joignant ces noeuds par une ligne, le résultat serait incohérent.