====== Mettre des points sur une carte avec Matplotlib ====== Je fais une copie de [[nsi:modules:points_sur_une_carte|cette page]] en l'adaptant au cas de l'Europe. ===== Ce que l'on veut faire ===== {{ :nsi:modules:europe.png?direct&200|}} Nous souhaitons placer quelques villes : data = [ {"nom":"Paris", "lat":48.866667, "lng": 2.333333}, {"nom":"Londres", "lat":51.507222, "lng":0.1275}, {"nom":"Berlin", "lat":52.5166667, "lng":13.383} ] ===== Afficher la carte ===== Télécharger le fichier : {{ :nsi:modules:europe.png?linkonly|}} import matplotlib.pyplot as plt import matplotlib.image as mpimg img = mpimg.imread('europe.png') plt.imshow(img) plt.show() {{ :nsi:modules:europe_1.png?direct&400|}} ===== Coordonnées sur la carte ===== La carte choisie a le format 857x712. Le coin supérieur gauche a les coordonnées (0;0) et le coint inférieur droit (856;711). Rien à voir avec latitude et longitude... Nous devons créer une fonction (lng;lat) -> (x;y). {{ :nsi:modules:france_vide_points.png?direct&200|}} La carte n'est pas en projection plate, il faut faire quelques calculs. Je vous donne la fonction. def latlng_to_xy(lat,lng): xA = 770 xB = 179 lngA = 8.226100 lngB = -1.784251 a = (xA - xB) / (lngA - lngB) b = xA - a*lngA return int(a*lng + b) # on approxime à l'entier ==== Latitude vers y ==== Le principe est exactement le même. def lat_to_y(lat): yA = 190 yB = 685 latA = 48.968311 latB = 43.372928 a = (yA - yB) / (latA - latB) b = yA - a*latA return int(a*lat + b) # on approxime à l'entier ===== Placer les points ===== Il suffit de générer une liste pour les x et une autre pour les y : data = [ {"nom":"Paris", "lat":48.866667, "lng": 2.333333}, {"nom":"Marseille", "lat":43.300000, "lng":5.400000}, {"nom":"Berlin", "lat":52.520007, "lng":13.404954} ] xs = [lng_to_x(item["lng"]) for item in data] ys = [lat_to_y(item["lat"]) for item in data] plt.scatter(xs,ys) ====== Fichier final ===== {{ :nsi:modules:france_vide_2.png?direct&400|}} import matplotlib.pyplot as plt import matplotlib.image as mpimg def lng_to_x(lng): xA = 770 xB = 179 lngA = 8.226100 lngB = -1.784251 a = (xA - xB) / (lngA - lngB) b = xA - a*lngA return int(a*lng + b) # on approxime à l'entier def lat_to_y(lat): yA = 190 yB = 685 latA = 48.968311 latB = 43.372928 a = (yA - yB) / (latA - latB) b = yA - a*latA return int(a*lat + b) # on approxime à l'entier data = [ {"nom":"Paris", "lat":48.866667, "lng": 2.333333}, {"nom":"Marseille", "lat":43.300000, "lng":5.400000}, {"nom":"Berlin", "lat":52.520007, "lng":13.404954} ] xs = [lng_to_x(item["lng"]) for item in data] ys = [lat_to_y(item["lat"]) for item in data] img = mpimg.imread('france_vide.png') plt.scatter(xs,ys) plt.imshow(img) plt.show() Notez que le point de Berlin n'apparaît pas et qu'il n'a pas occasionner de modification de l'échelle. Le point de Marseille semble un peu dans la mer. Cela peut avoir deux causes : * notre réglage avec les points A et B n'est pas assez précis, * la carte utilisée est légèrement fausse. En effet, si vous regardez une carte plus détaillée, vous verrez que la côte au voisinage de Marseille est beaucoup plus compliquée que ce qui apparaît sur notre carte vide. Il est fréquent que des cartes comme celle-ci simplifient le tracé des côtes.