mirror of
https://forge.chapril.org/tykayn/parking-land
synced 2025-10-04 17:04:54 +02:00
init parking land
This commit is contained in:
commit
2399302e4e
15 changed files with 377200 additions and 0 deletions
BIN
Briis sous forges_surface_comparison_bar_chart.jpg
Normal file
BIN
Briis sous forges_surface_comparison_bar_chart.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
Limours_city_map.jpg
Normal file
BIN
Limours_city_map.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
Limours_city_map_comparison.jpg
Normal file
BIN
Limours_city_map_comparison.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
Limours_surface_comparison_bar_chart.jpg
Normal file
BIN
Limours_surface_comparison_bar_chart.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
8
README.md
Normal file
8
README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# parking land
|
||||||
|
calcul d'infos sur les nombre et les surfaces estimées sur le périmètre d'une ville selon les données OSM.
|
||||||
|
|
||||||
|
- Bâtiments
|
||||||
|
- Routes
|
||||||
|
- Parking voiture et vélo
|
||||||
|
- Pistes cyclables
|
||||||
|
- Stations de recharge pour véhicule électrique
|
386
compute.py
Normal file
386
compute.py
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
from shapely.geometry import Polygon
|
||||||
|
import argparse
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
OVERPASS_API = "https://overpass-api.de/api/interpreter"
|
||||||
|
|
||||||
|
# Configuration des arguments de ligne de commande
|
||||||
|
parser = argparse.ArgumentParser(description="Calculer les parkings et la surface d'une ville.")
|
||||||
|
parser.add_argument("--city", type=str, default="Limours", help="Nom de la ville (défaut: Limours)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
CITY_NAME = args.city
|
||||||
|
# limours: 3601176343
|
||||||
|
city_overpass_id = "3601209165"
|
||||||
|
|
||||||
|
COUNTRY_NAME = "France"
|
||||||
|
# estimations des tailles de parking en m carré selon le placement
|
||||||
|
PARKING_SIZE_ESTIMATE = {
|
||||||
|
"bike":2,
|
||||||
|
"surface": 20,
|
||||||
|
"multilevel": 25,
|
||||||
|
"underground": 30,
|
||||||
|
"pmr": 40
|
||||||
|
}
|
||||||
|
|
||||||
|
DEGREES_TO_METERS = 111312
|
||||||
|
|
||||||
|
|
||||||
|
def estimate_road_length_and_surface(city_name):
|
||||||
|
# Vérifier si le fichier JSON existe
|
||||||
|
if not os.path.exists('overpass_data.json'):
|
||||||
|
print("Le fichier overpass_data.json n'existe pas. Veuillez d'abord exécuter fetch.py.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Charger les données depuis le fichier JSON
|
||||||
|
with open('overpass_data.json', 'r') as file:
|
||||||
|
data = json.load(file)
|
||||||
|
|
||||||
|
parking_area = 0
|
||||||
|
bicycle_parking_area = 0
|
||||||
|
bicycle_parking_capacity_provided = 0
|
||||||
|
car_parking_capacity_provided = 0
|
||||||
|
charging_stations = 0
|
||||||
|
charging_points = 0
|
||||||
|
parking_with_capacity_count = 0 # Compteur pour les parkings avec capacité renseignée
|
||||||
|
road_length = 0
|
||||||
|
roundabout_count = 0
|
||||||
|
mini_roundabout_count = 0
|
||||||
|
road_cycleway_length = 0
|
||||||
|
road_surface = 0
|
||||||
|
cycleway_count = 0
|
||||||
|
building_count = 0
|
||||||
|
building_area = 0
|
||||||
|
building_sizes = [0, 10, 50, 100, 200, 500, float('inf')]
|
||||||
|
building_size_counts = [0, 0, 0, 0, 0, 0, 0]
|
||||||
|
charging_stations_with_capacity_count = 0
|
||||||
|
charging_stations_capacity_provided = 0
|
||||||
|
|
||||||
|
for element in data["elements"]:
|
||||||
|
if "tags" in element and "building" in element["tags"]:
|
||||||
|
if "geometry" in element:
|
||||||
|
polygon = Polygon([(point['lon'], point['lat']) for point in element["geometry"]])
|
||||||
|
area = polygon.area
|
||||||
|
for i, size in enumerate(building_sizes):
|
||||||
|
if area < size:
|
||||||
|
building_size_counts[i] += 1
|
||||||
|
break
|
||||||
|
print("Bâtiments de moins de 10 m²:", building_size_counts[0])
|
||||||
|
print("Bâtiments de 10 à 50 m²:", building_size_counts[1])
|
||||||
|
print("Bâtiments de 50 à 100 m²:", building_size_counts[2])
|
||||||
|
print("Bâtiments de 100 à 200 m²:", building_size_counts[3])
|
||||||
|
print("Bâtiments de 200 à 500 m²:", building_size_counts[4])
|
||||||
|
print("Bâtiments de plus de 500 m²:", building_size_counts[5])
|
||||||
|
|
||||||
|
print('éléments:', len(data["elements"]))
|
||||||
|
|
||||||
|
for element in data["elements"]:
|
||||||
|
two_points_distance = 0
|
||||||
|
element_road_length = 0
|
||||||
|
if "geometry" in element:
|
||||||
|
geometry = element["geometry"]
|
||||||
|
coordinates = geometry
|
||||||
|
if len(coordinates) > 1:
|
||||||
|
for i in range(len(coordinates) - 1):
|
||||||
|
# print(coordinates)
|
||||||
|
lon1 = coordinates[i]['lon']
|
||||||
|
lat1 = coordinates[i]['lat']
|
||||||
|
|
||||||
|
lon2 = coordinates[i + 1]['lon']
|
||||||
|
lat2 = coordinates[i + 1]['lat']
|
||||||
|
# print(lon1, lat1, lon2, lat2)
|
||||||
|
# Convertir les degrés de lat/lon en mètres
|
||||||
|
lon1_m, lat1_m = int(lon1 * DEGREES_TO_METERS), int(lat1 * DEGREES_TO_METERS)
|
||||||
|
lon2_m, lat2_m = int(lon2 * DEGREES_TO_METERS), int(lat2 * DEGREES_TO_METERS)
|
||||||
|
two_points_distance = math.sqrt((lon2_m - lon1_m)**2 + (lat2_m - lat1_m)**2)
|
||||||
|
# print(lon1_m, lat1_m, lon2_m, lat2_m)
|
||||||
|
# print('two_points_distance ', two_points_distance)
|
||||||
|
# break
|
||||||
|
|
||||||
|
element_road_length += two_points_distance
|
||||||
|
|
||||||
|
# Estimation de la surface des bâtiments
|
||||||
|
if "tags" in element and "building" in element["tags"]:
|
||||||
|
building_count += 1
|
||||||
|
if "geometry" in element:
|
||||||
|
polygon = Polygon([(point['lon'], point['lat']) for point in element["geometry"]])
|
||||||
|
building_area += polygon.area
|
||||||
|
|
||||||
|
if "tags" in element and "highway" in element["tags"] and element["tags"]["highway"] == "cycleway":
|
||||||
|
cycleway_count += 1
|
||||||
|
road_cycleway_length += two_points_distance
|
||||||
|
if "tags" in element and "highway" in element["tags"]:
|
||||||
|
if "lanes" in element["tags"]:
|
||||||
|
lane_width = 3.5 # Assuming 3.5m width per lane
|
||||||
|
road_width = int(element["tags"]["lanes"]) * lane_width * 2 # Double voie
|
||||||
|
else:
|
||||||
|
road_width = 7 # Default width for single lane roads
|
||||||
|
if element["tags"]["highway"] in ["motorway", "trunk", "primary", "secondary", "tertiary", "unclassified", "residential", "service"] and "length" in element:
|
||||||
|
road_length += element["length"]
|
||||||
|
road_surface += element["length"] * road_width
|
||||||
|
elif element["tags"]["highway"] == "roundabout":
|
||||||
|
roundabout_count += 1
|
||||||
|
road_length += math.pi * element["tags"]["circumference"]
|
||||||
|
road_surface += math.pi * element["tags"]["circumference"] * road_width
|
||||||
|
elif element["tags"]["highway"] == "mini_roundabout":
|
||||||
|
mini_roundabout_count += 1
|
||||||
|
|
||||||
|
|
||||||
|
if "tags" in element and "amenity" in element["tags"]:
|
||||||
|
if element["tags"]["amenity"] == "parking":
|
||||||
|
if "capacity" in element["tags"]:
|
||||||
|
parking_with_capacity_count += 1
|
||||||
|
# print('car parking capacity:', element["tags"]["capacity"])
|
||||||
|
car_parking_capacity_provided += int(element["tags"]["capacity"])
|
||||||
|
# Estimer la surface du parking à partir de la capacité
|
||||||
|
parking_area += PARKING_SIZE_ESTIMATE["surface"] * int(element["tags"]["capacity"])
|
||||||
|
elif "geometry" in element:
|
||||||
|
# Calculer la surface selon la forme du polygone
|
||||||
|
polygon = Polygon([(point['lon'], point['lat']) for point in element["geometry"]])
|
||||||
|
parking_area += polygon.area / 1_000_000 # Conversion en km²
|
||||||
|
elif element["tags"]["amenity"] == "bicycle_parking":
|
||||||
|
if "capacity" in element["tags"]:
|
||||||
|
parking_with_capacity_count += 1
|
||||||
|
bicycle_parking_capacity_provided += int(element["tags"]["capacity"])
|
||||||
|
bicycle_parking_area += PARKING_SIZE_ESTIMATE["bike"]
|
||||||
|
# stations de recharge
|
||||||
|
elif element["tags"]["amenity"] == "charging_station":
|
||||||
|
charging_stations += 1
|
||||||
|
if "capacity" in element["tags"]:
|
||||||
|
charging_stations_with_capacity_count += 1
|
||||||
|
charging_stations_capacity_provided += int(element["tags"]["capacity"])
|
||||||
|
elif "tags" in element and "man_mande" in element["tags"] and ["tags"]["man_mande"] == "charge_point":
|
||||||
|
charging_points += 1
|
||||||
|
# points de charge
|
||||||
|
road_length += element_road_length
|
||||||
|
road_length_km = road_length / 1000
|
||||||
|
road_surface_km2 = 3.5*2*road_length / 1000000 # Conversion de mètres carrés en kilomètres carrés
|
||||||
|
# road_surface = 3.5*2*road_length / 1000
|
||||||
|
|
||||||
|
|
||||||
|
# compter la surface des buildings
|
||||||
|
# comparer la surface des buildings par rapport à la surface totale de la ville
|
||||||
|
# -----------------
|
||||||
|
# estimer la surface prise par les parkings voiture, compter selon les capacity renseignées, et selon les surfaces des polygones geojson
|
||||||
|
# compter les places de parking par habitant
|
||||||
|
# -----------------
|
||||||
|
# infos vélo:
|
||||||
|
# estimer les km de piste cyclable
|
||||||
|
# estimer la surface prise par les parkings vélo
|
||||||
|
# compter les places de parking vélo, amenity=bicycle_parking
|
||||||
|
# compter les parking vélo par habitant
|
||||||
|
|
||||||
|
return {
|
||||||
|
"longueur_route_km": road_length_km,
|
||||||
|
"road_cycleway_km": road_cycleway_length/1000,
|
||||||
|
"compte_highways": len(data["elements"]),
|
||||||
|
"surface_route_km2": road_surface_km2,
|
||||||
|
"building_count" : building_count,
|
||||||
|
"building_area" : building_area/1000,
|
||||||
|
"building_sizes" : building_sizes,
|
||||||
|
"building_size_counts" : building_size_counts,
|
||||||
|
"compte_piste_cyclable": cycleway_count,
|
||||||
|
"car_parking_capacity_provided" : car_parking_capacity_provided,
|
||||||
|
"roundabout_count":roundabout_count,
|
||||||
|
"mini_roundabout_count":mini_roundabout_count,
|
||||||
|
"surface_parking_km2": parking_area, # Surface totale des parkings en km²
|
||||||
|
"surface_bicycle_parking_km2": bicycle_parking_area / 1_000_000, # Conversion en km²
|
||||||
|
"parking_with_capacity_count": parking_with_capacity_count, # Nombre de parkings avec capacité renseignée
|
||||||
|
"capacity_bicycle_parking_provided": bicycle_parking_capacity_provided,
|
||||||
|
"bicycle_parking_surface_from_capacity_provided_in_m2" : bicycle_parking_capacity_provided * 2,
|
||||||
|
"charging_stations" : charging_stations,
|
||||||
|
"charging_stations_with_capacity_count" : charging_stations_with_capacity_count,
|
||||||
|
"charging_stations_capacity_provided" : charging_stations_capacity_provided,
|
||||||
|
"charging_points" : charging_points,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_osm_relation_id(city_name, country_name):
|
||||||
|
# Configuration pour Nominatim
|
||||||
|
NOMINATIM_API = "https://nominatim.openstreetmap.org/search"
|
||||||
|
NOMINATIM_QUERY = f"{city_name}, {country_name}"
|
||||||
|
|
||||||
|
# Requête HTTP pour trouver l'identifiant OSM de la ville
|
||||||
|
response = requests.get(NOMINATIM_API, params={
|
||||||
|
"format": "json",
|
||||||
|
"addressdetails": 1,
|
||||||
|
"q": NOMINATIM_QUERY
|
||||||
|
}, headers={"User-Agent": "MonApplication/1.0"}) # Ajout du User-Agent
|
||||||
|
|
||||||
|
# Vérification de la réponse
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
print('résultat de recherche nominatim', len(data))
|
||||||
|
# Trouver l'identifiant OSM de la relation correspondant à la ville
|
||||||
|
for result in data:
|
||||||
|
if "osm_id" in result:
|
||||||
|
return result["osm_id"]
|
||||||
|
else:
|
||||||
|
print(f"Échec de la recherche sur Nominatim. Code d'erreur: {response.status_code}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_city_boundary(city_name, country_name):
|
||||||
|
|
||||||
|
# Requête Overpass pour obtenir les limites de la ville
|
||||||
|
overpass_query__city_bounds = f"""[out:json][timeout:25];relation["name"="{city_name}"]["admin_level"="8"];(._;>;);out geom;
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = requests.post(OVERPASS_API, data={"data": overpass_query__city_bounds}, headers={"X-Requested-With": "overpass-turbo"})
|
||||||
|
|
||||||
|
print(response.status_code)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
# print("data response: ", data)
|
||||||
|
if data["elements"]:
|
||||||
|
for element in data["elements"]:
|
||||||
|
if "bounds" in element:
|
||||||
|
# print('bounds: ', element['bounds'])
|
||||||
|
return element['bounds']
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_parking_areas(city_bounds):
|
||||||
|
overpass_query__parkings = '[out:json][timeout:25];area(id:3601176343)->.searchArea;nwr["amenity"="parking"](area.searchArea);out center;'
|
||||||
|
|
||||||
|
print('reqête pour les parkings: ', overpass_query__parkings)
|
||||||
|
|
||||||
|
response = requests.post(OVERPASS_API, data={"data": overpass_query__parkings})
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Échec de la requête Overpass. Code d'erreur: {response.status_code}")
|
||||||
|
return []
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
with open(f'parkings_results_{CITY_NAME}.json', 'w') as file:
|
||||||
|
json.dump(data, file, ensure_ascii=False, indent=4)
|
||||||
|
return data["elements"]
|
||||||
|
|
||||||
|
def estimate_parking_surface(parking_areas):
|
||||||
|
total_surface = 0
|
||||||
|
parking_count = 0
|
||||||
|
# print('parkings: ', len(parking_areas))
|
||||||
|
for area in parking_areas:
|
||||||
|
if "tags" in area and "amenity" in area["tags"] and area["tags"]["amenity"] == "parking":
|
||||||
|
if "capacity" in area["tags"]:
|
||||||
|
# print('capacité du parking: ', area["tags"]["capacity"])
|
||||||
|
parking_count += int(area["tags"]["capacity"])
|
||||||
|
else:
|
||||||
|
parking_count += 1
|
||||||
|
if "parking" in area["tags"] and area["tags"]["parking"] in PARKING_SIZE_ESTIMATE:
|
||||||
|
total_surface += PARKING_SIZE_ESTIMATE[area["tags"]["parking"]]
|
||||||
|
else:
|
||||||
|
# Utilisation d'une valeur par défaut si le type de parking n'est pas spécifié
|
||||||
|
total_surface += PARKING_SIZE_ESTIMATE["surface"]
|
||||||
|
return total_surface, parking_count
|
||||||
|
|
||||||
|
def calculate_city_surface(city_bounds):
|
||||||
|
# Conversion des coordonnées en mètres carrés sans bibliothèque
|
||||||
|
lat_diff = city_bounds["maxlat"] - city_bounds["minlat"]
|
||||||
|
lon_diff = city_bounds["maxlon"] - city_bounds["minlon"]
|
||||||
|
|
||||||
|
# Approximation de la distance en mètres
|
||||||
|
meters_per_latitude = 111_000 # 1 degré de latitude ≈ 111 km
|
||||||
|
meters_per_longitude = 111_000 * math.cos(math.radians((city_bounds["maxlat"] + city_bounds["minlat"]) / 2)) # Ajustement pour la longitude
|
||||||
|
|
||||||
|
# Calcul de la largeur et de la hauteur en mètres
|
||||||
|
width = lon_diff * meters_per_longitude
|
||||||
|
height = lat_diff * meters_per_latitude
|
||||||
|
|
||||||
|
# Calcul de la surface en mètres carrés
|
||||||
|
city_surface_m2 = width * height
|
||||||
|
print("city_surface_m2", city_surface_m2)
|
||||||
|
return city_surface_m2 # Retourne l'aire en mètres carrés
|
||||||
|
|
||||||
|
def get_population():
|
||||||
|
wiki_api_url = f"https://fr.wikipedia.org/w/api.php?action=parse&page={CITY_NAME}&format=json"
|
||||||
|
response = requests.get(wiki_api_url)
|
||||||
|
data = response.json()
|
||||||
|
nombre_habitants = None
|
||||||
|
for line in data["parse"]["text"]["*"].splitlines():
|
||||||
|
if "Habitants" in line or "Population" in line:
|
||||||
|
nombre_habitants = int(line.split(":")[1].strip().replace(" ", ""))
|
||||||
|
break
|
||||||
|
return nombre_habitants
|
||||||
|
|
||||||
|
def draw_city_map(city_name, road_surface_km2, city_surface_km2):
|
||||||
|
# Dimensions de la carte
|
||||||
|
fig, ax = plt.subplots(figsize=(8, 8))
|
||||||
|
|
||||||
|
# Calcul de la longueur du côté du carré représentant la surface des routes
|
||||||
|
road_side_length = (road_surface_km2 * 1_000_000) ** 0.5 # Conversion de km² à m²
|
||||||
|
city_side_length = (city_surface_km2) ** 0.5 # La surface de la ville est déjà en m²
|
||||||
|
|
||||||
|
# Création d'un carré représentant la surface des routes
|
||||||
|
road_square = plt.Rectangle((0, 0), road_side_length, road_side_length, color='blue', alpha=0.5, label='Surface des routes')
|
||||||
|
|
||||||
|
# Création d'un carré représentant la surface de la ville
|
||||||
|
city_square = plt.Rectangle((road_side_length, 0), city_side_length, city_side_length, color='green', alpha=0.5, label='Surface de la ville')
|
||||||
|
|
||||||
|
# Ajout des carrés à la carte
|
||||||
|
ax.add_patch(road_square)
|
||||||
|
ax.add_patch(city_square)
|
||||||
|
|
||||||
|
# Configuration de la carte
|
||||||
|
ax.set_xlim(0, max(road_side_length, city_side_length) * 1.1) # Laisser un peu d'espace
|
||||||
|
ax.set_ylim(0, max(road_side_length, city_side_length) * 1.1)
|
||||||
|
ax.set_title(f"Comparaison de la surface de {city_name} - Routes vs Ville")
|
||||||
|
ax.set_xlabel("Longitude (m)")
|
||||||
|
ax.set_ylabel("Latitude (m)")
|
||||||
|
ax.legend()
|
||||||
|
|
||||||
|
# Sauvegarde de la carte en JPG
|
||||||
|
plt.savefig(f"{city_name}_city_map_comparison.jpg", format='jpg')
|
||||||
|
# plt.show()
|
||||||
|
|
||||||
|
def draw_bar_chart(city_name, road_surface_km2, city_surface_km2):
|
||||||
|
# Données pour le diagramme
|
||||||
|
labels = ['Surface des routes (km²)', 'Surface de la ville (km²)']
|
||||||
|
values = [road_surface_km2, city_surface_km2]
|
||||||
|
|
||||||
|
# Création du diagramme en barres
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.bar(labels, values, color=['blue', 'green'], alpha=0.7)
|
||||||
|
|
||||||
|
# Configuration du diagramme
|
||||||
|
ax.set_title(f"Comparaison des surfaces à {city_name}")
|
||||||
|
ax.set_ylabel("Surface (km²)")
|
||||||
|
ax.set_ylim(0, max(values) * 1.1) # Ajuster l'axe y pour laisser un peu d'espace
|
||||||
|
|
||||||
|
# Sauvegarde du diagramme en JPG
|
||||||
|
plt.savefig(f"{city_name}_surface_comparison_bar_chart.jpg", format='jpg')
|
||||||
|
# plt.show()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
# city_bounds = get_city_boundary(CITY_NAME, COUNTRY_NAME)
|
||||||
|
# city_surface_km2 = calculate_city_surface(city_bounds) / 1_000_000 # Conversion de m² à km²
|
||||||
|
|
||||||
|
city_surface_km2 = 10.86
|
||||||
|
resultats = estimate_road_length_and_surface(CITY_NAME)
|
||||||
|
print('résultats:', resultats)
|
||||||
|
|
||||||
|
# Sauvegarder les résultats dans summary_results.json
|
||||||
|
with open('summary_results.json', 'w') as summary_file:
|
||||||
|
json.dump(resultats, summary_file, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
road_surface_km2 = resultats["surface_route_km2"]
|
||||||
|
|
||||||
|
# draw_city_map(CITY_NAME, road_surface_km2, city_surface_km2)
|
||||||
|
draw_bar_chart(CITY_NAME, road_surface_km2, city_surface_km2) # Appel de la fonction pour le diagramme en barres
|
||||||
|
|
||||||
|
|
||||||
|
print(f"**Résultats pour {CITY_NAME}, {COUNTRY_NAME}**")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
25
fetch.py
Normal file
25
fetch.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
OVERPASS_API = "https://overpass-api.de/api/interpreter"
|
||||||
|
city_overpass_id = "3601209165" # ID de la ville
|
||||||
|
|
||||||
|
def fetch_overpass_data():
|
||||||
|
# Requête Overpass pour obtenir les routes et bâtiments de la ville
|
||||||
|
overpass_query = f'''
|
||||||
|
[out:json][timeout:25];area(id:{city_overpass_id})->.searchArea;(way["building"](area.searchArea);nwr["amenity"="bicycle_parking"](area.searchArea);nwr["amenity"="charging_station"](area.searchArea);nwr["man_made"="charge_point"](area.searchArea);nwr["amenity"="parking"](area.searchArea);way["highway"]["highway"~"residential|primary|secondary|tertiary|service|footway|unclassified|cycleway|roundabout|mini_roundabout"](area.searchArea););out geom;
|
||||||
|
'''
|
||||||
|
|
||||||
|
response = requests.post(OVERPASS_API, data={"data": overpass_query}, headers={"X-Requested-With": "overpass-turbo"})
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
with open('overpass_data.json', 'w') as file:
|
||||||
|
json.dump(data, file, ensure_ascii=False, indent=4)
|
||||||
|
print("Données Overpass récupérées et sauvegardées dans overpass_data.json")
|
||||||
|
else:
|
||||||
|
print(f"Échec de la requête Overpass. Code d'erreur: {response.status_code}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fetch_overpass_data()
|
185900
highway_results.json
Normal file
185900
highway_results.json
Normal file
File diff suppressed because it is too large
Load diff
185981
overpass_data.json
Normal file
185981
overpass_data.json
Normal file
File diff suppressed because it is too large
Load diff
1920
parkings_results.json
Normal file
1920
parkings_results.json
Normal file
File diff suppressed because it is too large
Load diff
38
present.py
Normal file
38
present.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import json
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
def generate_html_from_json(json_file, output_html):
|
||||||
|
with open(json_file, 'r') as file:
|
||||||
|
data = json.load(file)
|
||||||
|
|
||||||
|
# Configuration de Jinja2
|
||||||
|
env = Environment(loader=FileSystemLoader('.'))
|
||||||
|
template = env.get_template('template.html')
|
||||||
|
|
||||||
|
# Rendu du template avec les données
|
||||||
|
html_content = template.render(
|
||||||
|
city_name=data.get("city_name", "la ville"),
|
||||||
|
longueur_route_km=data["longueur_route_km"],
|
||||||
|
road_cycleway_km=data["road_cycleway_km"],
|
||||||
|
compte_highways=data["compte_highways"],
|
||||||
|
surface_route_km2=data["surface_route_km2"],
|
||||||
|
compte_piste_cyclable=data["compte_piste_cyclable"],
|
||||||
|
roundabout_count=data["roundabout_count"],
|
||||||
|
mini_roundabout_count=data["mini_roundabout_count"],
|
||||||
|
building_count=data["building_count"],
|
||||||
|
building_area=data["building_area"],
|
||||||
|
surface_parking_km2=data["surface_parking_km2"],
|
||||||
|
surface_bicycle_parking_km2=data["surface_bicycle_parking_km2"],
|
||||||
|
car_parking_capacity_provided=data["car_parking_capacity_provided"],
|
||||||
|
building_size_counts=data["building_size_counts"],
|
||||||
|
charging_stations=data["charging_stations"],
|
||||||
|
charging_stations_with_capacity_count=data["charging_stations_with_capacity_count"],
|
||||||
|
charging_stations_capacity_provided=data["charging_stations_capacity_provided"],
|
||||||
|
charging_points=data["charging_points"]
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(output_html, 'w') as html_file:
|
||||||
|
html_file.write(html_content)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_html_from_json('summary_results.json', 'summary_results.html')
|
139
summary_results.html
Normal file
139
summary_results.html
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Résumé des résultats</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-of-type(2) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
table {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Résumé des résultats pour la ville</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Mesure</th>
|
||||||
|
<th>Valeur</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Longueur de route (km) 🛣️</td>
|
||||||
|
<td>228.31</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Longueur de piste cyclable (km) 🚴♂️</td>
|
||||||
|
<td>0.03</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de routes 🚗</td>
|
||||||
|
<td>3526</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des routes (km²) 🌍</td>
|
||||||
|
<td>1.60</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de pistes cyclables 🚲</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de ronds-points ⭕</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de mini ronds-points 🔵</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des parkings (km²) 🅿️</td>
|
||||||
|
<td>9820.00</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des parkings à vélos (km²) 🚲🅿️</td>
|
||||||
|
<td>0.00</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de parkings avec capacité renseignée 🚗💼</td>
|
||||||
|
<td>491</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments 🏢</td>
|
||||||
|
<td>2515</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Aire des bâtiments (m²) 📏</td>
|
||||||
|
<td>0.00</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de moins de 10 m² 🏠</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 10 à 50 m² 🏡</td>
|
||||||
|
<td>2515</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 50 à 100 m² 🏢</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 100 à 200 m² 🏬</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 200 à 500 m² 🏣</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de plus de 500 m² 🏛️</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de stations de recharge ⚡</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de stations de recharge avec capacité renseignée ⚡💼</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Capacité totale des stations de recharge ⚡📦</td>
|
||||||
|
<td>7</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de points de charge 🔌</td>
|
||||||
|
<td>0</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
39
summary_results.json
Normal file
39
summary_results.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"longueur_route_km": 228.30878348424707,
|
||||||
|
"road_cycleway_km": 0.027059960352724084,
|
||||||
|
"compte_highways": 3526,
|
||||||
|
"surface_route_km2": 1.5981614843897296,
|
||||||
|
"building_count": 2515,
|
||||||
|
"building_area": 2.6535844764989233e-08,
|
||||||
|
"building_sizes": [
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
50,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
500,
|
||||||
|
Infinity
|
||||||
|
],
|
||||||
|
"building_size_counts": [
|
||||||
|
0,
|
||||||
|
2515,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"compte_piste_cyclable": 4,
|
||||||
|
"car_parking_capacity_provided": 491,
|
||||||
|
"roundabout_count": 0,
|
||||||
|
"mini_roundabout_count": 0,
|
||||||
|
"surface_parking_km2": 9820.0,
|
||||||
|
"surface_bicycle_parking_km2": 3.6e-05,
|
||||||
|
"parking_with_capacity_count": 41,
|
||||||
|
"capacity_bicycle_parking_provided": 115,
|
||||||
|
"bicycle_parking_surface_from_capacity_provided_in_m2": 230,
|
||||||
|
"charging_stations": 4,
|
||||||
|
"charging_stations_with_capacity_count": 4,
|
||||||
|
"charging_stations_capacity_provided": 7,
|
||||||
|
"charging_points": 0
|
||||||
|
}
|
139
template.html
Normal file
139
template.html
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Résumé des résultats</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-of-type(2) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
table {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Résumé des résultats pour {{ city_name }}</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Mesure</th>
|
||||||
|
<th>Valeur</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Longueur de route (km) 🛣️</td>
|
||||||
|
<td>{{ "%.2f"|format(longueur_route_km) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Longueur de piste cyclable (km) 🚴♂️</td>
|
||||||
|
<td>{{ "%.2f"|format(road_cycleway_km) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de routes 🚗</td>
|
||||||
|
<td>{{ compte_highways }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des routes (km²) 🌍</td>
|
||||||
|
<td>{{ "%.2f"|format(surface_route_km2) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de pistes cyclables 🚲</td>
|
||||||
|
<td>{{ compte_piste_cyclable }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de ronds-points ⭕</td>
|
||||||
|
<td>{{ roundabout_count }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de mini ronds-points 🔵</td>
|
||||||
|
<td>{{ mini_roundabout_count }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des parkings (km²) 🅿️</td>
|
||||||
|
<td>{{ "%.2f"|format(surface_parking_km2) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Surface des parkings à vélos (km²) 🚲🅿️</td>
|
||||||
|
<td>{{ "%.2f"|format(surface_bicycle_parking_km2) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de parkings avec capacité renseignée 🚗💼</td>
|
||||||
|
<td>{{ car_parking_capacity_provided }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments 🏢</td>
|
||||||
|
<td>{{ building_count }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Aire des bâtiments (m²) 📏</td>
|
||||||
|
<td>{{ "%.2f"|format(building_area) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de moins de 10 m² 🏠</td>
|
||||||
|
<td>{{ building_size_counts[0] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 10 à 50 m² 🏡</td>
|
||||||
|
<td>{{ building_size_counts[1] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 50 à 100 m² 🏢</td>
|
||||||
|
<td>{{ building_size_counts[2] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 100 à 200 m² 🏬</td>
|
||||||
|
<td>{{ building_size_counts[3] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de 200 à 500 m² 🏣</td>
|
||||||
|
<td>{{ building_size_counts[4] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de bâtiments de plus de 500 m² 🏛️</td>
|
||||||
|
<td>{{ building_size_counts[5] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de stations de recharge ⚡</td>
|
||||||
|
<td>{{ charging_stations }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de stations de recharge avec capacité renseignée ⚡💼</td>
|
||||||
|
<td>{{ charging_stations_with_capacity_count }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Capacité totale des stations de recharge ⚡📦</td>
|
||||||
|
<td>{{ charging_stations_capacity_provided }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Nombre de points de charge 🔌</td>
|
||||||
|
<td>{{ charging_points }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
2625
ville.json
Normal file
2625
ville.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue