fix(extract): Kommentarfehler doppelte Mitte, Rueckgabetyp, zwei Lagetests

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 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Sonnet 5 committed 2026-09-17 08:03:31 +02:00
1 parent c0cc32f3f3
commit e92d5b5ce8
2 files changed
+26 -4

No files matched your search

+6 -3
View File
@@ -11,7 +11,7 @@ unterbringen, und aus der Nähe bleibt Geometrie scharf, wo eine Textur verwisch
""" """
from __future__ import annotations from __future__ import annotations
from shapely.geometry import LineString from shapely.geometry import LineString, Polygon
from shapely.ops import substring from shapely.ops import substring
from .roads import Graph from .roads import Graph
@@ -24,7 +24,7 @@ KINDS = ("gelb_gestrichelt", "gelb_doppelt", "weiss_gestrichelt", "weiss_rand",
"haltelinie", "zebra") "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.""" """Mittellinie, Spurtrenner und Randlinien je Kante, zwischen den Kreuzungsrändern."""
out = [] out = []
for k, edge in enumerate(graph.edges): 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. # Wohnstraße: eine gestrichelte gelbe Mitte, Überholen erlaubt.
out += [(p, "gelb_gestrichelt") for p in _dashed(line, 0.0)] out += [(p, "gelb_gestrichelt") for p in _dashed(line, 0.0)]
else: 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)] out += [(_solid(line, off), "gelb_doppelt") for off in (-WIDTH, WIDTH)]
rand = section.carriageway / 2 - section.parking rand = section.carriageway / 2 - section.parking
out += [(_solid(line, off), "weiss_rand") for off in (-rand, rand)] out += [(_solid(line, off), "weiss_rand") for off in (-rand, rand)]
+20 -1
View File
@@ -5,7 +5,7 @@ from collections import Counter
from leonida.roads import Edge, Graph, Node from leonida.roads import Edge, Graph, Node
from leonida.marking import DASH, GAP, WIDTH, longitudinal 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: 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] 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(): def test_linien_sind_zehn_zentimeter_breit():
poly = longitudinal(strecke("wohnstrasse"))[0][0] poly = longitudinal(strecke("wohnstrasse"))[0][0]
x0, y0, x1, y1 = poly.bounds x0, y0, x1, y1 = poly.bounds