Files
gta6/tools/extract/tests/test_marking_long.py
T
knsoandClaude Sonnet 5 e92d5b5ce8 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>
2026-09-17 08:03:31 +02:00

87 lines
3.9 KiB
Python

"""Längsmarkierungen: Mittellinie, Spurtrenner, Randlinien."""
from __future__ import annotations
from collections import Counter
from leonida.roads import Edge, Graph, Node
from leonida.marking import DASH, GAP, WIDTH, longitudinal
from leonida.section import LANE, SECTION
def strecke(klass: str, length: float = 120.0) -> Graph:
return Graph(nodes=[Node((0.0, 0.0)), Node((length, 0.0))],
edges=[Edge(0, 1, [(0.0, 0.0), (length, 0.0)], SECTION[klass].corridor, klass)])
def arten(graph: Graph) -> Counter:
return Counter(art for _, art in longitudinal(graph))
def test_gasse_bekommt_keine_markierung():
assert longitudinal(strecke("gasse")) == []
def test_wohnstrasse_bekommt_eine_gestrichelte_gelbe_mitte():
zahl = arten(strecke("wohnstrasse"))
assert set(zahl) == {"gelb_gestrichelt"}
# 120 m in 12-m-Takten: zehn Striche.
assert zahl["gelb_gestrichelt"] == 10
assert DASH == 3.0 and GAP == 9.0
def test_hauptstrasse_bekommt_doppelte_mitte_und_zwei_randlinien():
zahl = arten(strecke("hauptstrasse"))
assert zahl["gelb_doppelt"] == 2, "zwei durchgezogene Linien nebeneinander"
assert zahl["weiss_rand"] == 2, "je eine an der Grenze zur Parkspur"
assert "weiss_gestrichelt" not in zahl, "zwei Spuren brauchen keinen Spurtrenner"
def test_boulevard_bekommt_zusaetzlich_spurtrenner():
zahl = arten(strecke("boulevard"))
assert zahl["gelb_doppelt"] == 2
assert zahl["weiss_rand"] == 2
assert zahl["weiss_gestrichelt"] == 20, "je Richtung ein gestrichelter Trenner, 10 Striche"
def test_randlinie_liegt_an_der_grenze_zur_parkspur():
section = SECTION["hauptstrasse"]
ränder = [poly for poly, art in longitudinal(strecke("hauptstrasse")) if art == "weiss_rand"]
abstände = sorted(round(abs(poly.centroid.y), 2) for poly in ränder)
erwartet = round(section.carriageway / 2 - section.parking, 2)
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
assert round(y1 - y0, 3) == WIDTH
assert round(x1 - x0, 3) == DASH
def test_markierung_endet_am_kreuzungsrand():
graph = Graph(nodes=[Node((0.0, 0.0)), Node((120.0, 0.0)), Node((120.0, 60.0)), Node((180.0, 0.0))],
edges=[Edge(0, 1, [(0.0, 0.0), (120.0, 0.0)], 12.0, "wohnstrasse"),
Edge(1, 2, [(120.0, 0.0), (120.0, 60.0)], 12.0, "wohnstrasse"),
Edge(1, 3, [(120.0, 0.0), (180.0, 0.0)], 12.0, "wohnstrasse")])
ende = max(poly.bounds[2] for poly, _ in longitudinal(graph) if poly.bounds[2] < 120)
assert ende < 120 - SECTION["wohnstrasse"].carriageway / 2, "vor der Kreuzung ist Schluss"