"""Querschnitte und Fahrbahnbänder.""" from __future__ import annotations from leonida.roads import CLASS_WIDTH, Edge, Graph, Node from leonida.section import LANE, SECTION, ribbon, setback, trimmed_line def strecke(klass: str, length: float = 100.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)], CLASS_WIDTH[klass], klass)]) def test_fahrbahn_und_zwei_gehwege_ergeben_den_korridor(): for name, section in SECTION.items(): assert section.carriageway + 2 * section.walk == section.corridor, name assert section.corridor == CLASS_WIDTH[name], name def test_spuren_und_parkspuren_fuellen_die_fahrbahn(): for name, section in SECTION.items(): if name == "gasse": continue # eine Fahrgasse ohne Spureinteilung, breiter als eine Regelspur assert section.lanes * LANE + 2 * section.parking == section.carriageway, name def test_nur_die_gasse_hat_keinen_bordstein(): assert [name for name, s in SECTION.items() if not s.kerb] == ["gasse"] def test_band_ist_so_breit_wie_die_fahrbahn(): band = ribbon(strecke("hauptstrasse"), 0) x0, y0, x1, y1 = band.bounds assert round(y1 - y0, 6) == SECTION["hauptstrasse"].carriageway assert round(x1 - x0, 6) == 100.0, "freie Enden werden nicht zurückgeschnitten" def test_an_einer_kreuzung_wird_zurueckgeschnitten(): graph = Graph( nodes=[Node((0.0, 0.0)), Node((100.0, 0.0)), Node((100.0, 60.0)), Node((160.0, 0.0))], edges=[Edge(0, 1, [(0.0, 0.0), (100.0, 0.0)], 12.0, "wohnstrasse"), Edge(1, 2, [(100.0, 0.0), (100.0, 60.0)], 12.0, "wohnstrasse"), Edge(1, 3, [(100.0, 0.0), (160.0, 0.0)], 12.0, "wohnstrasse")]) assert graph.degree(1) == 3 r = setback(graph, 1) assert r == SECTION["wohnstrasse"].carriageway / 2 + 2.0 line = trimmed_line(graph, 0) assert round(line.length, 6) == round(100.0 - r, 6) assert line.coords[0] == (0.0, 0.0), "das freie Ende bleibt, nur das Kreuzungsende weicht" def test_kante_ganz_innerhalb_der_kreuzung_liefert_kein_band(): # Zwei Kreuzungen (Grad 3) nur 3 m auseinander - genau der Fall, den CONTRACT_MAX in roads.py # sonst zusammenzieht, hier aber synthetisch stehen gelassen, um trimmed_line() an diesem # Rand zu prüfen. Der Auftrag hatte hier nur ein Kreuz aus vier Knoten mit je einem Arm an # den Knoten 0 und 1 - das ergibt Grad 2, keine Kreuzung, und die Kante würde nicht # zurückgeschnitten. Erst der zweite Arm an jedem der beiden Knoten macht sie zu echten # Kreuzungen (Grad 3), deren Rückschnitt die 3 m kurze Verbindungskante ganz auffrisst. graph = Graph(nodes=[Node((0.0, 0.0)), Node((3.0, 0.0)), Node((0.0, 50.0)), Node((0.0, -50.0)), Node((3.0, 50.0)), Node((3.0, -50.0))], edges=[Edge(0, 1, [(0.0, 0.0), (3.0, 0.0)], 18.0, "hauptstrasse"), Edge(0, 2, [(0.0, 0.0), (0.0, 50.0)], 18.0, "hauptstrasse"), Edge(0, 3, [(0.0, 0.0), (0.0, -50.0)], 18.0, "hauptstrasse"), Edge(1, 4, [(3.0, 0.0), (3.0, 50.0)], 18.0, "hauptstrasse"), Edge(1, 5, [(3.0, 0.0), (3.0, -50.0)], 18.0, "hauptstrasse")]) assert graph.degree(0) == 3 and graph.degree(1) == 3 assert trimmed_line(graph, 0) is None assert ribbon(graph, 0) is None