#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script très simplifié pour générer une carte d'une ville à partir de son ID OpenStreetMap. Utilise directement l'API Overpass et Folium pour créer une carte HTML. """ import os import sys import argparse import requests import folium import json from datetime import datetime def get_osm_data(osm_id, element_type="relation"): """ Récupère les données OpenStreetMap pour un élément donné. Args: osm_id (int): L'identifiant OpenStreetMap element_type (str): Le type d'élément ('relation', 'way', 'node') Returns: dict: Les données récupérées ou None en cas d'erreur """ print(f"Récupération des données pour {element_type}/{osm_id}...") # Construire la requête Overpass if element_type == "relation": query = f""" [out:json]; relation({osm_id}); out body; >; out skel qt; """ elif element_type == "way": query = f""" [out:json]; way({osm_id}); out body; >; out skel qt; """ elif element_type == "node": query = f""" [out:json]; node({osm_id}); out body; """ else: print(f"Type d'élément non reconnu: {element_type}") return None # Envoyer la requête à l'API Overpass try: overpass_url = "https://overpass-api.de/api/interpreter" response = requests.post(overpass_url, data={"data": query}) if response.status_code != 200: print(f"Erreur lors de la requête Overpass: {response.status_code}") return None data = response.json() if not data.get('elements'): print(f"Aucune donnée trouvée pour {element_type}/{osm_id}") return None return data except Exception as e: print(f"Erreur lors de la récupération des données: {str(e)}") return None def get_bbox_from_data(data): """ Calcule la boîte englobante à partir des données OSM. Args: data (dict): Les données OSM Returns: tuple: (min_lat, min_lon, max_lat, max_lon) ou None """ try: nodes = [e for e in data['elements'] if e.get('type') == 'node'] if not nodes: print("Aucun nœud trouvé dans les données") return None lats = [n.get('lat', 0) for n in nodes if 'lat' in n] lons = [n.get('lon', 0) for n in nodes if 'lon' in n] if not lats or not lons: print("Coordonnées manquantes dans les données") return None min_lat, max_lat = min(lats), max(lats) min_lon, max_lon = min(lons), max(lons) return (min_lat, min_lon, max_lat, max_lon) except Exception as e: print(f"Erreur lors du calcul de la boîte englobante: {str(e)}") return None def get_elements_in_bbox(bbox): """ Récupère les routes, bâtiments et parkings dans une boîte englobante. Args: bbox (tuple): (min_lat, min_lon, max_lat, max_lon) Returns: dict: Les données récupérées ou None en cas d'erreur """ print(f"Récupération des éléments dans la zone...") # Construire la requête Overpass query = f""" [out:json]; ( way[highway]({bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}); way[building]({bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}); way[amenity=parking]({bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}); ); out body; >; out skel qt; """ # Envoyer la requête à l'API Overpass try: overpass_url = "https://overpass-api.de/api/interpreter" response = requests.post(overpass_url, data={"data": query}) if response.status_code != 200: print(f"Erreur lors de la requête Overpass: {response.status_code}") return None data = response.json() if not data.get('elements'): print("Aucun élément trouvé dans la zone") return None return data except Exception as e: print(f"Erreur lors de la récupération des éléments: {str(e)}") return None def create_map(osm_id, output_path=None): """ Crée une carte pour un élément OpenStreetMap. Args: osm_id (int): L'identifiant OpenStreetMap output_path (str): Chemin où sauvegarder la carte HTML Returns: str: Chemin vers le fichier HTML généré ou None en cas d'erreur """ # Essayer d'abord en tant que relation data = get_osm_data(osm_id, "relation") element_type = "relation" # Si ça ne fonctionne pas, essayer en tant que way if not data: print("Essai en tant que chemin (way)...") data = get_osm_data(osm_id, "way") element_type = "way" # Si ça ne fonctionne toujours pas, essayer en tant que node if not data: print("Essai en tant que nœud (node)...") data = get_osm_data(osm_id, "node") element_type = "node" # Si aucune méthode ne fonctionne if not data: print(f"Impossible de récupérer les données pour l'ID OSM: {osm_id}") return None # Extraire les informations de base element_info = next((e for e in data['elements'] if e.get('id') == osm_id), None) if not element_info: print(f"Élément non trouvé dans les données") return None # Récupérer le nom name = element_info.get('tags', {}).get('name', f"Lieu_{osm_id}") print(f"Lieu identifié: {name}") # Calculer la boîte englobante bbox = get_bbox_from_data(data) if not bbox: print("Impossible de calculer la boîte englobante") return None # Récupérer les éléments dans la zone elements_data = get_elements_in_bbox(bbox) if not elements_data: print("Impossible de récupérer les éléments dans la zone") return None # Calculer le centre de la carte center_lat = (bbox[0] + bbox[2]) / 2 center_lon = (bbox[1] + bbox[3]) / 2 center = (center_lat, center_lon) # Créer la carte print("Création de la carte...") m = folium.Map(location=center, zoom_start=14, tiles='OpenStreetMap') # Ajouter un titre title_html = f'''
ID OpenStreetMap: {osm_id} (Type: {element_type})
''' m.get_root().html.add_child(folium.Element(title_html)) # Ajouter un marqueur pour le centre folium.Marker( location=center, popup=f"Centre de {name}", icon=folium.Icon(color='red', icon='info-sign') ).add_to(m) # Extraire les nœuds pour construire les géométries nodes = {n['id']: (n['lat'], n['lon']) for n in elements_data['elements'] if n['type'] == 'node'} # Compter les éléments pour les statistiques highways_count = 0 buildings_count = 0 parkings_count = 0 # Traiter les routes, bâtiments et parkings for element in elements_data['elements']: if element['type'] == 'way' and 'tags' in element: # Récupérer les coordonnées des nœuds coords = [] for node_id in element['nodes']: if node_id in nodes: coords.append(nodes[node_id]) if not coords: continue # Déterminer le type d'élément if 'highway' in element['tags']: # C'est une route highways_count += 1 folium.PolyLine( coords, color='#555555', weight=2, opacity=0.7, tooltip=element['tags'].get('name', 'Route') ).add_to(m) elif 'building' in element['tags']: # C'est un bâtiment buildings_count += 1 folium.Polygon( coords, color='#777777', fill=True, fill_color='#777777', fill_opacity=0.7, tooltip=element['tags'].get('name', 'Bâtiment') ).add_to(m) elif element['tags'].get('amenity') == 'parking': # C'est un parking parkings_count += 1 folium.Polygon( coords, color='#999999', fill=True, fill_color='#999999', fill_opacity=0.7, tooltip=element['tags'].get('name', 'Parking') ).add_to(m) # Ajouter une légende avec les statistiques legend_html = f'''Statistiques
Routes: {highways_count}
Bâtiments: {buildings_count}
Parkings: {parkings_count}