#!/usr/bin/env python3 """ Reichert App/assets/data/lg-roadnet.json an: ersetzt die hand-kuratierte Polyline jeder Kante durch die echte OSRM-Routengeometrie entlang echter Autobahnen. Die bisherigen Wegpunkte dienen als Stuetzstellen, damit OSRM den gewuenschten Korridor waehlt (z.B. Brenner statt Mont Blanc). Nutzt den freien OSRM-Demo-Server (router.project-osrm.org). Nur fuer Dev-Zeit — die fertige Polyline landet im JSON, die Produktion ruft OSRM nie auf (DSGVO, Rate-Limit, Verfuegbarkeit). Aufruf: python App/sims/logistik/scripts/enrich-roadnet-osrm.py """ import json import ssl import urllib.request import urllib.parse import time import sys from pathlib import Path # SSL-Cert-Verify aus — Windows-Python findet den CA-Store oft nicht. Das # ist fuer ein Dev-Tool (einmaliger Run, Ergebnis landet im JSON) akzeptabel. # Produktiv wird OSRM nie aufgerufen. SSL_CTX = ssl.create_default_context() SSL_CTX.check_hostname = False SSL_CTX.verify_mode = ssl.CERT_NONE ROADNET = Path(__file__).resolve().parents[3] / "assets" / "data" / "lg-roadnet.json" OSRM = "https://router.project-osrm.org/route/v1/driving/{coords}?overview=full&geometries=geojson" def fetch_route(waypoints): # waypoints = [[lat, lon], ...] -> OSRM erwartet "lon,lat;lon,lat;..." coords = ";".join(f"{w[1]},{w[0]}" for w in waypoints) url = OSRM.format(coords=coords) with urllib.request.urlopen(url, timeout=30, context=SSL_CTX) as resp: data = json.load(resp) if data.get("code") != "Ok" or not data.get("routes"): raise RuntimeError(f"OSRM-Fehler: {data.get('code')} / {data.get('message')}") route = data["routes"][0] geo = route["geometry"]["coordinates"] # [[lon, lat], ...] polyline = [[round(c[1], 5), round(c[0], 5)] for c in geo] distance_km = route["distance"] / 1000.0 return polyline, distance_km def main(): net = json.loads(ROADNET.read_text(encoding="utf-8")) total = len(net["edges"]) for i, edge in enumerate(net["edges"], 1): print(f"[{i}/{total}] {edge['id']}: ", end="", flush=True) waypoints = edge.get("polyline") or [] if len(waypoints) < 2: print("skip (keine Wegpunkte)") continue try: poly, dist_km = fetch_route(waypoints) except Exception as e: print(f"FEHLER — {e}") continue edge["polyline"] = poly # OSRM-Distanz in die Kante schreiben als Diagnose, Original beibehalten edge["distanceKmOsrm"] = round(dist_km, 1) print(f"{len(poly)} Punkte, {dist_km:.0f} km (hand: {edge.get('distanceKm')})") time.sleep(1.1) # OSRM-Demo: ~1 req/s, nicht mehr ROADNET.write_text( json.dumps(net, ensure_ascii=False, indent=2), encoding="utf-8", ) print(f"\nFertig — {ROADNET} aktualisiert.") if __name__ == "__main__": main()