Comment trouver le bureau de poste le plus proche de chez vous à l’aide de Voronoï et Python ?

Bien entendu, cette question peut se formuler avec autre chose qu’un bureau de poste…

Si vous ne connaissez pas le pavage de Voronoï, je vous encourage à regarder ce post.

Vous pouvez aussi regarder cet article sur Wikipedia.

Comment trouver le bureau de poste le plus proche de chez vous? La méthode.

La méthode est « simple » : on répertorie toutes les coordonnées de ce que l’on cherche (ici, les bureaux de poste) et on fait notre pavage…

Facile à dire, mais concrètement ?

Récupération des coordonnées

On va s’aider de l’API OpenStreetMap.

import requests

def get_post_offices_overpass(city_name):
    query = f"""
    [out:json];
    area["name"="{city_name}"]->.searchArea;
    node["amenity"="post_office"](area.searchArea);
    out body;
    """
    url = "http://overpass-api.de/api/interpreter"
    response = requests.post(url, data={'data': query})
    data = response.json()
    post_offices = [(element['tags'].get('name', 'Post Office'), element['lat'], element['lon'])
                    for element in data['elements']]
    return post_offices

Placement sur une carte et tracé du pavage de Voronoï

On va s’aider de folium.

import folium
import numpy as np
from shapely.geometry import Polygon
from shapely.ops import unary_union
from geovoronoi import voronoi_regions_from_coords

def create_map(city_name="Bordeaux"):
    post_offices = get_post_offices_overpass(city_name)

    # Créer une carte centrée sur Bordeaux
    map_bordeaux = folium.Map(location=[44.8378, -0.5792], zoom_start=13)

    # Ajouter les bureaux de poste à la carte
    for name, lat, lng in post_offices:
        folium.Marker(location=[lat, lng], popup=name).add_to(map_bordeaux)
        
    # Convertir les coordonnées des bureaux de poste en objets Point
    coords = np.array([(lng, lat) for name, lat, lng in post_offices])

    # Définir une zone de délimitation (par exemple, les limites de Bordeaux)
    # Utiliser un polygone explicite pour Bordeaux
    boundary_coords = [(-0.8, 45.1), (0.02, 45.1), (0.02, 44.6), (-0.8, 44.6), (-0.8, 45.1)]
    boundary_polygon = Polygon(boundary_coords)

    # Calculer les régions de Voronoi à partir des coordonnées
    try:
        region_polys, region_pts = voronoi_regions_from_coords(coords, boundary_polygon)
    except RuntimeError as e:
        print(f"Erreur lors de la génération des régions de Voronoi: {e}")
        return

    # Ajouter les régions de Voronoi à la carte folium
    for region in region_polys.values():
        folium.Polygon(locations=[(lat, lng) for lng, lat in region.exterior.coords]).add_to(map_bordeaux)

    # Sauvegarder la carte dans un fichier HTML
    map_bordeaux.save('map_bordeaux.html')
    
    return None

Cela va générer une page HTML d’une carte zoomable:

Bon, là, ce n’est qu’une image car je ne peux pas insérer la page directement, mais vous voyez le genre ?

Et pour une autre ville ?

La seule chose qui diffère dans le code est le rectangle dans lequel se trouve la ville: il faudra le construire vous même (le boundary_polygon).

Pour se faire, vous pouvez ajouter l’instruction:

boundary_polygon = Polygon(boundary_coords)
print("Coords:", coords) # ligne à ajouter

tout de suite après avoir défini la variable boundary_polygon. Vous verrez ainsi où se situent les points et vous n’aurez plus qu’à modifier les coordonnées des coins du rectangle :

boundary_coords = [(xmin, ymax), (xmax, ymax), (xmax, ymin), (xmin, ymin), (xmin, ymax)]

Et pour autre chose qu’un bureau de poste?

Il faudra changer les informations de la fonction get_post_offices_overpass. Concrètement, il faudra changer « Post Office » par ce que vous voulez. Pour connaître les termes, consultez la page:

https://wiki.openstreetmap.org/wiki/FR:Key:shop

Et c’est ainsi que je m’aperçus que je faisais 1 km pour rien à chaque fois…

Catégories : Python

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
1 Commentaire
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
mathieu

cool

1
0
Nous aimerions avoir votre avis, veuillez laisser un commentaire.x