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
+30
-24
@@ -33,6 +33,7 @@ SIDEWALK = (206, 202, 194)
|
|||||||
SURFACE = {"sand": (226, 210, 150), "park": (120, 160, 90), "urban": (176, 176, 172),
|
SURFACE = {"sand": (226, 210, 150), "park": (120, 160, 90), "urban": (176, 176, 172),
|
||||||
"field": (96, 176, 78), "court": (92, 138, 118), "pool": (70, 150, 220), "parking": ROAD}
|
"field": (96, 176, 78), "court": (92, 138, 118), "pool": (70, 150, 220), "parking": ROAD}
|
||||||
PATH = (226, 216, 190)
|
PATH = (226, 216, 190)
|
||||||
|
BRIDGE = (196, 92, 92)
|
||||||
PALM = (40, 190, 70)
|
PALM = (40, 190, 70)
|
||||||
OUTLINE = (30, 30, 30)
|
OUTLINE = (30, 30, 30)
|
||||||
TALL = 120.0 # Meter, ab der ein Gebäude die hellste Färbung bekommt
|
TALL = 120.0 # Meter, ab der ein Gebäude die hellste Färbung bekommt
|
||||||
@@ -78,24 +79,25 @@ def _load_chunks(out_dir: Path) -> list[dict]:
|
|||||||
return [json.loads(f.read_text()) for f in sorted(out_dir.glob("chunk_*.json"))]
|
return [json.loads(f.read_text()) for f in sorted(out_dir.glob("chunk_*.json"))]
|
||||||
|
|
||||||
|
|
||||||
def _paint_layers(img, chunks, scale, *, land, surface, sidewalk, lots, road, building,
|
def _paint_layers(img, chunks, scale, *, land, surface, sidewalk, lots, road, bridge, building,
|
||||||
outline=None, palm=None, path=None) -> dict:
|
outline=None, palm=None, path=None) -> dict:
|
||||||
"""Ebene für Ebene über alle Chunks, damit nichts von einem Nachbarchunk überdeckt wird.
|
"""Ebene für Ebene über alle Chunks, damit nichts von einem Nachbarchunk überdeckt wird.
|
||||||
|
|
||||||
surface ist eine Funktion der Belagsart, building eine Funktion der Gebäudehöhe; beide können
|
surface ist eine Funktion der Belagsart, building eine Funktion der Gebäudehöhe; beide können
|
||||||
None liefern und die Fläche so aussparen (path=None lässt ebenso die ganze Ebene aus). land,
|
None liefern und die Fläche so aussparen (path=None lässt ebenso die ganze Ebene aus). land,
|
||||||
sidewalk, lots und road sind dagegen an jedem Aufrufort eine feste Füllung — in der
|
sidewalk, lots, road und bridge sind dagegen an jedem Aufrufort eine feste Füllung: in der
|
||||||
Begehbarkeitsmaske ausdrücklich WALKABLE oder BLOCKED, denn Fahrbahn und Restflächen sollen dort
|
Begehbarkeitsmaske für alle fünf WALKABLE, denn nach der Bedeutung in nearestWalkable()
|
||||||
aktiv sperren statt nur wirkungslos zu bleiben: dort fährt Verkehr, kein Fußgänger soll landen.
|
(src/ui/mapMath.js) ist ein Pixel begehbar, wenn seine Fläche Kollisionsboden ohne Gebäude ist —
|
||||||
Reihenfolge von hinten nach vorn: Land, Beläge, Wege, Gehweg, Restflächen, Fahrbahn, Gebäude —
|
und Fahrbahn (die kollidierende Mulde), Restflächen (auf der Bodenplatte) und Brücken (eigenes
|
||||||
jede Ebene deckt die vorige ab.
|
Deck) haben Kollision, Beläge und Wege dagegen nicht.
|
||||||
|
Reihenfolge von hinten nach vorn: Land, Beläge, Wege, Gehweg, Restflächen, Fahrbahn, Brücken,
|
||||||
|
Gebäude — jede Ebene deckt die vorige ab. Brücken zuletzt, damit eine Brücke als Brücke zu sehen
|
||||||
|
ist und nicht als Straße im Wasser: ihre Fahrbahn steckt schon in carriageway an derselben Stelle.
|
||||||
|
|
||||||
chunk["markings"] wird hier nie gelesen: bei einem Pixel je Meter wäre eine 10 cm breite Linie
|
chunk["markings"] wird hier nie gelesen: bei einem Pixel je Meter wäre eine 10 cm breite Linie
|
||||||
ein Drittel Pixel und damit nur Rauschen. chunk["bridges"] ebenfalls nicht mehr: ihre Fahrbahn
|
ein Drittel Pixel und damit nur Rauschen.
|
||||||
steckt schon in carriageway, ihr begehbarer Streifen im sidewalk — eine eigene Brücken-Regel
|
|
||||||
braucht es hier nicht mehr.
|
|
||||||
"""
|
"""
|
||||||
stats = {"land": 0, "gehweg": 0, "restflaechen": 0, "strassen": 0, "gebaeude": 0, "palmen": 0}
|
stats = {"land": 0, "gehweg": 0, "restflaechen": 0, "strassen": 0, "bruecken": 0, "gebaeude": 0, "palmen": 0}
|
||||||
placed = [(chunk, chunk["origin"][0], -chunk["origin"][1]) for chunk in chunks]
|
placed = [(chunk, chunk["origin"][0], -chunk["origin"][1]) for chunk in chunks]
|
||||||
for chunk, ox, oy in placed:
|
for chunk, ox, oy in placed:
|
||||||
for rings in chunk["land"]:
|
for rings in chunk["land"]:
|
||||||
@@ -122,6 +124,10 @@ def _paint_layers(img, chunks, scale, *, land, surface, sidewalk, lots, road, bu
|
|||||||
for item in chunk["carriageway"]:
|
for item in chunk["carriageway"]:
|
||||||
_draw(img, item["poly"], ox, oy, road, scale=scale)
|
_draw(img, item["poly"], ox, oy, road, scale=scale)
|
||||||
stats["strassen"] += 1
|
stats["strassen"] += 1
|
||||||
|
for chunk, ox, oy in placed:
|
||||||
|
for item in chunk["bridges"]:
|
||||||
|
_draw(img, item["poly"], ox, oy, bridge, scale=scale)
|
||||||
|
stats["bruecken"] += 1
|
||||||
for chunk, ox, oy in placed:
|
for chunk, ox, oy in placed:
|
||||||
for item in chunk["buildings"]:
|
for item in chunk["buildings"]:
|
||||||
_draw(img, item["poly"], ox, oy, building(item["height"]), outline=outline, scale=scale)
|
_draw(img, item["poly"], ox, oy, building(item["height"]), outline=outline, scale=scale)
|
||||||
@@ -139,8 +145,8 @@ def render(out_dir: Path, dst: Path) -> dict:
|
|||||||
size = int((SLICE["x1"] - SLICE["x0"]) * SCALE)
|
size = int((SLICE["x1"] - SLICE["x0"]) * SCALE)
|
||||||
img = Image.new("RGB", (size, size), WATER)
|
img = Image.new("RGB", (size, size), WATER)
|
||||||
stats = _paint_layers(img, _load_chunks(out_dir), SCALE, land=LAND, surface=SURFACE.__getitem__,
|
stats = _paint_layers(img, _load_chunks(out_dir), SCALE, land=LAND, surface=SURFACE.__getitem__,
|
||||||
sidewalk=SIDEWALK, lots=ROAD, road=ROAD, building=_building_shade,
|
sidewalk=SIDEWALK, lots=ROAD, road=ROAD, bridge=BRIDGE,
|
||||||
outline=OUTLINE, palm=PALM, path=PATH)
|
building=_building_shade, outline=OUTLINE, palm=PALM, path=PATH)
|
||||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||||
img.save(dst)
|
img.save(dst)
|
||||||
return stats
|
return stats
|
||||||
@@ -149,19 +155,19 @@ def render(out_dir: Path, dst: Path) -> dict:
|
|||||||
def _walkable_mask(chunks: list[dict], width_m: int) -> Image.Image:
|
def _walkable_mask(chunks: list[dict], width_m: int) -> Image.Image:
|
||||||
"""Begehbarkeitsmaske mit WALKABLE_SCALE, vorsichtig aus einem 1-m-Raster verdichtet.
|
"""Begehbarkeitsmaske mit WALKABLE_SCALE, vorsichtig aus einem 1-m-Raster verdichtet.
|
||||||
|
|
||||||
Begehbar heißt: die Figur steht dort auf Kollision. Das tragen nur die Landplatte und der
|
Begehbar heißt hier wörtlich, was nearestWalkable() in src/ui/mapMath.js daraus liest: die ganze
|
||||||
Gehweg. Fahrbahn und Restflächen sperren aktiv, auch über der Landplatte — dort fährt Verkehr,
|
Fläche eines Pixels ist Kollisionsboden ohne Gebäude. Das sind Landplatte, Gehweg, Fahrbahn,
|
||||||
kein Fußgänger soll dort landen —, und Gebäude sind geschlossene Kästen. Für eine Brücke gibt es
|
Restflächen und Brückendecks — alle fünf tragen für sich, auch eine Brücke über Wasser ganz ohne
|
||||||
keine eigene Regel mehr: ihr begehbarer Streifen liegt im Gehweg, der dort die Landplatte
|
Landplatte darunter. Beläge und Wege bleiben reine Auflagen ohne eigene Kollision, Gebäude sind
|
||||||
ersetzt, ihre Fahrbahn sperrt wie jede andere. Ein Maskenpixel gilt nur als begehbar, wenn jeder
|
geschlossene Kästen, und Wasser bleibt gesperrt, weil dort nichts gemalt wird. Ein Maskenpixel
|
||||||
Quadratmeter darunter frei ist. Ein nur teilweise freier Pixel setzte die Figur sonst in eine
|
gilt nur als begehbar, wenn jeder Quadratmeter darunter frei ist. Ein nur teilweise freier Pixel
|
||||||
Wand oder vor die Kaimauer ins Wasser; an den ausgelieferten Daten traf das 4,3 % der Klicks
|
setzte die Figur sonst in eine Wand oder vor die Kaimauer ins Wasser; an den ausgelieferten Daten
|
||||||
auf Gebäude. Die Landung erfolgt in der Pixelmitte (nearestWalkable in src/ui/mapMath.js),
|
traf das 4,3 % der Klicks auf Gebäude. Die Landung erfolgt in der Pixelmitte (nearestWalkable in
|
||||||
also mindestens 2 m von jedem gesperrten Quadratmeter entfernt.
|
src/ui/mapMath.js), also mindestens 2 m von jedem gesperrten Quadratmeter entfernt.
|
||||||
"""
|
"""
|
||||||
fine = Image.new("L", (width_m, width_m), BLOCKED)
|
fine = Image.new("L", (width_m, width_m), BLOCKED)
|
||||||
_paint_layers(fine, chunks, 1.0, land=WALKABLE, surface=lambda _kind: None,
|
_paint_layers(fine, chunks, 1.0, land=WALKABLE, surface=lambda _kind: None, sidewalk=WALKABLE,
|
||||||
sidewalk=WALKABLE, lots=BLOCKED, road=BLOCKED, building=lambda _height: BLOCKED)
|
lots=WALKABLE, road=WALKABLE, bridge=WALKABLE, building=lambda _height: BLOCKED)
|
||||||
step = round(1 / WALKABLE_SCALE)
|
step = round(1 / WALKABLE_SCALE)
|
||||||
size = width_m // step
|
size = width_m // step
|
||||||
cells = np.asarray(fine).reshape(size, step, size, step)
|
cells = np.asarray(fine).reshape(size, step, size, step)
|
||||||
@@ -176,7 +182,7 @@ def render_map(out_dir: Path, dst_dir: Path) -> dict:
|
|||||||
|
|
||||||
picture = Image.new("RGB", (int(width_m * MAP_SCALE),) * 2, WATER)
|
picture = Image.new("RGB", (int(width_m * MAP_SCALE),) * 2, WATER)
|
||||||
_paint_layers(picture, chunks, MAP_SCALE, land=LAND, surface=SURFACE.__getitem__,
|
_paint_layers(picture, chunks, MAP_SCALE, land=LAND, surface=SURFACE.__getitem__,
|
||||||
sidewalk=SIDEWALK, lots=ROAD, road=ROAD, building=_building_shade,
|
sidewalk=SIDEWALK, lots=ROAD, road=ROAD, bridge=BRIDGE, building=_building_shade,
|
||||||
outline=OUTLINE, path=PATH)
|
outline=OUTLINE, path=PATH)
|
||||||
|
|
||||||
walkable = _walkable_mask(chunks, width_m)
|
walkable = _walkable_mask(chunks, width_m)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ def test_walkable_mask_blocks_buildings_and_water(tmp_path):
|
|||||||
assert mask.mode == "L"
|
assert mask.mode == "L"
|
||||||
assert mask.size == (750, 750)
|
assert mask.size == (750, 750)
|
||||||
assert mask.getpixel((10, 10)) == overview.BLOCKED # Gebäude bei 40 m / 40 m
|
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((50, 50)) == overview.WALKABLE # Land bei 200 m / 200 m
|
||||||
assert mask.getpixel((375, 375)) == overview.BLOCKED # Wasser
|
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):
|
def test_walkable_mask_counts_only_ground_with_collision(tmp_path):
|
||||||
"""Ein Belag traegt weiterhin nicht, ganz ohne Landplatte im Chunk. Fahrbahn und Restflaeche
|
"""Begehbar ist aller Boden mit Kollision, ganz ohne Landplatte im Chunk: der Gehweg, die
|
||||||
sperren aktiv (siehe test_walkable_mask_blocks_buildings_and_water fuer denselben Befund MIT
|
Fahrbahn als kollidierende Mulde, Restflaechen auf der Bodenplatte und eine Bruecke mit eigenem
|
||||||
Landplatte); eine Bruecke fuer sich traegt jetzt nicht mehr - ihr begehbarer Streifen liegt im
|
Deck tragen alle fuer sich - eine Bruecke ueber Wasser ist deshalb ausdruecklich begehbar. Nur
|
||||||
Gehweg, der die Landplatte an der Stelle ersetzt und hier zeigt, dass er das auch ohne sie tut.
|
ein Belag ist reine Auflage ohne eigene Kollision, und natuerlich sperren Gebaeude und Wasser.
|
||||||
"""
|
"""
|
||||||
src = tmp_path / "chunks"
|
src = tmp_path / "chunks"
|
||||||
src.mkdir()
|
src.mkdir()
|
||||||
@@ -112,12 +112,12 @@ def test_walkable_mask_counts_only_ground_with_collision(tmp_path):
|
|||||||
dst = tmp_path / "out"
|
dst = tmp_path / "out"
|
||||||
overview.render_map(src, dst)
|
overview.render_map(src, dst)
|
||||||
mask = Image.open(dst / "map-walkable.png")
|
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((5, 5)) == overview.BLOCKED # Sand ohne Land bei 20 m / 20 m: reine Auflage, keine Kollision
|
||||||
assert mask.getpixel((27, 5)) == overview.BLOCKED # Fahrbahn ohne Land bei 108 m / 20 m: sperrt aktiv
|
assert mask.getpixel((27, 5)) == overview.WALKABLE # Fahrbahn ohne Land bei 108 m / 20 m: kollidierende Mulde
|
||||||
assert mask.getpixel((37, 5)) == overview.BLOCKED # Restflaeche ohne Land bei 148 m / 20 m: sperrt aktiv
|
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((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((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 jetzt auch ohne Land
|
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):
|
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
|
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):
|
def test_committed_map_files_match_the_committed_chunks(tmp_path):
|
||||||
"""Kartenbild, Maske und map.json müssen aus genau den ausgelieferten Chunks stammen.
|
"""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
|
Welt und landete nach einer alten Maske. Die Laufzeitprüfung über manifest_sha256 bemerkt das
|
||||||
erst im Browser, dieser Test schon beim Testlauf.
|
erst im Browser, dieser Test schon beim Testlauf.
|
||||||
|
|
||||||
Übersprungen bis Task 16: render_map() liest seit dieser Aufgabe (15) nur noch carriageway,
|
Übersprungen: render_map() kennt nur noch das neue Chunk-Format (carriageway/sidewalk/lots/
|
||||||
sidewalk und lots statt roads und centerlines, aber public/data/vice-a bleibt laut Plan (Ruling
|
bridges/...), aber die committeten Chunks unter public/data/vice-a liegen noch im alten Format
|
||||||
zu Task 12 in docs/superpowers/sdd/2026-09-16-strassen/progress.md) bis Task 16 im alten Format —
|
(roads/centerlines) — der Pipeline-Lauf, der sie im neuen Format neu erzeugt, ist noch nicht
|
||||||
der Pipeline-Lauf in Task 12 schreibt die Daten nur zur Messung und stellt sie danach per
|
committet. Bis dahin wirft dieser Test einen KeyError statt eines aussagekräftigen Fehlschlags.
|
||||||
git checkout wieder her. Bis Task 16 die Welt neu erzeugt und committet, wirft dieser Test einen
|
Sobald public/data/vice-a im neuen Chunk-Format neu erzeugt und committet ist, muss dieses Skip
|
||||||
KeyError statt eines aussagekräftigen Fehlschlags; Task 16 muss dieses Skip mit den neuen Daten
|
mit entfernt werden.
|
||||||
zusammen entfernen.
|
|
||||||
"""
|
"""
|
||||||
shipped = Path(overview.__file__).resolve().parents[2] / "public" / "data" / "vice-a"
|
shipped = Path(overview.__file__).resolve().parents[2] / "public" / "data" / "vice-a"
|
||||||
overview.render_map(shipped, tmp_path)
|
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
|
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 = tmp_path / "chunks"
|
||||||
src.mkdir()
|
src.mkdir()
|
||||||
_strassen_fixture(src)
|
_strassen_fixture(src)
|
||||||
@@ -260,7 +265,31 @@ def test_gehweg_ist_begehbar_die_fahrbahn_nicht(tmp_path):
|
|||||||
overview.render_map(src, dst)
|
overview.render_map(src, dst)
|
||||||
maske = Image.open(dst / "map-walkable.png").convert("L")
|
maske = Image.open(dst / "map-walkable.png").convert("L")
|
||||||
step = round(1 / overview.WALKABLE_SCALE)
|
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
|
# x=117 statt 113: 4 m Abstand zu jeder Kante des 12 m breiten Gehwegs, genau das Muster der
|
||||||
# der Fahrbahnprobe unten (x=105, 4 m Abstand zu deren Kanten 100/112) - keine Grenzzelle.
|
# 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((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