Befund 9: Nach dem Pipeline-Lauf mit den Befunden 3-8 geänderte Zahlen in test_committed_roads.py eingetragen (Restflächen 169 statt 171, Markierungsstücke haltelinie 1.555/zebra 14.846 statt 1.553/14.832, Flächen Gehweg 0,2987/Restflächen 0,0967 statt 0,2982/0,0972 km² - Bordstein, Fahrbahn und Kantenstücke je Klasse bleiben unverändert, weil keiner der Befunde am Graphen oder an carriageway/curb rührt) sowie den Messwerte-Absatz „Gemessen nach der Fixwelle" im Entwurf ergänzt. Beide Abnahmen erneut bestanden: zweiter Lauf ändert keine Datei, beide Suiten grün. Befund 10: Neuer Test test_markierung_liegt_nicht_wesentlich_ausserhalb_ der_fahrbahn haelt fest, wie viel Markierungsflaeche ausserhalb der Fahrbahn liegt. Rechnerisch gegen die Daten vor der Fixwelle nachgewiesen, dass er vor Befund 3 mit 452,65 m² weit über jeder sinnvollen Schranke rot gewesen waere. Die Schranke (130 m²) ist kein reiner Rundungswert: Befund 3 senkt den echten Wert auf 110,06 m² (0,25 % von 43.906 m²), behebt das Problem aber nicht vollständig - ein Bogen kann zwischen reach und reach + STOP_SETBACK + STOP_DEPTH noch einmal abknicken, was die umgesetzte Korrektur nicht auffängt. Das ist im Test-Docstring und im Fixwelle-Bericht offengelegt, nicht stillschweigend toleriert.
90 lines
4.3 KiB
Python
90 lines
4.3 KiB
Python
"""Die ausgelieferten Straßen, festgehalten (Entwurf, Abschnitt Tests: Integrationslauf).
|
|
|
|
Der Test liest die committeten Chunks, nicht den Lauf — die Kacheln liegen nicht im Repository.
|
|
Die Zahlen sind beim Neuerzeugen gemessen. Ändert sich die Extraktion absichtlich, gehören die neuen
|
|
Zahlen hierher, mit einem Satz im Commit, warum. Die Kreuzungszahl fehlt, weil die Chunks keine
|
|
Knoten tragen; sie steht in den Messwerten des Entwurfs.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
|
|
from shapely.geometry import LineString, Point, Polygon
|
|
from shapely.ops import unary_union
|
|
|
|
ROOT = Path(__file__).resolve().parents[3] / "public" / "data" / "vice-a"
|
|
|
|
|
|
def _chunks() -> list[dict]:
|
|
return [json.loads(p.read_text(encoding="utf-8")) for p in sorted(ROOT.glob("chunk_*.json"))]
|
|
|
|
|
|
def _flaeche(chunks, key) -> float:
|
|
return sum(Polygon(i["poly"][0], i["poly"][1:]).area for c in chunks for i in c.get(key, []))
|
|
|
|
|
|
def test_kantenstuecke_je_klasse():
|
|
assert dict(Counter(e["klasse"] for c in _chunks() for e in c["edges"])) == {
|
|
"boulevard": 270, "wohnstrasse": 537, "gasse": 1010, "hauptstrasse": 401,
|
|
}
|
|
|
|
|
|
def test_markierungsstuecke_je_art():
|
|
assert dict(Counter(m["art"] for c in _chunks() for m in c["markings"])) == {
|
|
"gelb_doppelt": 1216, "gelb_gestrichelt": 2370, "haltelinie": 1555,
|
|
"weiss_gestrichelt": 2066, "weiss_rand": 1219, "zebra": 14846,
|
|
}
|
|
|
|
|
|
def test_restflaechen_und_bordsteinstuecke():
|
|
chunks = _chunks()
|
|
assert sum(len(c["lots"]) for c in chunks) == 279 # „lots" aus „Stücke, je Chunk gezählt"
|
|
assert sum(len(c["curb"]) for c in chunks) == 1415 # „curb" aus „Stücke, je Chunk gezählt"
|
|
|
|
|
|
def test_flaechen_und_bordsteinlaenge():
|
|
chunks = _chunks()
|
|
assert round(_flaeche(chunks, "carriageway") / 1e6, 4) == 0.9076 # aus „Flächen km²"
|
|
assert round(_flaeche(chunks, "sidewalk") / 1e6, 4) == 0.2987
|
|
assert round(_flaeche(chunks, "lots") / 1e6, 4) == 0.0967
|
|
laenge = sum(LineString(line).length for c in chunks for line in c["curb"])
|
|
assert round(laenge / 1e3, 2) == 120.28 # aus „Bordstein km"
|
|
|
|
|
|
def test_keine_palme_auf_der_fahrbahn():
|
|
for c in _chunks():
|
|
fahrbahn = [Polygon(i["poly"][0], i["poly"][1:]) for i in c["carriageway"]]
|
|
auf = [p for p in c["palms"] if any(f.contains(Point(p)) for f in fahrbahn)]
|
|
assert auf == [], f"Chunk {c['chunk']}"
|
|
|
|
|
|
def test_markierung_liegt_nicht_wesentlich_ausserhalb_der_fahrbahn():
|
|
"""Befund 10 der Fixwelle: Vor Befund 3 lagen 452,65 m² Markierungsfläche (1,03 % von
|
|
43.906 m²) außerhalb der Fahrbahn, weil "along" in junction_marks() nur aus dem ersten
|
|
Segment einer Zufahrt kam. Rechnerisch nachgewiesen gegen die damals ausgelieferten Daten
|
|
(Commit 0ad6eee, vor dieser Fixwelle) - mit dem hier verwendeten Maß (Fläche von markings
|
|
minus der Vereinigung von carriageway, je Chunk summiert) maß dieser Befund dort 452,65 m²
|
|
und wäre an jeder Schranke unter diesem Wert rot gewesen.
|
|
|
|
Befund 3 behebt den Hauptteil davon (auf 110,06 m² = 0,25 %, siehe Fixwelle-Bericht), aber
|
|
nicht den ganzen Rest: Ein Bogen kann zwischen Streckenlänge reach und
|
|
reach + STOP_SETBACK + STOP_DEPTH noch einmal abknicken, was ein einzelner Richtungsstrahl
|
|
nicht mehr auffängt - das verlangte die vom Befund selbst genannte, größere Alternative ("die
|
|
Markierung entlang der tatsächlichen Kante aufbauen"), die diese Fixwelle nicht umsetzt. Die
|
|
Schranke hier ist deshalb *kein* reiner Rundungswert, sondern hält den mit Befund 3
|
|
erreichten, im Fixwelle-Bericht offengelegten Stand fest (mit etwas Luft nach oben) und
|
|
schlägt bei einer echten Verschlechterung an.
|
|
"""
|
|
gesamt_ausserhalb = 0.0
|
|
for c in _chunks():
|
|
fahrbahn = unary_union([Polygon(i["poly"][0], i["poly"][1:]) for i in c.get("carriageway", [])])
|
|
for m in c.get("markings", []):
|
|
poly = Polygon(m["poly"][0], m["poly"][1:])
|
|
gesamt_ausserhalb += poly.difference(fahrbahn).area if not fahrbahn.is_empty else poly.area
|
|
assert gesamt_ausserhalb < 130.0, (
|
|
f"{gesamt_ausserhalb:.2f} m² Markierungsfläche liegen außerhalb der Fahrbahn "
|
|
"(Fixwelle-Stand: 110,06 m²) - das ist mehr als der dokumentierte Rest, nicht nur Rundung"
|
|
)
|