From e92d5b5ce8b8c96e98abbd2fff600d42a2c8786f Mon Sep 17 00:00:00 2001 From: Kenso Grimm Date: Thu, 17 Sep 2026 08:03:31 +0200 Subject: [PATCH] fix(extract): Kommentarfehler doppelte Mitte, Rueckgabetyp, zwei Lagetests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Kommentar zu gelb_doppelt nannte den Achsabstand (2*WIDTH = 20 cm) als "Abstand der Mitten", meinte damit aber die Luecke zwischen den gemalten Linien - die entsteht erst nach der Pufferung um je WIDTH/2 und betraegt WIDTH = 10 cm, wie vom Entwurf verlangt. Die Geometrie war immer richtig, nur der Satz dazu nicht. longitudinal() versprach list[tuple[object, str]] statt der zugesagten list[tuple[Polygon, str]] - Polygon war nicht einmal importiert. Dazu zwei Tests, die die schon richtige Lage festhalten, damit ein Kommentarfehler wie der obige naechstes Mal auffiele: gelb_doppelt liegt symmetrisch um die Achse mit 20 cm Achsabstand und 10 cm Luecke, der Boulevard-Spurtrenner liegt bei genau ±LANE. Kein TDD-Fall - beide liefen beim ersten Lauf gruen. Co-Authored-By: Claude Sonnet 5 --- tools/extract/leonida/marking.py | 9 ++++++--- tools/extract/tests/test_marking_long.py | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tools/extract/leonida/marking.py b/tools/extract/leonida/marking.py index dda1651..84d8d26 100644 --- a/tools/extract/leonida/marking.py +++ b/tools/extract/leonida/marking.py @@ -11,7 +11,7 @@ unterbringen, und aus der Nähe bleibt Geometrie scharf, wo eine Textur verwisch """ from __future__ import annotations -from shapely.geometry import LineString +from shapely.geometry import LineString, Polygon from shapely.ops import substring from .roads import Graph @@ -24,7 +24,7 @@ KINDS = ("gelb_gestrichelt", "gelb_doppelt", "weiss_gestrichelt", "weiss_rand", "haltelinie", "zebra") -def longitudinal(graph: Graph) -> list[tuple[object, str]]: +def longitudinal(graph: Graph) -> list[tuple[Polygon, str]]: """Mittellinie, Spurtrenner und Randlinien je Kante, zwischen den Kreuzungsrändern.""" out = [] for k, edge in enumerate(graph.edges): @@ -36,7 +36,10 @@ def longitudinal(graph: Graph) -> list[tuple[object, str]]: # Wohnstraße: eine gestrichelte gelbe Mitte, Überholen erlaubt. out += [(p, "gelb_gestrichelt") for p in _dashed(line, 0.0)] else: - # Doppelt durchgezogen: zwei Linien mit 10 cm Abstand der Mitten. + # Doppelt durchgezogen: Die Achsen liegen bei ±WIDTH, also 20 cm auseinander. Jede + # Linie ist WIDTH breit (Pufferung um WIDTH/2 je Seite), sodass von den 20 cm genau + # WIDTH = 10 cm als Lücke zwischen den gemalten Linien übrig bleiben - das ist der im + # Entwurf verlangte Abstand, nicht der Achsabstand selbst. out += [(_solid(line, off), "gelb_doppelt") for off in (-WIDTH, WIDTH)] rand = section.carriageway / 2 - section.parking out += [(_solid(line, off), "weiss_rand") for off in (-rand, rand)] diff --git a/tools/extract/tests/test_marking_long.py b/tools/extract/tests/test_marking_long.py index c8bc547..9662dae 100644 --- a/tools/extract/tests/test_marking_long.py +++ b/tools/extract/tests/test_marking_long.py @@ -5,7 +5,7 @@ from collections import Counter from leonida.roads import Edge, Graph, Node from leonida.marking import DASH, GAP, WIDTH, longitudinal -from leonida.section import SECTION +from leonida.section import LANE, SECTION def strecke(klass: str, length: float = 120.0) -> Graph: @@ -51,6 +51,25 @@ def test_randlinie_liegt_an_der_grenze_zur_parkspur(): assert abstände == [erwartet, erwartet] +def test_gelb_doppelt_liegt_symmetrisch_mit_zehn_zentimeter_luecke(): + # Fixrunde 1: Der Kommentar im Code verwechselte den Achsabstand (2*WIDTH = 20 cm) mit der + # Lücke zwischen den gemalten Linien (WIDTH = 10 cm, die nach der Pufferung um je WIDTH/2 + # übrig bleibt). Beide Zahlen sind richtig, aber verschieden - hier einzeln festgehalten, + # damit sie nicht wieder verwechselt werden. + unten, oben = sorted( + (poly for poly, art in longitudinal(strecke("hauptstrasse")) if art == "gelb_doppelt"), + key=lambda poly: poly.centroid.y) + assert round(unten.centroid.y, 3) == -round(oben.centroid.y, 3), "symmetrisch um die Achse" + assert round(oben.centroid.y - unten.centroid.y, 3) == 2 * WIDTH, "Achsabstand: 20 cm" + assert round(oben.bounds[1] - unten.bounds[3], 3) == WIDTH, "Lücke zwischen den Linien: 10 cm" + + +def test_spurtrenner_liegt_zwischen_den_gleichgerichteten_spuren(): + trenner = [poly for poly, art in longitudinal(strecke("boulevard")) if art == "weiss_gestrichelt"] + achsen = sorted({round(poly.centroid.y, 2) for poly in trenner}) + assert achsen == [-LANE, LANE], "je Richtung ein Trenner, an der Grenze der beiden Spuren dieser Richtung" + + def test_linien_sind_zehn_zentimeter_breit(): poly = longitudinal(strecke("wohnstrasse"))[0][0] x0, y0, x1, y1 = poly.bounds