mirror of
https://forge.chapril.org/tykayn/parking-land
synced 2025-06-20 01:44:42 +02:00
176 lines
No EOL
6.4 KiB
Python
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() |