mirror of
https://forge.chapril.org/tykayn/parking-land
synced 2025-06-20 01:44:42 +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