Altitude sur les cartes numériques

Sur les cartes de ce site, pour afficher en bas à gauche de l'écran l'altitude du point où se trouve le curseur, nous utilisons traditionnellement le service BD Alti de l'IGN, qui nous retourne, pour une longitude et une latitude données, une altitude.


Mais quand nous nous promenons en Italie, au-delà de quelques kilomètres de la frontière, le service de l'IGN ne nous retourne plus d'information, ou plutôt une valeur d'altitude de -99999 mètres, car ce n'est plus dans son secteur géographique.


Heureusement, au début des années 2000, la navette spatiale Endeavour de la NASA avait procédé à un relevé radar de la quasi-totalité de la surface de la Terre, et a mis ces données à la disposition de tous. Ces fichiers, nommés SRTM, avaient initialement une résolution (distance entre chaque altitude) de 90 mètres, puis ces dernières années sont apparues des versions plus précises, d'une résolution de 30 mètres.


Navette spatiale Endeavour de la NASA
Navette spatiale Endeavour - crédit photo : NASA

Chaque fichier SRTM, pesant 25 Mo, couvre une zone d'environ 110 km par 110 km, et contient près de 13 millions de valeurs d'altitude. Mais comme nous l'expliquons plus bas, il est très simple et surtout rapide (moins de 50 ms sur notre serveur), d'extraire une altitude pour une longitude et une latitude donnée.


La précision de ces données est très bonne, environ 10 mètres, à notre avis identique entre la BD Alti de l'IGN et les données SRTM. La seule restriction est sur les sommets : comme la résolution est de 30 mètres, et qu'un sommet est souvent bien plus petit que cela, la valeur retournée est une moyenne basse, typiquement 10 à 20 mètres de moins que la réalité.


Mais comme nous disposions des traces GPS de nos randonnées, qui contiennent des altitudes souvent juste à 1 ou 2 mètres près, nous les avons également intégrées dans notre algorithme. Près de 100.000 points extraits de 130 fichiers, pour la plupart le long de sentiers et sur les sommets de la région. Ainsi, si vous posez le curseur sur le sommet du Mont Mounier, s'affiche l'altitude correcte de 2.817 mètres, au lieu de 2.811 pour la BD Alti.


Pour savoir pour chaque altitude d'où nous prenons l'information, il suffit de regarder la lettre "m" qui suit l'altitude : si elle suivie du symbole ":", la valeur vient de nos traces GPS. Si c'est le symbole ".", l'origine est un fichier SRTM. Et s'il n'y a pas de symbole, c'est l'IGN qui fournit l'altitude.


Exemple de calcul d'altitude sur une carte numérique
Altitudes calculées grâce à nos traces GPS, au Mont Mounier et au Pizzo d'Ormea

Extraction des altitudes dans les fichiers SRTM

Pour qui voudrait exploiter avec quelques lignes de programme les données des fichiers SRTM, voici quelques explications techniques, avec des exemples en langage PHP.
Correction du code le 11/08/17 pour gérer les longitudes et latitudes négatives.


Les fichiers, avec une extension .HGT, contiennent 3601 lignes de 3601 colonnes, couvrant exactement un degré en longitude et en latitude. Chaque point est un entier signé sur 16 bits, au format "big-endian" (octet de poids fort avant octet de poids faible), qui représente l'altitude en mètres. Tout cela est détaillé, en anglais, ici.


Les fichiers sont nommés sont la forme N<latitude>E<longitude>.HGT, pour leur coin inférieur gauche (sud-ouest), donc si les coordonnées en degrés décimaux de notre point sont latitude=43.91139 et longitude=7.23158 (la Madone d'Utelle), il nous faut le fichier N43E007.HGT.


Pour récupérer ces fichiers, saisissez dans votre moteur de recherche favori le nom d'un fichier, comme N43E007.HGT, et vérifier que le fichier à l'intérieur du .ZIP fait bien 25 Mo (s'il est plus petit, c'est un fichier de résolution 90 mètres).


Ou, pour les Alpes et l'Europe du Sud, nous les mettons à disposition en téléchargement.


Pour trouver la ligne dans le fichier, prendre la fraction de la latitude, et la multiplier par 3601, et comme les lignes vont du nord vers le sud, soustraire ce résultat de 3601 :


$i=3601-floor((abs($lat-floor($lat)))*3601);

Pour trouver la colonne dans la ligne, procéder de même :


$j=floor(abs($lon-floor($lon))*3601);

Et pour la position dans le fichier, multiplier l'indice de la ligne par la longueur d'une ligne, ajouter la colonne, sans oublier de multiplier le résultat par 2, chaque point occupant deux octets :


$filePos=(($i-1)*3601+($j-1))*2;

Pour la lecture dans le fichier, se positionner à l'endroit calculé, lire les deux octets, calculer le résultat, et dans notre cas le retourner au format JSON :


fseek($hgtHandle,$filePos);
$byte1=fread($hgtHandle,1);
$byte2=fread($hgtHandle,1);
$alti=ord($byte1)*256+ord($byte2);
echo json_encode($alti);