#!/usr/bin/env python3 """ Genereer interactieve kaart voor adres analyse. Toont in één figuur: - blauw: 20 minuten autorijden (driving-car) - groen: 30 minuten fietsen (cycling-regular) """ import json import sys import urllib.parse import urllib.request import folium ORS_BASE = "http://192.168.1.71:9080/ors/v2" PDOK_BASE = "https://api.pdok.nl/bzk/locatieserver/search/v3_1" def geocode_adres(adres): params = urllib.parse.urlencode({ "q": adres, "rows": 5, "fl": "centroide_ll,weergavenaam,postcode,woonplaatsnaam,type,huisnummer", }) url = f"{PDOK_BASE}/free?{params}" with urllib.request.urlopen(url, timeout=10) as resp: data = json.loads(resp.read()) docs = data.get("response", {}).get("docs", []) if not docs: raise ValueError(f"Adres niet gevonden: {adres}") doc = next((d for d in docs if d.get("type") == "adres"), docs[0]) point = doc["centroide_ll"].replace("POINT(", "").replace(")", "").split() lon, lat = float(point[0]), float(point[1]) return { "adres": doc.get("weergavenaam", adres), "postcode": doc.get("postcode", ""), "woonplaats": doc.get("woonplaatsnaam", ""), "lat": lat, "lon": lon, } def haal_isochroon(lon, lat, profiel, minuten): payload = json.dumps({ "locations": [[lon, lat]], "range": [minuten * 60], "attributes": ["area", "reachfactor", "total_pop"], }).encode() req = urllib.request.Request( f"{ORS_BASE}/isochrones/{profiel}", data=payload, headers={"Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=60) as resp: return json.loads(resp.read()) def polygon_bounds(feature_collection): bbox = feature_collection.get("bbox", []) if len(bbox) == 4: return [[bbox[1], bbox[0]], [bbox[3], bbox[2]]] bounds = [] for feature in feature_collection.get("features", []): coords = feature.get("geometry", {}).get("coordinates", [[]])[0] bounds.extend([[lat, lon] for lon, lat in coords]) return bounds def voeg_isochroon_toe(m, iso, label, kleur, tooltip): for feature in iso.get("features", []): coords = feature["geometry"]["coordinates"][0] props = feature.get("properties", {}) area_km2 = props.get("area", 0) / 1_000_000 reach = props.get("reachfactor", 0) folium.Polygon( locations=[[lat, lon] for lon, lat in coords], color=kleur, weight=3, fill=True, fill_color=kleur, fill_opacity=0.18, popup=( f"{label}
" f"Oppervlakte: {area_km2:.1f} km²
" f"Reach factor: {reach:.3f}" ), tooltip=tooltip, ).add_to(m) def genereer_kaart(adres, output_file="/root/adres-analyse/kaart.html"): locatie = geocode_adres(adres) lat, lon = locatie["lat"], locatie["lon"] auto_iso = haal_isochroon(lon, lat, "driving-car", 20) fiets_iso = haal_isochroon(lon, lat, "cycling-regular", 30) m = folium.Map(location=[lat, lon], zoom_start=11, tiles="OpenStreetMap") folium.Marker( [lat, lon], popup=locatie["adres"], tooltip=locatie["adres"], icon=folium.Icon(color="red", icon="home"), ).add_to(m) voeg_isochroon_toe(m, auto_iso, "Auto 20 min", "#2196F3", "Bereikbaar in 20 min (auto)") voeg_isochroon_toe(m, fiets_iso, "Fiets 30 min", "#2E7D32", "Bereikbaar in 30 min (fiets)") all_bounds = polygon_bounds(auto_iso) + polygon_bounds(fiets_iso) if all_bounds: m.fit_bounds(all_bounds) title_html = f'''
📍 Adres Analyse
{locatie["adres"]}
■ 20 min autorijden
■ 30 min fietsen
''' m.get_root().html.add_child(folium.Element(title_html)) m.save(output_file) print(f"Kaart gegenereerd: {output_file}") print(f"Adres: {locatie['adres']}") print(f"Coördinaten: {lat}, {lon}") if __name__ == "__main__": adres = sys.argv[1] if len(sys.argv) > 1 else "Griendvelden 14 Best" output = sys.argv[2] if len(sys.argv) > 2 else "/root/adres-analyse/kaart.html" genereer_kaart(adres, output)