Tracé de frontières avec gnuplot(2)

Dernière modification

Résumé : Comment transformer les données osm représentant la limite d'une région en données utilisables par gnuplot.

Modifié(e) :

< Tags: OpenStreetMap, gnuplot

à

> [[Gnuplot]]
> Tags: OpenStreetMap


Gnuplot

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 d'en extraire les coordonnées (latitude et longitude) au moyen d'xslt et xmlstarlet[1], 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/937244 mais en ajoutant la terminaison /full qui permet que lorsqu'un élément comprend une référence vers un autre élément (c-à-d. en pratique les noeuds mentionnés dans les routes), ceux-ci sont inclus dans le fichier.

  wget -O 937244.osm http://www.openstreetmap.org/api/0.6/relation/937244/full

On peut commencer par vouloir en connaître le nombre d'éléments:

 $ xmlstarlet sel -t -o "nodes: " -v "count(//node)" -n \ 
   -o "ways: " -v "count(//way)"  937244.xml
 nodes: 24156
 ways: 224

On pourrait être tenté d'extraire la longitude et la latitude de chaque point au moyen d'une requête simple:

  $ xmlstarlet sel -t -m "//node" -v "concat(@lon,' ',@lat)" \
    -n   937244.xml > coutour_Belgique.dat

Mais le résultat est inutilisable car les points ne sont pas ordonnés.

http://www.k1ka.be/pics/contour.png

Il faut donc accéder d'abord à chacun des éléments way, puis aux points référencés dans ceux-ci. La requête est un peu plus complexe et passe par un fichier xslt:

  <xsl:template match="/">
    <xsl:call-template name="t1"/>
  </xsl:template>
  
  <xsl:key name="ref" match="node" use="@id" />
  
  <xsl:template name="t1">
    <xsl:for-each select="//way">
      <xsl:value-of select="'# way:'"/>
      <xsl:value-of select="@id"/>
      <xsl:value-of select="'&#10;'"/>
      <xsl:for-each select="nd">
        <xsl:variable name="refid" select="@ref"/>
        <xsl:value-of select="key('ref',$refid)/@lon"/>
        <xsl:value-of select="' '"/>
        <xsl:value-of select="key('ref',$refid)/@lat"/>
        <xsl:value-of select="'&#10;'"/>
      </xsl:for-each>
    <xsl:value-of select="'&#10;&#10;'"/>
    </xsl:for-each>
  </xsl:template>

qui permet de passer la commande

  $ xmlstarlet tr nodes_w_keys.xsl 937244.xml > contour_Belgique.dat

et le fichier est à présent traçable avec gnuplot:

 gnuplot> set term png
 Terminal type set to 'png'
 Options are 'nocrop font /usr/share/fonts/truetype/ttf-liberation 
 /LiberationSans-Regular.ttf 12 size 640,480 '
 gnuplot> set key off
 gnuplot> set output 'contour_Belgique.png'
 gnuplot> plot 'contour_Belgique.dat' with lines

http://www.k1ka.be/pics/contour_Belgique.png

Reste que les segments composant la frontière ne sont pas eux-mêmes ordonnés, ce qu'on peut observer en lançant le tracé en spécifiant un nombre limité de ces segments:

 gnuplot> plot 'contour_Belgique.dat'  index 1:10 with lines

L'idéal serait donc de trouver un moyen d'ordonner les points...