"""Eine von Hand ergänzte Straße ins Netz einfügen, mit echten Knoten an ihren Kreuzungen.""" from __future__ import annotations from leonida.roads import Edge, Graph, Node, insert_edge def kreuz() -> Graph: """Eine 100 m lange Straße bei y = 50, von (0,50) nach (100,50).""" return Graph(nodes=[Node((0.0, 50.0)), Node((100.0, 50.0))], edges=[Edge(0, 1, [(0.0, 50.0), (100.0, 50.0)], 12.0, "wohnstrasse")]) def test_kreuzung_in_der_mitte_bekommt_einen_knoten_mit_grad_4(): out = insert_edge(kreuz(), [(50.0, 0.0), (50.0, 100.0)], 12.0, "wohnstrasse") knoten = next(k for k, n in enumerate(out.nodes) if n.point == (50.0, 50.0)) assert out.degree(knoten) == 4 assert not any(e.a == e.b for e in out.edges) def t_kreuzung() -> Graph: """Ein T bei (50,0): die Strecke (0,0)-(100,0) durchgehend, ein Ast nach Norden - Grad 3.""" return Graph(nodes=[Node((0.0, 0.0)), Node((100.0, 0.0)), Node((50.0, 0.0)), Node((50.0, 50.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")]) def test_neues_ende_haengt_sich_an_einen_knoten_mit_grad_3(): graph = t_kreuzung() assert graph.degree(2) == 3 # (54,6) liegt 7,2 m von Knoten 2 entfernt (< JUNCTION_RADIUS), aber auf keiner der drei # vorhandenen Kanten - reine Anhänge-Nähe, keine Kreuzung. out = insert_edge(graph, [(54.0, 6.0), (94.0, 46.0)], 6.0, "gasse") assert out.degree(2) == 4 assert len(out.nodes) == 5, "nur das ferne Ende der neuen Gasse ist ein neuer Knoten" def kreuz_mit_nahem_knoten() -> Graph: """kreuz(), dazu ein Sackgassenfuss 5,7 m neben der kommenden Kreuzung bei (50,50).""" return Graph(nodes=[Node((0.0, 50.0)), Node((100.0, 50.0)), Node((54.0, 54.0)), Node((54.0, 90.0))], edges=[Edge(0, 1, [(0.0, 50.0), (100.0, 50.0)], 12.0, "wohnstrasse"), Edge(2, 3, [(54.0, 54.0), (54.0, 90.0)], 6.0, "gasse")]) def test_kreuzungspunkt_nahe_einem_knoten_bekommt_keinen_zweiten(): """Regel b: ein Kreuzungspunkt im 8-m-Umkreis eines vorhandenen Knotens bekommt keinen eigenen neuen Knoten - sonst lägen zwei Knoten nur wenige Meter auseinander.""" out = insert_edge(kreuz_mit_nahem_knoten(), [(50.0, 0.0), (50.0, 100.0)], 12.0, "wohnstrasse") assert not any(n.point == (50.0, 50.0) for n in out.nodes), "kein zweiter Knoten 5,7 m daneben" assert len(out.nodes) == 6 # 4 vorhandene + 2 neue Sackgassen # Am wiederverwendeten Knoten (54,54) treffen sich jetzt der alte Sackgassenfuss (Grad 1) und # die neue Kreuzung selbst (zwei gekreuzte Straßen, je zweimal gespalten: Grad 4) - macht 5. assert out.degree(2) == 5