Atlas: Deploy-Buendel vor Staustufen-Sprint
- Logistik: Musik-Player Playlist-Modus (5 Gruppen, 20 Tracks) - Heli: End-Screen auf .ggs-endscreen, Mission-Bilder, Voice-Lines, Briefing-Audio - Logistik: Layout-Tausch Auftraege+Fahrzeuge links, Karte rechts - Logistik: Tier-1-Staedte ausgebaut, Auto-Timescale-Badge - Logistik: Roadnet/Railnet Dijkstra-Routing, Balance-Updates - Atlas: 5 Atlas-Inbox-Nachrichten (Cards-Pattern, DALL-E-Key, Musik-Playlists) - Status-Updates Heli + Logistik Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Vereinfacht die OSRM-Polylines in lg-roadnet.json via Douglas-Peucker
|
||||
(~100 m Toleranz). Reduziert die Dateigroesse von ~9 MB auf ~1 MB, ohne
|
||||
dass die Kurvenfuehrung auf Europa-Zoomstufen sichtbar leidet.
|
||||
|
||||
Dazu: Berlin-Kopenhagen manuell reparieren — OSRM Auto-Profil kennt die
|
||||
Fähre Rostock-Gedser nicht und umrundet die Ostsee (1027 km). Wir setzen
|
||||
die Route auf Berlin->Rostock (Land, OSRM) + Rostock-Gedser (Fähre, direkt)
|
||||
+ Gedser->Kopenhagen (Land, OSRM), Distanz = 450 km analog Realfahrt.
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
import ssl
|
||||
import time
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
ROADNET = Path(__file__).resolve().parents[3] / "assets" / "data" / "lg-roadnet.json"
|
||||
TOLERANCE_DEG = 0.001 # ~110 m — glatt genug auf Europa-Zoom 4-8
|
||||
OSRM = "https://router.project-osrm.org/route/v1/driving/{coords}?overview=full&geometries=geojson"
|
||||
|
||||
SSL_CTX = ssl.create_default_context()
|
||||
SSL_CTX.check_hostname = False
|
||||
SSL_CTX.verify_mode = ssl.CERT_NONE
|
||||
|
||||
|
||||
def perpendicular_distance(pt, a, b):
|
||||
"""Abstand pt zu Gerade a-b (in lat/lon-Einheiten, nicht metrisch, ok fuer RDP)."""
|
||||
dx = b[0] - a[0]
|
||||
dy = b[1] - a[1]
|
||||
if dx == 0 and dy == 0:
|
||||
return math.hypot(pt[0] - a[0], pt[1] - a[1])
|
||||
t = ((pt[0] - a[0]) * dx + (pt[1] - a[1]) * dy) / (dx * dx + dy * dy)
|
||||
t = max(0.0, min(1.0, t))
|
||||
proj_x = a[0] + t * dx
|
||||
proj_y = a[1] + t * dy
|
||||
return math.hypot(pt[0] - proj_x, pt[1] - proj_y)
|
||||
|
||||
|
||||
def rdp(points, epsilon):
|
||||
"""Douglas-Peucker-Vereinfachung."""
|
||||
if len(points) < 3:
|
||||
return list(points)
|
||||
# Max-deviation Punkt finden
|
||||
max_d = 0.0
|
||||
idx = 0
|
||||
for i in range(1, len(points) - 1):
|
||||
d = perpendicular_distance(points[i], points[0], points[-1])
|
||||
if d > max_d:
|
||||
max_d = d
|
||||
idx = i
|
||||
if max_d <= epsilon:
|
||||
return [points[0], points[-1]]
|
||||
left = rdp(points[:idx + 1], epsilon)
|
||||
right = rdp(points[idx:], epsilon)
|
||||
return left[:-1] + right
|
||||
|
||||
|
||||
def fetch_route(waypoints):
|
||||
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)
|
||||
route = data["routes"][0]
|
||||
geo = route["geometry"]["coordinates"]
|
||||
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"))
|
||||
|
||||
# 1) Berlin-Kopenhagen (Faehre Rostock-Gedser) neu bauen
|
||||
print("Berlin-Kopenhagen (Faehre rekonstruieren):")
|
||||
rostock = [54.09, 12.14]
|
||||
gedser = [54.58, 11.93]
|
||||
berlin = [52.52, 13.405]
|
||||
kph = [55.6761, 12.5683]
|
||||
try:
|
||||
poly1, d1 = fetch_route([berlin, rostock])
|
||||
time.sleep(1.1)
|
||||
poly3, d3 = fetch_route([gedser, kph])
|
||||
# Faehren-Segment: gerade Linie mit zwei Zwischenpunkten fuer Animation
|
||||
poly2 = [rostock, [54.33, 12.03], gedser]
|
||||
combined = poly1 + poly2[1:] + poly3[1:]
|
||||
# Land-Strecke + Faehre-Distanz (Rostock-Gedser ca. 48 km Luftlinie ueber Ostsee)
|
||||
total_km = d1 + 48 + d3
|
||||
print(f" Berlin->Rostock {d1:.0f} km, Faehre 48 km, Gedser->KPH {d3:.0f} km = {total_km:.0f} km")
|
||||
for edge in net["edges"]:
|
||||
if edge["id"] == "berlin-kopenhagen":
|
||||
edge["polyline"] = combined
|
||||
edge["distanceKmOsrm"] = round(total_km, 1)
|
||||
break
|
||||
except Exception as e:
|
||||
print(f" FEHLER: {e} — behalte bisherige Polyline.")
|
||||
|
||||
# 2) Alle Polylines vereinfachen
|
||||
print(f"\nDouglas-Peucker mit Tolerance {TOLERANCE_DEG}° (~{int(TOLERANCE_DEG*111*1000)} m):")
|
||||
for edge in net["edges"]:
|
||||
before = len(edge.get("polyline") or [])
|
||||
if before < 3:
|
||||
continue
|
||||
simplified = rdp(edge["polyline"], TOLERANCE_DEG)
|
||||
edge["polyline"] = simplified
|
||||
after = len(simplified)
|
||||
ratio = after / before * 100
|
||||
print(f" {edge['id']}: {before} -> {after} Punkte ({ratio:.1f}%)")
|
||||
|
||||
ROADNET.write_text(
|
||||
json.dumps(net, ensure_ascii=False, separators=(",", ":"),
|
||||
indent=None),
|
||||
encoding="utf-8",
|
||||
)
|
||||
new_size = ROADNET.stat().st_size / 1024 / 1024
|
||||
print(f"\nFertig — {new_size:.2f} MB")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user