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:
2026-04-26 01:05:13 +02:00
parent f811437a35
commit 79ac9dad84
773 changed files with 17482 additions and 541 deletions
@@ -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()