#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script pour générer une carte visuelle d'une ville à partir de son ID OpenStreetMap. Les routes, parkings et bâtiments sont colorés en gris sur un fond vert. """ import os import sys import argparse import osmnx as ox import matplotlib.pyplot as plt import matplotlib.cm as cm import networkx as nx import geopandas as gpd from shapely.geometry import Point, Polygon, MultiPolygon import logging # Configuration de la journalisation logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Configuration globale d'OSMnx ox.config(use_cache=True, log_console=False) def get_city_by_osm_id(osm_id): """ Récupère les données d'une ville à partir de son ID OpenStreetMap. Args: osm_id (int): L'identifiant OpenStreetMap de la ville Returns: dict: Un dictionnaire contenant les différentes géométries de la ville """ try: logger.info(f"Récupération des données pour la ville avec l'ID OSM: {osm_id}") # Récupérer la géométrie de la ville city_boundary = ox.geocode_to_gdf(f"relation/{osm_id}") if city_boundary.empty: logger.error(f"Aucune donnée trouvée pour l'ID OSM: {osm_id}") return None # Récupérer le nom de la ville city_name = city_boundary.iloc[0].get('name', f"Ville_{osm_id}") logger.info(f"Ville identifiée: {city_name}") # Récupérer le réseau routier logger.info("Récupération du réseau routier...") road_network = ox.graph_from_polygon(city_boundary.iloc[0].geometry, network_type='drive') # Récupérer les bâtiments logger.info("Récupération des bâtiments...") buildings = ox.features_from_polygon(city_boundary.iloc[0].geometry, tags={'building': True}) # Récupérer les parkings logger.info("Récupération des parkings...") parkings = ox.features_from_polygon(city_boundary.iloc[0].geometry, tags={'amenity': 'parking'}) return { 'city_name': city_name, 'boundary': city_boundary, 'road_network': road_network, 'buildings': buildings, 'parkings': parkings } except Exception as e: logger.error(f"Erreur lors de la récupération des données: {str(e)}") return None def generate_city_map(city_data, output_path=None): """ Génère une carte visuelle de la ville avec les routes, parkings et bâtiments. Args: city_data (dict): Dictionnaire contenant les données de la ville output_path (str, optional): Chemin où sauvegarder l'image. Si None, utilise le nom de la ville. Returns: str: Chemin vers l'image générée """ if not city_data: logger.error("Aucune donnée de ville fournie pour générer la carte") return None try: city_name = city_data['city_name'] # Créer une figure de grande taille fig, ax = plt.subplots(figsize=(15, 15), dpi=300) # Définir les couleurs background_color = '#8CDD81' # Vert clair pour le fond road_color = '#555555' # Gris pour les routes building_color = '#777777' # Gris pour les bâtiments parking_color = '#999999' # Gris clair pour les parkings # Dessiner le fond (limite de la ville) city_data['boundary'].plot(ax=ax, facecolor=background_color, edgecolor='none', alpha=0.8) # Dessiner les routes if 'road_network' in city_data and city_data['road_network']: logger.info("Dessin du réseau routier...") ox.plot_graph(city_data['road_network'], ax=ax, node_size=0, edge_color=road_color, edge_linewidth=0.5, edge_alpha=0.7) # Dessiner les bâtiments if 'buildings' in city_data and not city_data['buildings'].empty: logger.info("Dessin des bâtiments...") city_data['buildings'].plot(ax=ax, facecolor=building_color, edgecolor='none', alpha=0.7) # Dessiner les parkings if 'parkings' in city_data and not city_data['parkings'].empty: logger.info("Dessin des parkings...") city_data['parkings'].plot(ax=ax, facecolor=parking_color, edgecolor='none', alpha=0.7) # Configurer les aspects visuels ax.set_title(f"Carte de {city_name}", fontsize=16) ax.set_axis_off() # Ajuster les limites de la carte plt.tight_layout() # Définir le chemin de sortie if not output_path: output_path = f"{city_name.replace(' ', '_')}_city_map.jpg" # Sauvegarder l'image logger.info(f"Sauvegarde de la carte dans: {output_path}") plt.savefig(output_path, dpi=300, bbox_inches='tight') plt.close() return output_path except Exception as e: logger.error(f"Erreur lors de la génération de la carte: {str(e)}") return None def main(): """ Fonction principale qui traite les arguments de ligne de commande et génère la carte de la ville. """ parser = argparse.ArgumentParser(description='Génère une carte visuelle d\'une ville à partir de son ID OpenStreetMap.') parser.add_argument('osm_id', type=int, help='ID OpenStreetMap de la ville') parser.add_argument('-o', '--output', type=str, help='Chemin où sauvegarder l\'image (par défaut: nom_ville_city_map.jpg)') parser.add_argument('-v', '--verbose', action='store_true', help='Afficher les messages de débogage') args = parser.parse_args() # Configurer le niveau de journalisation if args.verbose: logger.setLevel(logging.DEBUG) # Récupérer les données de la ville city_data = get_city_by_osm_id(args.osm_id) if not city_data: logger.error(f"Impossible de récupérer les données pour l'ID OSM: {args.osm_id}") sys.exit(1) # Générer la carte output_path = generate_city_map(city_data, args.output) if output_path: logger.info(f"Carte générée avec succès: {output_path}") else: logger.error("Échec de la génération de la carte") sys.exit(1) if __name__ == "__main__": main()