fix(extract): Fahrbahn, Restflächen und Brücken sind begehbar, nicht nur der Gehweg
Korrektur eines Fehlers im Plantext, nicht in der vorigen Umsetzung: "begehbar" ist in src/ui/mapMath.js (nearestWalkable()/landingFor()) als "Kollisionsboden ohne Gebäude" definiert, nicht als Fußgängerzone. Fahrbahn ist die kollidierende Mulde, Restflächen liegen auf der Bodenplatte, Brücken haben ihr eigenes Deck - alle drei tragen wie die Landplatte und der Gehweg. Nur Gebäude sperren; Wasser bleibt gesperrt, weil nichts darüber gemalt wird. Ein Klick auf eine Straße oder einen Damm über Wasser landet damit wieder auf ihr, statt ins Nichts zu greifen. chunk["bridges"] wird dafür wieder gelesen und zusätzlich im Kartenbild in BRIDGE gezeichnet, nach der Fahrbahn, damit eine Brücke als Brücke zu sehen ist und nicht als Straße im Wasser. test_walkable_mask_counts_only_ground_with_collision und test_walkable_mask_blocks_buildings_and_water zurückgestellt; ein neuer Test sichert die Brückenfarbe im Kartenbild. test_gehweg_ist_begehbar_die_fahrbahn_nicht sagte nach der Korrektur nicht mehr die Wahrheit über sich selbst - Fahrbahn ist jetzt auch begehbar - und ist umbenannt in test_gehweg_und_fahrbahn_sind_beide_begehbar. Der Skip-Grund von test_committed_map_files_match_the_committed_chunks nennt jetzt die Bedingung fürs Entfernen statt einer Aufgabennummer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e21367e73
commit
6c73b7f816
2 files changed
+81
-46
No files matched your search
@@ -58,7 +58,7 @@ def test_walkable_mask_blocks_buildings_and_water(tmp_path):
|
||||
assert mask.mode == "L"
|
||||
assert mask.size == (750, 750)
|
||||
assert mask.getpixel((10, 10)) == overview.BLOCKED # Gebäude bei 40 m / 40 m
|
||||
assert mask.getpixel((27, 31)) == overview.BLOCKED # Fahrbahn bei 110 m / 125 m: sperrt jetzt aktiv, auch auf Land
|
||||
assert mask.getpixel((27, 31)) == overview.WALKABLE # Fahrbahn bei 110 m / 125 m: kollidierende Mulde, nicht nur Auflage
|
||||
assert mask.getpixel((50, 50)) == overview.WALKABLE # Land bei 200 m / 200 m
|
||||
assert mask.getpixel((375, 375)) == overview.BLOCKED # Wasser
|
||||
|
||||
@@ -87,10 +87,10 @@ def test_debug_overview_still_draws_palms(tmp_path):
|
||||
|
||||
|
||||
def test_walkable_mask_counts_only_ground_with_collision(tmp_path):
|
||||
"""Ein Belag traegt weiterhin nicht, ganz ohne Landplatte im Chunk. Fahrbahn und Restflaeche
|
||||
sperren aktiv (siehe test_walkable_mask_blocks_buildings_and_water fuer denselben Befund MIT
|
||||
Landplatte); eine Bruecke fuer sich traegt jetzt nicht mehr - ihr begehbarer Streifen liegt im
|
||||
Gehweg, der die Landplatte an der Stelle ersetzt und hier zeigt, dass er das auch ohne sie tut.
|
||||
"""Begehbar ist aller Boden mit Kollision, ganz ohne Landplatte im Chunk: der Gehweg, die
|
||||
Fahrbahn als kollidierende Mulde, Restflaechen auf der Bodenplatte und eine Bruecke mit eigenem
|
||||
Deck tragen alle fuer sich - eine Bruecke ueber Wasser ist deshalb ausdruecklich begehbar. Nur
|
||||
ein Belag ist reine Auflage ohne eigene Kollision, und natuerlich sperren Gebaeude und Wasser.
|
||||
"""
|
||||
src = tmp_path / "chunks"
|
||||
src.mkdir()
|
||||
@@ -112,12 +112,12 @@ def test_walkable_mask_counts_only_ground_with_collision(tmp_path):
|
||||
dst = tmp_path / "out"
|
||||
overview.render_map(src, dst)
|
||||
mask = Image.open(dst / "map-walkable.png")
|
||||
assert mask.getpixel((5, 5)) == overview.BLOCKED # Sand ohne Land bei 20 m / 20 m: traegt nicht
|
||||
assert mask.getpixel((27, 5)) == overview.BLOCKED # Fahrbahn ohne Land bei 108 m / 20 m: sperrt aktiv
|
||||
assert mask.getpixel((37, 5)) == overview.BLOCKED # Restflaeche ohne Land bei 148 m / 20 m: sperrt aktiv
|
||||
assert mask.getpixel((5, 5)) == overview.BLOCKED # Sand ohne Land bei 20 m / 20 m: reine Auflage, keine Kollision
|
||||
assert mask.getpixel((27, 5)) == overview.WALKABLE # Fahrbahn ohne Land bei 108 m / 20 m: kollidierende Mulde
|
||||
assert mask.getpixel((37, 5)) == overview.WALKABLE # Restflaeche ohne Land bei 148 m / 20 m: liegt auf der Bodenplatte
|
||||
assert mask.getpixel((42, 5)) == overview.BLOCKED # Wasser bei 168 m / 20 m
|
||||
assert mask.getpixel((47, 5)) == overview.BLOCKED # Bruecke ohne Land bei 188 m / 20 m: traegt nicht mehr
|
||||
assert mask.getpixel((57, 5)) == overview.WALKABLE # Gehweg bei 228 m / 20 m: traegt jetzt auch ohne Land
|
||||
assert mask.getpixel((47, 5)) == overview.WALKABLE # Bruecke ohne Land bei 188 m / 20 m: eigenes Deck, auch ueber Wasser begehbar
|
||||
assert mask.getpixel((57, 5)) == overview.WALKABLE # Gehweg bei 228 m / 20 m: traegt auch ohne Land
|
||||
|
||||
|
||||
def test_walkable_mask_blocks_pixels_that_are_only_partly_free(tmp_path):
|
||||
@@ -144,7 +144,9 @@ def test_walkable_mask_blocks_pixels_that_are_only_partly_free(tmp_path):
|
||||
assert mask.getpixel((8, 11)) == overview.WALKABLE # 32..36 m: frei
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="public/data/vice-a ist bis Task 16 im alten Chunk-Format; siehe Docstring")
|
||||
@pytest.mark.skip(reason="public/data/vice-a ist noch im alten Chunk-Format (roads/centerlines); "
|
||||
"Skip erst entfernen, wenn es im neuen Format (carriageway/sidewalk/lots/"
|
||||
"bridges/...) neu erzeugt und committet ist")
|
||||
def test_committed_map_files_match_the_committed_chunks(tmp_path):
|
||||
"""Kartenbild, Maske und map.json müssen aus genau den ausgelieferten Chunks stammen.
|
||||
|
||||
@@ -152,13 +154,12 @@ def test_committed_map_files_match_the_committed_chunks(tmp_path):
|
||||
Welt und landete nach einer alten Maske. Die Laufzeitprüfung über manifest_sha256 bemerkt das
|
||||
erst im Browser, dieser Test schon beim Testlauf.
|
||||
|
||||
Übersprungen bis Task 16: render_map() liest seit dieser Aufgabe (15) nur noch carriageway,
|
||||
sidewalk und lots statt roads und centerlines, aber public/data/vice-a bleibt laut Plan (Ruling
|
||||
zu Task 12 in docs/superpowers/sdd/2026-09-16-strassen/progress.md) bis Task 16 im alten Format —
|
||||
der Pipeline-Lauf in Task 12 schreibt die Daten nur zur Messung und stellt sie danach per
|
||||
git checkout wieder her. Bis Task 16 die Welt neu erzeugt und committet, wirft dieser Test einen
|
||||
KeyError statt eines aussagekräftigen Fehlschlags; Task 16 muss dieses Skip mit den neuen Daten
|
||||
zusammen entfernen.
|
||||
Übersprungen: render_map() kennt nur noch das neue Chunk-Format (carriageway/sidewalk/lots/
|
||||
bridges/...), aber die committeten Chunks unter public/data/vice-a liegen noch im alten Format
|
||||
(roads/centerlines) — der Pipeline-Lauf, der sie im neuen Format neu erzeugt, ist noch nicht
|
||||
committet. Bis dahin wirft dieser Test einen KeyError statt eines aussagekräftigen Fehlschlags.
|
||||
Sobald public/data/vice-a im neuen Chunk-Format neu erzeugt und committet ist, muss dieses Skip
|
||||
mit entfernt werden.
|
||||
"""
|
||||
shipped = Path(overview.__file__).resolve().parents[2] / "public" / "data" / "vice-a"
|
||||
overview.render_map(shipped, tmp_path)
|
||||
@@ -251,7 +252,11 @@ def test_markierung_wird_nicht_gezeichnet(tmp_path):
|
||||
assert bild.getpixel((105, 120)) == overview.ROAD
|
||||
|
||||
|
||||
def test_gehweg_ist_begehbar_die_fahrbahn_nicht(tmp_path):
|
||||
def test_gehweg_und_fahrbahn_sind_beide_begehbar(tmp_path):
|
||||
"""Gehweg und Fahrbahn sehen im Kartenbild verschieden aus (SIDEWALK/ROAD), tragen in der
|
||||
Begehbarkeitsmaske aber beide: 'begehbar' heisst hier Kollisionsboden ohne Gebaeude
|
||||
(nearestWalkable() in src/ui/mapMath.js), nicht Fussgaengerzone.
|
||||
"""
|
||||
src = tmp_path / "chunks"
|
||||
src.mkdir()
|
||||
_strassen_fixture(src)
|
||||
@@ -260,7 +265,31 @@ def test_gehweg_ist_begehbar_die_fahrbahn_nicht(tmp_path):
|
||||
overview.render_map(src, dst)
|
||||
maske = Image.open(dst / "map-walkable.png").convert("L")
|
||||
step = round(1 / overview.WALKABLE_SCALE)
|
||||
# x=117 statt 113: 4 m Abstand zu jeder Kante des jetzt 12 m breiten Gehwegs, genau das Muster
|
||||
# der Fahrbahnprobe unten (x=105, 4 m Abstand zu deren Kanten 100/112) - keine Grenzzelle.
|
||||
# x=117 statt 113: 4 m Abstand zu jeder Kante des 12 m breiten Gehwegs, genau das Muster der
|
||||
# Fahrbahnprobe (x=105, 4 m Abstand zu deren Kanten 100/112) - keine Grenzzelle.
|
||||
assert maske.getpixel((117 // step, 10 // step)) == overview.WALKABLE, "Gehweg"
|
||||
assert maske.getpixel((105 // step, 10 // step)) == overview.BLOCKED, "Fahrbahn"
|
||||
assert maske.getpixel((105 // step, 10 // step)) == overview.WALKABLE, "Fahrbahn"
|
||||
|
||||
|
||||
def test_bruecke_bleibt_im_kartenbild_als_bruecke_sichtbar(tmp_path):
|
||||
"""chunk["bridges"] wird nach der Fahrbahn gezeichnet: sonst zeigte eine Bruecke ueber Wasser nur
|
||||
ihre Fahrbahn (carriageway liegt an derselben Stelle) und saehe wie eine Strasse im Wasser aus
|
||||
statt wie eine Bruecke.
|
||||
"""
|
||||
src = tmp_path / "chunks"
|
||||
src.mkdir()
|
||||
chunk = {
|
||||
"chunk": [0, 0],
|
||||
"origin": [SLICE["x0"], -SLICE["y1"]],
|
||||
"land": [], "surfaces": [], "paths": [], "curb": [], "edges": [], "markings": [],
|
||||
"sidewalk": [], "lots": [],
|
||||
"carriageway": [{"poly": [_ring(100, 0, 120, 40)], "klasse": "hauptstrasse"}],
|
||||
"bridges": [{"poly": [_ring(100, 0, 120, 40)]}],
|
||||
"buildings": [], "palms": [],
|
||||
}
|
||||
(src / "chunk_0_0.json").write_text(json.dumps(chunk))
|
||||
(src / "manifest.json").write_text('{"slice": "vice-a"}\n')
|
||||
dst = tmp_path / "out"
|
||||
overview.render_map(src, dst)
|
||||
bild = Image.open(dst / "map.png").convert("RGB")
|
||||
assert bild.getpixel((110, 20)) == overview.BRIDGE, "Bruecke ueber Wasser, nicht Strasse im Wasser"
|
||||
Reference in new issue
Block a user