Files
gta6/tools/extract/tests/test_junction.py
T
knsoandClaude Sonnet 5 ee07a6bf2a fix(extract): carriageway_area() liefert immer MultiPolygon, Kreuzungstest schärfen
Zwei Befunde aus der Prüfung: unary_union() vereinte eine einzelne zusammenhängende
Kreuzung zu einem einfachen Polygon statt des zugesagten MultiPolygon (bricht an kleinen
Prüfkörpern, nicht am echten Netz mit seinen 213 Teilen - deshalb bisher unbemerkt).
Normalisiert jetzt auf MultiPolygon, mit Testzusicherung an der zusammenhängenden
kreuzung()-Fixture.

test_zwei_parallele_strassen_verschmelzen_nicht bewachte nichts: alle vier Knoten hatten
Grad 1, junction_area() lief nie. Fixture bekommt jetzt an beiden Straßen einen Querarm
(Grad 3), damit das Schließen tatsächlich ausgeführt wird, während die Straßen getrennt
bleiben.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 03:35:59 +02:00

77 lines
4.1 KiB
Python

"""Kreuzungsflächen und die Fahrbahn als Ganzes."""
from __future__ import annotations
from shapely.geometry import Point
from leonida.roads import Edge, Graph, Node
from leonida.section import FILLET, carriageway_area, junction_area
def kreuzung(klass: str = "hauptstrasse", arm: float = 60.0) -> Graph:
return Graph(
nodes=[Node((0.0, 0.0)), Node((arm, 0.0)), Node((-arm, 0.0)), Node((0.0, arm)), Node((0.0, -arm))],
edges=[Edge(0, i, [(0.0, 0.0), p], 18.0, klass)
for i, p in ((1, (arm, 0.0)), (2, (-arm, 0.0)), (3, (0.0, arm)), (4, (0.0, -arm)))])
def test_kreuzung_deckt_den_knoten_ab():
area = junction_area(kreuzung(), 0)
assert area.contains(Point(0, 0))
def test_einspringende_ecke_ist_gerundet():
area = junction_area(kreuzung(), 0)
# Ohne Rundung endete die Fläche an der Ecke (6, 6) scharf - halbe Fahrbahn in beide
# Richtungen. Mit 6 m Radius ist die einspringende Ecke ausgefüllt.
assert area.contains(Point(6.5, 6.5))
assert FILLET == 6.0
def test_zwei_parallele_strassen_verschmelzen_nicht():
# Zwei Wohnstraßen mit 10 m Abstand der Mittellinien: Fahrbahn je 7 m, dazwischen 3 m Lücke.
# Je ein Querarm macht aus jeder Straße eine echte Kreuzung (Grad 3) - ohne ihn hätte keiner
# der vier Knoten Grad >= 3, junction_area() liefe nie, und der Test bewachte nichts (siehe
# Fixbericht). Ein auf die ganze Karte statt je Knoten angewandtes Schließen würde die beiden
# Fahrbahnen trotzdem verkleben, weil ihr Abstand (3 m) unter 2 * FILLET (12 m) liegt -
# Gegenprobe dazu ebenfalls im Fixbericht.
graph = Graph(
nodes=[Node((0.0, 0.0)), Node((100.0, 0.0)), Node((50.0, 0.0)), Node((50.0, -50.0)),
Node((0.0, 10.0)), Node((100.0, 10.0)), Node((50.0, 10.0)), Node((50.0, 60.0))],
edges=[Edge(0, 2, [(0.0, 0.0), (50.0, 0.0)], 12.0, "wohnstrasse"),
Edge(2, 1, [(50.0, 0.0), (100.0, 0.0)], 12.0, "wohnstrasse"),
Edge(2, 3, [(50.0, 0.0), (50.0, -50.0)], 12.0, "wohnstrasse"),
Edge(4, 6, [(0.0, 10.0), (50.0, 10.0)], 12.0, "wohnstrasse"),
Edge(6, 5, [(50.0, 10.0), (100.0, 10.0)], 12.0, "wohnstrasse"),
Edge(6, 7, [(50.0, 10.0), (50.0, 60.0)], 12.0, "wohnstrasse")])
assert graph.degree(2) == 3 and graph.degree(6) == 3, "beide Straßen brauchen eine echte Kreuzung"
area = carriageway_area(graph)
assert len(area.geoms) == 2, "getrennte Straßen bleiben getrennt"
def test_fahrbahn_enthaelt_baender_und_kreuzung():
area = carriageway_area(kreuzung())
# Schnittstellenzusage: immer MultiPolygon, auch wenn - wie hier - eine einzelne
# zusammenhängende Kreuzung unary_union() zu einem einfachen Polygon vereint. Task 7
# iteriert über .geoms; das bricht sonst genau an kleinen, zusammenhängenden Prüfkörpern.
assert area.geom_type == "MultiPolygon"
assert area.contains(Point(0, 0)), "die Kreuzung selbst"
assert area.contains(Point(40, 0)), "ein Band"
assert not area.contains(Point(40, 40)), "die Ecke zwischen zwei Armen bleibt frei"
def test_schleife_bekommt_zwei_stummel_kein_loch_im_belag():
# Eine Schleife hängt mit beiden Enden am selben Knoten. incident() liefert sie nur einmal,
# und edge.a == node ist bei ihr immer wahr - ohne einen zweiten Stummel für die zweite
# Abgangsrichtung bliebe zwischen dem zurückgeschnittenen Schleifenband und der
# Kreuzungsfläche ein Loch. Zwei gerade Arme sorgen dafür, dass der Knoten überhaupt als
# Kreuzung (Grad >= 3) zählt.
graph = Graph(
nodes=[Node((0.0, 0.0)), Node((-100.0, 0.0)), Node((0.0, -100.0))],
edges=[Edge(0, 0, [(0.0, 0.0), (0.0, 20.0), (20.0, 20.0), (20.0, 0.0), (0.0, 0.0)], 18.0, "hauptstrasse"),
Edge(0, 1, [(0.0, 0.0), (-100.0, 0.0)], 18.0, "hauptstrasse"),
Edge(0, 2, [(0.0, 0.0), (0.0, -100.0)], 18.0, "hauptstrasse")])
area = carriageway_area(graph)
# Zwischen der Kreuzungsfläche (endet bei halber Fahrbahn = 6 m) und dem zurückgeschnittenen
# Schleifenband (beginnt beim Setback = 8 m) liegt (7, 0) - ohne den zweiten Stummel außerhalb.
assert area.contains(Point(7.0, 0.0))