Pour des raisons techniques, je ne peux pas passer par l'API classique prévue par exemple par Google.
En effet, il s'agit d'une API javascript, et le navigateur intégrée à la PSP est très limité.
L'intérêt est donc d'étudier comment Google Maps, Virtual Earth et Yahoo! Maps stockent leurs images pour les récupérer directement à la source.
Ainsi, il devient possible de les intégrer à des applications de plus bas niveau.
On trouve déjà pas mal de documentation sur internet, mais je n'ai pas trouvé de billet résumant tout sur la même page, et encore moins en français, ce que je vais essayer de faire ici.
La meilleure façon d'obtenir les informations est d'utiliser un sniffer réseau, afin de récupérer les requêtes effectuées pendant qu'on utilise le service de cartographie dans son navigateur.
Personnellement, j'ai utilisé Wireshark (l'ancien Ethereal), qui reconnait le protocole HTTP et le présente de façon simplifié.
Les 3 principaux services de cartographies se ressemblent énormément au niveau de la projection et du découpage de la carte.
La carte est découpée en carrés de 256 x 256 pixels, et chaque fois qu'on zoome on redivise le carré en 4 nouvelles images.
Je trouve assez amusant de voir que les 3 acteurs ont choisi exactement les mêmes chiffres. Pourquoi 256 pixels et pas 512 ou 1024 ? Pourquoi découper exactement de la même façon la carte ?
En tout cas c'est très sympa pour le programmeur car ça rend plus facile l'écriture d'un programme compatible avec les 3 services de cartographie.
On arrive ainsi à passer d'une carte à une autre en étant aligné au pixel près !
Dans la suite du billet, "z" désigne le niveau de zoom, et "x" et "y" les coordonnées.
Pour nommer une image de la carte à un niveau de zoom donné, on va distinguer 2 méthodes de désignation : la méthode "récursive" et la méthode "linéaire".
Par exemple pour désigner la zone rouge suivante (z=3) :
La première façon de désigner les images est tout simplement de numéroter les lignes et les colonnes de 0 à 2^z-1.
Par exemple, x=5 et y=3 pour la zone rouge.
| (0,0) | (1,0) | (2,0) | (3,0) | (4,0) | (5,0) | (6,0) | (7,0) |
| (0,1) | (1,1) | (2,1) | (3,1) | (4,1) | (5,1) | (6,1) | (7,1) |
| (0,2) | (1,2) | (2,2) | (3,2) | (4,2) | (5,2) | (6,2) | (7,2) |
| (0,3) | (1,3) | (2,3) | (3,3) | (4,3) | (5,3) | (6,3) | (7,3) |
| (0,4) | (1,4) | (2,4) | (3,4) | (4,4) | (5,4) | (6,4) | (7,4) |
| (0,5) | (1,5) | (2,5) | (3,5) | (4,5) | (5,5) | (6,5) | (7,5) |
| (0,6) | (1,6) | (2,6) | (3,6) | (4,6) | (5,6) | (6,6) | (7,6) |
| (0,7) | (1,7) | (2,7) | (3,7) | (4,7) | (5,7) | (6,7) | (7,7) |
L'autre technique de désignation est la suivante : on divise la carte en 4, le quart nord-ouest s'appele "A", le quart nord-est "B", le quart sud-ouest "C" et le quart sud-est "D".
On redivise récursivement le bon carré de la même façon.
En concaténant les lettres obtenu on obtient la référence de l'image, en "z" lettres pour un zoom de niveau "z".
Par exemple "BCD" pour notre zone rouge.
Les coordonnées "x" et "y" n'apparaissent donc pas directement, mais on passe facilement d'un système à l'autre avec une fonction récursive.
| A |
|
||||||||
| C | D |
Et voilà, ces deux techniques sont les seules utilisées par nos services de cartographies, aux lettres utilisées près, et aux décalages près...
Voici le détail :
-
Google Maps
Chez Google, le zoom est numéroté de 17 à -4 (on peut peut-être aller encore plus bas sur certaines zones).
17 correspond au niveau de zoom le plus lointain, où on voit toute la terre dans un carré de 256x256 pixels.
-
Vue "Map"
C'est la vue par défaut, les images sont au format PNG.
Les coordonnées "x" et "y" sont linéaires, et vont de 0 à 2^(17-z)-1.
L'adresse est de la forme suivante :http://mt0.google.com/mt?n=404&v=w2.69&x=5&y=3&zoom=14

mt0 est un des serveurs d'images, il y en a d'autres (mt1, mt2 et mt3 en ce moment).
Le paramètre v=2.69 doit être mis à jour pour se conformer à la dernière version du protocole.
Comme vous pouvez le voir, il n'y a pas de clef en paramètre (pas d'API key). On peut donc obtenir les images de façon "publique".
-
Vue "Terrain"
Images au format JPEG, même système de coordonées, avec une adresse légèrement différente :http://mt0.google.com/mt?n=404&v=w2p.64&x=5&y=3&zoom=14

Le paramètre v=2p.64 doit être mis à jour pour se conformer à la dernière version du protocole.
-
Vue "Satellite"
Les images sont au format JPEG.
La technique pour désigner les images est l'approche récursive, avec les lettres "q" (pour le NW), "r" (pour le NE), "s" (pour le SE), "t" (pour le SW).
La racine est désignée par "t" :http://kh0.google.com/kh?n=404&v=25&t=trts

Là aussi il y a d'autres serveurs possibles (kh1, kh2 et kh3 en ce moment).
Attention, j'ai remarqué que Google Maps peut blacklister temporairement votre addresse IP si vous faites trop de requêtes sur ces serveurs...
-
-
Virtual Earth
Chez Virtual Earth, c'est encore plus simple, seule la technique "récursive" est utilisée, avec les chiffres "0" (pour le NW), "1" (pour le NE), "2" (pour le SW) et "3" (pour le SE).
Bizarrement, c'est le protocole pour lequel j'ai trouvé le plus de documentation "officielle" : Contrairement à Google Maps, il n'y a pas de "racine", on démarre tout de suite avec 4 images au plus haut niveau.
-
Vue "Road"
Les images sont au format PNG :http://tiles.virtualearth.net/tiles/r123?g=117

Le paramètre g=117 est à mettre à jour en fonction du numéro actuel de version.
Là aussi il y a plusieurs serveurs, mais j'ai choisi le nom de domaine de plus haut niveau, qui assure lui-même la répartition (round robin DNS). -
Vue "Aerial"
Les images sont au format JPEG :http://tiles.virtualearth.net/tiles/a123?g=117

-
Vue "Hybrid"
Les images sont au format JPEG :http://tiles.virtualearth.net/tiles/h123?g=117

-
-
Yahoo! Maps
Le découpage utilisé est "linéaire", avec un zoom "z" démarrant à 18 (histoire de ne pas faire 17 comme Google
), "x" variant entre 0 et 2^(18-z)-1, et "y" variant entre -2^(17-z) et 2^(17-z)-1.
Attention l'axe "y" est inversé par rapport aux autres protocoles (les grandes valeurs sont au nord).-
Vue "Map"
Les images sont au format JPEG :http://us.maps1.yimg.com/us.tile.yimg.com/tl?v=4.1&x=5&y=0&z=15

-
Vue "Satellite"
Les images sont au format JPEG :http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.7&t=a&x=5&y=0&z=15

-
Sur PSP-Maps, j'ai rajouté un petit effet de "fading" lorsqu'on passe d'une vue à l'autre, et c'est du plus bel effet

Dans votre programme, il faut choisir votre système de coordonnées "principal".
Dans PSP-Maps, j'ai commencé par le support de Google Maps, donc j'ai gardé ce système de coordonnées linéaires.
On a donc "z" qui varie entre 17 et -4, "x" et "y" qui varient entre 0 et 2^(17-z)-1.
Lorsqu'on zoome, il suffit de décrémenter "z", et de multiplier "x" et "y" par 2.
Lorsqu'on dézoome, il suffit d'incrémenter "z", et de diviser "x" et "y" par 2.
Pour passer aux coordonnées linéaires utilisées par Yahoo! Maps, on peut réutiliser "x" directement, "z+1" comme niveau de zoom, et il faut décaler "y" : "2^(16-z)-y-1".
Pour passer aux coordonnées récursives utilisées par Google Maps, j'utilise la fonction suivante :
/* returns in buffer "b" the name of the Google Maps tile for location (x,y,z) */
void GGtile(int x, int y, int z, char *b)
{
int c = 18 - z;
b[c] = '\0';
while (z++ < 17)
{
c--;
if (x % 2)
{
if (y % 2)
b[c] = 's';
else
b[c] = 'r';
}
else
{
if (y % 2)
b[c] = 't';
else
b[c] = 'q';
}
x/=2;
y/=2;
}
b[0] = 't';
}
Pour passer aux coordonnées récursives utilisées par Virtual Earth, j'utilise la fonction suivante :
/* returns in buffer "b" the name of the Virtual Earth tile for location (x,y,z) */
void VEtile(int x, int y, int z, char *b)
{
int c = 17 - z;
b[c] = '\0';
while (z++ < 17)
{
c--;
if (x % 2)
{
if (y % 2)
b[c] = '3';
else
b[c] = '1';
}
else
{
if (y % 2)
b[c] = '2';
else
b[c] = '0';
}
x/=2;
y/=2;
}
}
Avec des commentaires et un contrôle sur les paramètres ça serait mieux 
Comme il ne s'agit que de requêtes HTTP, je pense qu'il n'y a pas de "risques" à utiliser ces informations, même si chaque service peut choisir de vous bannir.
C'est le cas de Google Maps si vous faites trop de requêtes (heureusement c'est un blacklistage temporaire).
Je vous invite fortement à mettre en place un cache local, afin de ne pas surcharger les serveurs de requêtes, et d'améliorer la fluidité de votre application.
Attention à la taille de celui-ci, ça grossi vite. Pour FreeMaps que je n'ai jamais "nettoyé", j'en suis à :
royale@fanta:~$ ls freemaps-cache/ | wc -l 439017 royale@fanta:~$ du -hs freemaps-cache/ 5,7G freemaps-cache/Certaines images ne sont pas disponibles à tous les niveaux de zoom, il faut donc gérer la réponse du serveur.
Sur PSP-Maps j'envoie directement le buffer de réponse à la fonction IMG_Load_RW de SDL_Image.
Si l'image est valide (PNG ou JPEG), un pointeur vers l'image décodée est retourné.
Si l'image est invalide (erreur HTML par exemple), NULL est retourné.
