Cartographie

Bouquet final de cette activité autour des fichiers GPX : la représentation graphique d'informations sur une carte OpenStreetMap. Il existe justement un module Python qui facilite cette opération.

Le module folium

Ce module doit être installé avant d'être utilisé. La commande sous Windows est la suivante :

python.exe -m pip install folium

Et sous macOS

python3 -m pip install folium

Attention !

Cette commande doit être exécutée en mode administrateur. Sous Windows, dans le menu Démarrer, clic droit sur l'application "invite de commandes" et choisir "exécuter en tant qu'administrateur".

Le module folium permet de créer une carte OpenStreetMap et d'y dessiner des marqueurs, des lignes brisées, des polygones, etc.

import folium

# Création d'une carte
fmap = folium.Map(location=[55.7353606, 10.822693], tiles="OpenStreetMap", zoom_start=8)

# Ajout d'un marqueur
folium.Marker([55.8716693, 9.8839912],
              popup="VIA University College",
              icon=folium.Icon(color='green')).add_to(fmap)


# Ajout d'une ligne brisée définie à partir de 5 points
points = [
  (55.6713808, 12.4533972),
  (55.4013094, 11.2062387),
  (55.3311408, 10.6322608),
  (55.7148992, 9.3734841),
  (55.8716693, 9.8839912)
]

folium.PolyLine(points, color="blue", weight=2.5, opacity=0.8).add_to(fmap)

# Génération du fichier HTML contenant la carte
fmap.save("via.html")

La méthode folium.Map(location=[latitude, longitude], tiles="OpenStreetMap", zoom_start=zoom) crée une carte centrée sur le point de coordonnées (latitude, longitude) avec un grossissement égal à zoom (compris entre 1 et 18) en utilisant un fond de carte OpenStreetMap.

La méthode Marker() place un marqueur sur la carte au point de cordonnées (latitude,longitude) avec une couleur (paramètre color) choisie dans une palette de 147 nuances et un titre (paramètre popup).

La méthode PolyLine() dessine une ligne brisée à partir d'une liste de couples de coordonnées.

Enfin, la méthode save() génère un fichier HTML qui embarque la carte, ainsi que tous les éléments ajoutés par le script (marqueurs, lignes, polygones, etc).

Exercice

Modifiez (une dernière fois) le script GPXplorer.py afin de générer une carte centrée sur le point de départ du parcours. Vous représenterez le parcours sous la forme d'une ligne brisée bleue d'épaisseur 3. Vous placerez aussi quatre marqueurs : un sur le départ, un sur l'arrivée et deux autres correspondant respectivement aux points de plus faible et plus grande altitude.

Correction
from lxml import etree
from GPSutils import *
import folium

# Liste des latitudes exprimées en degrés
latitude  = []

# Liste des longitudes exprimées en degrés
longitude = []

# Liste des altitudes exprimées en m
elevation = []

# Liste des instants de chaque mesure en secondes,
# le premier étant égal à 0
time      = []

# Liste des distances cumulées
distance  = []

inputFilename = "RATJ2012-21km-herve.schely.gpx"
root = etree.parse(inputFilename)
ns = "http://www.topografix.com/GPX/1/1"

#
# Heure de départ
#
datetimelist = root.xpath("/ns:gpx/ns:trk/ns:trkseg/ns:trkpt/ns:time", namespaces={"ns": ns}) 
startTime = datetimelist[0].text

trackpointlist = root.xpath("/ns:gpx/ns:trk/ns:trkseg/ns:trkpt", namespaces={"ns": ns}) 
for point in trackpointlist:
    latitude.append(float(point.get("lat")))
    longitude.append(float(point.get("lon")))
    for param in point.getchildren():
        if param.tag == "{" + ns + "}ele":
            elevation.append(float(param.text))

        if param.tag == "{" + ns + "}time":
            time.append(duration(startTime, param.text))

distance.append(0)
for i in range(1,len(time)):
    d = greatCircleDistance(latitude[i-1], longitude[i-1], latitude[i], longitude[i])
    distance.append(distance[i-1]+d)

minElevationIndex = 0
maxElevationIndex = 0
for i in range(1,len(elevation)):
    if elevation[i]>elevation[maxElevationIndex]:
        maxElevationIndex = i
    if elevation[i]<elevation[minElevationIndex]:
        minElevationIndex = i

fmap = folium.Map(location=[latitude[0], longitude[0]], tiles="OpenStreetMap", zoom_start=13)

folium.Marker([latitude[0], longitude[0]],
              popup="Départ",
              icon=folium.Icon(color='green')).add_to(fmap)

folium.Marker([latitude[-1], longitude[-1]],
              popup="Arrivée",
              icon=folium.Icon(color='red')).add_to(fmap)

folium.Marker([latitude[minElevationIndex], longitude[minElevationIndex]],
              popup=str(elevation[minElevationIndex]) + " m",
              icon=folium.Icon(color='blue')).add_to(fmap)

folium.Marker([latitude[maxElevationIndex], longitude[maxElevationIndex]],
              popup=str(elevation[maxElevationIndex]) + " m",
              icon=folium.Icon(color='lightblue')).add_to(fmap)

# Draw polyline
points =[]
for i in range(0, len(latitude)):
    points.append(tuple([latitude[i], longitude[i]]))

folium.PolyLine(points, color="blue", weight=3, opacity=0.6).add_to(fmap)

fmap.save('gpx.html')

Vous pouvez tester votre script sur d'autres fichiers GPX.

Je suggère que nous nous dégourdissions les jambes avant d'aborder le chapitre suivant qui traite des interfaces graphiques ou comment créer des applications Python dans une fenêtre avec des boutons, des cases à cocher, des listes déroulantes, des images, etc.