feat(extract): Chunk-Format für Fahrbahn, Bordstein, Gehweg und Markierung
chunk_payload() liefert jetzt carriageway, curb, sidewalk, markings, lots, bridges und edges statt roads und centerlines - die Ausgabe fuer Task 12 (Pipeline) und Task 13/14 (Zeichnen). curb ist ein Linienzug: Bordstein hat keine eigene Flaeche, Loch und Fahrbahn teilen sich den Umriss. _line() normalisiert die Laufrichtung wie _rings() die Wicklung - anders als bei den alten centerlines duerfen curb und edges das, weil die Laternen ihre Seite seit Teil 2 aus Kantenrichtung und Gehwegpruefung waehlen, nicht mehr aus der Listenposition. Selbstpruefung zur Lauf-Stabilitaet ging ueber die zwei mitgelieferten Tests hinaus, die bridges und edges nur leer durchreichen. Ad-hoc nachgerechnet und dabei eine Luecke gefunden: Der Sortierschluessel von edges deckte nur (line, klasse) ab, nicht auch breite und fahrbahn wie bei buildings ueblich (dort alle vier Felder). Bei gleichem line+klasse, aber unterschiedlicher breite/fahrbahn, waere die Ausgabe wieder an der Listenposition haengengeblieben - in der echten Pipeline legt SECTION[klasse] beide Werte fest und kann so nicht divergieren, der Schluessel deckt jetzt trotzdem alle vier Felder ab, wie bei buildings. test_centerlines_keep_their_order_and_direction geht weg: Sie bewies die jetzt bewusst umgekehrte Zusicherung (Reihenfolge und Richtung tragen Bedeutung); centerlines selbst entfaellt. Die zwei neuen Tests aus dem Auftrag belegen das Gegenteil fuer die Nachfolgefelder. Bricht wie angekuendigt run.py (ruft chunk_payload noch mit roads=/centerlines= auf) - das repariert Task 11/12. Anders als im Auftrag angenommen bleibt die Testsuite komplett gruen (248/248): test_park_apply.py und test_park_street.py haengen an park.py's eigenem World, nicht an chunk_payload, und kein anderer Test importiert emit.py. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4bf670e0d0
commit
bdc6a0ffe5
2 files changed
+81
-41
No files matched your search
@@ -1,4 +1,4 @@
|
||||
from shapely.geometry import LineString, Polygon
|
||||
from shapely.geometry import Polygon
|
||||
from leonida.emit import chunk_payload, split_by_chunk, split_by_chunk_all
|
||||
|
||||
BIG = Polygon([(-1000, 2500), (-700, 2500), (-700, 2200), (-1000, 2200)]) # Chunk (0,0) und Nachbarn
|
||||
@@ -13,20 +13,24 @@ def test_coordinates_are_chunk_local_three_js():
|
||||
# chunk_payload() nimmt (wie in run.py) bereits chunk-geschnittene Geometrie entgegen;
|
||||
# BIG selbst überspannt vier Chunks (siehe Test oben), darum hier zuerst zuschneiden.
|
||||
clipped = split_by_chunk(BIG)[(0, 0)]
|
||||
payload = chunk_payload(0, 0, land=[clipped], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[])
|
||||
payload = chunk_payload(0, 0, land=[clipped], surfaces=[], carriageway=[], curb=[], sidewalk=[],
|
||||
markings=[], lots=[], bridges=[], edges=[], buildings=[], palms=[])
|
||||
ring = payload["land"][0][0] # Ruling 34: [0] ist jetzt der Aussenring
|
||||
assert payload["origin"] == [-1000, -2500] # three-z = -Y
|
||||
assert min(x for x, _ in ring) >= -0.01
|
||||
assert max(x for x, _ in ring) <= 250.01
|
||||
|
||||
def test_payload_matches_schema():
|
||||
payload = chunk_payload(2, 3, land=[], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[])
|
||||
assert set(payload) == {"chunk", "origin", "land", "surfaces", "roads", "centerlines", "buildings", "palms", "paths"}
|
||||
payload = chunk_payload(2, 3, land=[], surfaces=[], carriageway=[], curb=[], sidewalk=[], markings=[],
|
||||
lots=[], bridges=[], edges=[], buildings=[], palms=[])
|
||||
assert set(payload) == {"chunk", "origin", "land", "surfaces", "carriageway", "curb", "sidewalk",
|
||||
"markings", "lots", "bridges", "edges", "buildings", "palms", "paths"}
|
||||
assert payload["chunk"] == [2, 3]
|
||||
|
||||
def test_paths_are_chunk_local_rings_like_roads():
|
||||
path = Polygon([(-990, 2490), (-980, 2490), (-980, 2480), (-990, 2480)])
|
||||
payload = chunk_payload(0, 0, land=[], surfaces=[], roads=[], centerlines=[], buildings=[], palms=[], paths=[path])
|
||||
payload = chunk_payload(0, 0, land=[], surfaces=[], carriageway=[], curb=[], sidewalk=[], markings=[],
|
||||
lots=[], bridges=[], edges=[], buildings=[], palms=[], paths=[path])
|
||||
(entry,) = payload["paths"]
|
||||
assert set(entry) == {"poly"}
|
||||
ring = entry["poly"][0]
|
||||
@@ -38,8 +42,8 @@ def test_polygon_holes_survive_into_the_payload():
|
||||
gehen sonst 449.876 m2 Strassenloch und 208.657 m2 Stadtloch verloren."""
|
||||
outer = Polygon([(-1000, 2250), (-800, 2250), (-800, 2450), (-1000, 2450)],
|
||||
[[(-950, 2300), (-870, 2300), (-870, 2400), (-950, 2400)]])
|
||||
payload = chunk_payload(0, 0, land=[outer], surfaces=[], roads=[], centerlines=[],
|
||||
buildings=[], palms=[])
|
||||
payload = chunk_payload(0, 0, land=[outer], surfaces=[], carriageway=[], curb=[], sidewalk=[],
|
||||
markings=[], lots=[], bridges=[], edges=[], buildings=[], palms=[])
|
||||
assert len(payload["land"]) == 1
|
||||
rings = payload["land"][0]
|
||||
assert len(rings) == 2 # Aussenring und Loch
|
||||
@@ -63,11 +67,13 @@ def test_the_same_geometry_in_another_order_gives_the_same_output():
|
||||
a_gedreht = Polygon([(-980, 2480), (-980, 2490), (-990, 2490), (-990, 2480)])
|
||||
assert a.equals(a_gedreht) and list(a.exterior.coords) != list(a_gedreht.exterior.coords)
|
||||
erste = chunk_payload(0, 0, land=[a, b], surfaces=[(a, "urban"), (b, "urban")],
|
||||
roads=[(a, False), (b, True)], centerlines=[],
|
||||
carriageway=[(a, "wohnstrasse"), (b, "wohnstrasse")], curb=[], sidewalk=[],
|
||||
markings=[], lots=[], bridges=[b], edges=[],
|
||||
buildings=[(a, HEIGHT, False), (b, HEIGHT, True)],
|
||||
palms=[(-990.0, 2490.0), (-960.0, 2460.0)], paths=[a, b])
|
||||
zweite = chunk_payload(0, 0, land=[b, a_gedreht], surfaces=[(b, "urban"), (a_gedreht, "urban")],
|
||||
roads=[(b, True), (a_gedreht, False)], centerlines=[],
|
||||
carriageway=[(b, "wohnstrasse"), (a_gedreht, "wohnstrasse")], curb=[], sidewalk=[],
|
||||
markings=[], lots=[], bridges=[b], edges=[],
|
||||
buildings=[(b, HEIGHT, True), (a_gedreht, HEIGHT, False)],
|
||||
palms=[(-960.0, 2460.0), (-990.0, 2490.0)], paths=[b, a_gedreht])
|
||||
assert erste == zweite
|
||||
@@ -80,25 +86,12 @@ def test_surfaces_keep_the_order_of_their_kinds():
|
||||
Rasen sie auf map.png wieder zu (19.573 m2 Feld allein im Flamingo Park)."""
|
||||
rasen = Polygon([(-1000, 2500), (-900, 2500), (-900, 2400), (-1000, 2400)])
|
||||
feld = Polygon([(-980, 2480), (-940, 2480), (-940, 2440), (-980, 2440)])
|
||||
payload = chunk_payload(0, 0, land=[], surfaces=[(rasen, "park"), (feld, "field")], roads=[],
|
||||
centerlines=[], buildings=[], palms=[])
|
||||
payload = chunk_payload(0, 0, land=[], surfaces=[(rasen, "park"), (feld, "field")],
|
||||
carriageway=[], curb=[], sidewalk=[], markings=[], lots=[], bridges=[],
|
||||
edges=[], buildings=[], palms=[])
|
||||
assert [s["kind"] for s in payload["surfaces"]] == ["park", "field"]
|
||||
|
||||
|
||||
def test_centerlines_keep_their_order_and_direction():
|
||||
"""Die zweite Gegenprobe: Mittellinien werden bewusst nicht sortiert und nicht normalisiert.
|
||||
|
||||
vergeLampPoints() in src/world/props.js setzt jede Laterne abwechselnd links und rechts der
|
||||
Fahrbahn (gerader Index links, ungerader rechts) und dreht sie in Laufrichtung der Linie.
|
||||
Sortieren verschob an den ausgelieferten Chunks 1.848 von 3.921 Laternen auf die andere
|
||||
Strassenseite; normalize() wuerde zusaetzlich jede zweite Linie umdrehen."""
|
||||
spaet = LineString([(-900, 2400), (-950, 2400)])
|
||||
frueh = LineString([(-990, 2490), (-960, 2490)])
|
||||
payload = chunk_payload(0, 0, land=[], surfaces=[], roads=[], centerlines=[spaet, frueh],
|
||||
buildings=[], palms=[])
|
||||
assert payload["centerlines"] == [[[100, 100], [50, 100]], [[10, 10], [40, 10]]]
|
||||
|
||||
|
||||
def test_split_by_chunk_all_yields_polygons_for_a_multi_part_intersection():
|
||||
"""split_by_chunk_all() ist die Variante, die run.py tatsaechlich benutzt (nicht
|
||||
split_by_chunk), und hat einen MultiPolygon-Zweig, den kein anderer Test trifft: ein
|
||||
@@ -112,3 +105,37 @@ def test_split_by_chunk_all_yields_polygons_for_a_multi_part_intersection():
|
||||
parts = list(split_by_chunk_all([staple], 0, 0))
|
||||
assert len(parts) == 2
|
||||
assert all(p.geom_type == "Polygon" for p in parts)
|
||||
|
||||
|
||||
def test_neue_schichten_stehen_im_chunk():
|
||||
from shapely.geometry import LineString, box
|
||||
payload = chunk_payload(
|
||||
0, 0,
|
||||
land=[box(0, 2400, 100, 2500)], surfaces=[],
|
||||
carriageway=[(box(10, 2400, 20, 2500), "wohnstrasse")],
|
||||
curb=[LineString([(10, 2400), (10, 2500)])],
|
||||
sidewalk=[box(20, 2400, 23, 2500)],
|
||||
markings=[(box(14, 2440, 16, 2443), "gelb_gestrichelt")],
|
||||
lots=[box(40, 2400, 60, 2420)],
|
||||
bridges=[], edges=[(LineString([(15, 2400), (15, 2500)]), "wohnstrasse", 12.0, 7.0)],
|
||||
buildings=[], palms=[])
|
||||
assert payload["carriageway"][0]["klasse"] == "wohnstrasse"
|
||||
assert payload["markings"][0]["art"] == "gelb_gestrichelt"
|
||||
assert payload["edges"][0]["klasse"] == "wohnstrasse"
|
||||
assert payload["edges"][0]["fahrbahn"] == 7.0
|
||||
assert len(payload["curb"][0]) == 2, "der Bordstein ist ein Linienzug, keine Fläche"
|
||||
assert "roads" not in payload and "centerlines" not in payload
|
||||
|
||||
|
||||
def test_neue_schichten_sind_lauf_stabil():
|
||||
"""Zwei Aufrufe mit vertauschter Eingabe liefern dieselbe Ausgabe (Fixrunde 3 aus Teil 1)."""
|
||||
from shapely.geometry import LineString, box
|
||||
a, b = box(10, 2400, 20, 2450), box(30, 2400, 40, 2450)
|
||||
l1, l2 = LineString([(0, 2400), (0, 2450)]), LineString([(5, 2400), (5, 2450)])
|
||||
eins = chunk_payload(0, 0, land=[], surfaces=[], carriageway=[(a, "gasse"), (b, "gasse")],
|
||||
curb=[l1, l2], sidewalk=[a], markings=[(a, "zebra"), (b, "zebra")],
|
||||
lots=[a, b], bridges=[], edges=[], buildings=[], palms=[])
|
||||
zwei = chunk_payload(0, 0, land=[], surfaces=[], carriageway=[(b, "gasse"), (a, "gasse")],
|
||||
curb=[l2, l1], sidewalk=[a], markings=[(b, "zebra"), (a, "zebra")],
|
||||
lots=[b, a], bridges=[], edges=[], buildings=[], palms=[])
|
||||
assert eins == zwei
|
||||
Reference in new issue
Block a user