run.py baut jetzt aus dem Straßengraphen (Tasks 3-11) statt aus den nachgezeichneten Straßenrändern: Fahrbahn, Bordstein, Gehweg und Restflächen aus build_street(), amerikanische Markierungen aus markings(). fit_to_carriageway() bringt Bodenplatte und Beläge auf dasselbe Loch wie die Fahrbahn und hält Palmen dabei von ihr fern - nach derselben Regel, mit der apply_street() sie schon von der Jefferson Avenue fernhält. split_by_chunk_all() bekommt dafür eine parametrisierbare Splittergrenze: Ein Strich der gestrichelten Linien ist 3 m x 10 cm = 0,3 m² und wäre an der bisherigen 0,5-m²-Grenze für Flächen verschwunden. Markierungen laufen deshalb über den neuen Helfer chunk_markings() mit eigener, kleinerer Grenze; alle anderen Aufrufer bleiben bei 0,5 m². Am echten Netz gemessen: 1.537 Knoten, 1.790 Kanten, 830 Bordsteinstücke, 171 Restflächen, 22.394 Markierungen, 56 Palmen an der Fahrbahn entfernt. Fahrbahn-, Gehweg- und Restflächen sowie die Bordsteinlänge treffen die vorab am echten Netz gemessenen Erwartungswerte auf 0,03-0,3 % genau. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
74 lines
3.6 KiB
Python
74 lines
3.6 KiB
Python
"""Die Reihenfolge, in der die Straßen entstehen — ohne den vollen Lauf."""
|
||
from __future__ import annotations
|
||
|
||
from shapely.geometry import box
|
||
from shapely.ops import unary_union
|
||
|
||
from leonida.emit import chunk_box_of
|
||
from leonida.park import World
|
||
from leonida.roads import Edge, Graph, Node
|
||
from leonida.street import build_street, punch
|
||
from run import chunk_markings, fit_to_carriageway
|
||
|
||
|
||
def _gerade_wohnstrasse():
|
||
"""100 m Wohnstraße entlang y = 0: Fahrbahn 7 m breit, also von y = -3,5 bis 3,5."""
|
||
graph = Graph(nodes=[Node((0.0, 0.0)), Node((100.0, 0.0))],
|
||
edges=[Edge(0, 1, [(0.0, 0.0), (100.0, 0.0)], 12.0, "wohnstrasse")])
|
||
return graph, build_street(graph, box(0, -6, 100, 6), bridges=[])
|
||
|
||
|
||
def _welt(graph, *, surfaces=(), palms=()):
|
||
return World(land=[box(-20, -50, 120, 50)], surfaces=list(surfaces), roads=[], graph=graph,
|
||
buildings=[], palms=list(palms))
|
||
|
||
|
||
def test_boden_und_belag_bekommen_dasselbe_loch():
|
||
"""Vergisst run.py eine der beiden Schichten, liegt dort ein Belag über der Mulde oder die
|
||
Bodenplatte schließt sie."""
|
||
graph, street = _gerade_wohnstrasse()
|
||
platte = box(-20, -50, 120, 50)
|
||
welt = _welt(graph, surfaces=[(box(-20, -50, 50, 50), "urban"), (box(50, -50, 120, 50), "park")])
|
||
out = fit_to_carriageway(welt, street.carriageway)
|
||
boden = unary_union(out.land)
|
||
assert boden.intersection(street.carriageway).area < 0.01, "die Fahrbahn liegt im Loch"
|
||
loch = street.carriageway.intersection(platte).area
|
||
assert abs(platte.area - boden.area - loch) < 0.01, "das Loch ist nicht größer als die Fahrbahn"
|
||
for kind in ("urban", "park"):
|
||
belag = unary_union([poly for poly, k in out.surfaces if k == kind])
|
||
assert belag.intersection(street.carriageway).area < 0.01, f"kein Belag {kind} über der Mulde"
|
||
assert abs(unary_union([poly for poly, _ in out.surfaces]).area - boden.area) < 0.01, "dasselbe Loch"
|
||
|
||
|
||
def test_gehweg_liegt_nicht_im_loch():
|
||
graph, street = _gerade_wohnstrasse()
|
||
land = unary_union(punch([box(-20, -50, 120, 50)], street.carriageway))
|
||
assert street.sidewalk.difference(land).area < 0.5, "der Gehweg liegt auf der Bodenplatte"
|
||
|
||
|
||
def test_keine_palme_auf_oder_dicht_an_der_fahrbahn():
|
||
"""Entwurf, Ablauf Schritt 7: Palmen werden nach dem Straßenbau neu gesetzt. Am echten Netz
|
||
standen ohne diesen Schritt 24 Palmen auf der Fahrbahn und 32 weitere näher als PALM_KERB."""
|
||
graph, street = _gerade_wohnstrasse()
|
||
welt = _welt(graph, palms=[(50.0, 0.0), (50.0, 4.5), (50.0, 5.5)])
|
||
out = fit_to_carriageway(welt, street.carriageway)
|
||
assert out.palms == [(50.0, 5.5)], "auf der Fahrbahn und 1 m daneben weg, 2 m daneben bleibt"
|
||
|
||
|
||
def test_striche_ueberleben_den_zuschnitt():
|
||
"""Ein Strich der gestrichelten Mitte ist 3 m × 10 cm = 0,3 m². Mit der Splittergrenze der
|
||
Flächen (0,5 m²) fiel am echten Netz jeder einzelne der 4.363 Striche weg."""
|
||
zelle = chunk_box_of(0, 0)
|
||
x, y = zelle.centroid.x, zelle.centroid.y
|
||
stuecke = chunk_markings([(box(x, y, x + 3.0, y + 0.1), "gelb_gestrichelt")], 0, 0)
|
||
assert [art for _, art in stuecke] == ["gelb_gestrichelt"]
|
||
assert abs(stuecke[0][0].area - 0.3) < 1e-6
|
||
|
||
|
||
def test_strich_ueber_der_chunkgrenze_wird_geteilt_nicht_verworfen():
|
||
zelle = chunk_box_of(0, 0)
|
||
grenze, y = zelle.bounds[2], zelle.centroid.y # rechte Kante von Chunk (0, 0)
|
||
strich = [(box(grenze - 1.0, y, grenze + 2.0, y + 0.1), "weiss_gestrichelt")]
|
||
assert [round(poly.area, 6) for poly, _ in chunk_markings(strich, 0, 0)] == [0.1]
|
||
assert [round(poly.area, 6) for poly, _ in chunk_markings(strich, 1, 0)] == [0.2]
|