parking-land/map.py

176 lines
No EOL
6.4 KiB
Python

#!/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 = '#222' # Gris pour les routes
building_color = '#CCC' # Gris pour les bâtiments
parking_color = '#555' # 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()