diff --git a/tools/extract/leonida/park.py b/tools/extract/leonida/park.py index 5666ce6..bfe4f52 100644 --- a/tools/extract/leonida/park.py +++ b/tools/extract/leonida/park.py @@ -338,23 +338,32 @@ def build_layout(elements: list[dict], config, fit: ParkFit) -> ParkLayout: if kind is not None: surfaces[kind].extend(_polygons(game_poly.difference(blocked))) - warnings, paths = [], [] + warnings, paths, service_polys = [], [], [] if footways: union = unary_union(footways) - warnings = [f"Parkweg schneidet die Sperrfläche {k.name}" - for k, polygon in zip(config.keepouts, keepouts) if union.intersects(polygon)] + warnings += _keepout_warnings(union, config.keepouts, keepouts, "Parkweg") paths = _polygons(union.difference(blocked)) + if service: + service_union = unary_union(service) + warnings += _keepout_warnings(service_union, config.keepouts, keepouts, "Zufahrt") + service_polys = _polygons(service_union.difference(blocked)) return ParkLayout( lawn=fit.game_quad, surfaces=[(poly, kind) for kind in SURFACE_ORDER for poly in surfaces[kind]], paths=paths, - service=_polygons(unary_union(service)) if service else [], + service=service_polys, buildings=buildings, keepouts=keepouts, warnings=warnings, ) +def _keepout_warnings(union, config_keepouts, keepout_polys, label: str) -> list[str]: + """Warnungstexte für alle Sperrflächen, die `union` (Parkwege oder Zufahrten) schneiden.""" + return [f"{label} schneidet die Sperrfläche {k.name}" + for k, polygon in zip(config_keepouts, keepout_polys) if union.intersects(polygon)] + + def _surface_kind(tags: dict) -> str | None: sports = set(tags.get("sport", "").split(";")) leisure = tags.get("leisure") diff --git a/tools/extract/tests/test_park_layout.py b/tools/extract/tests/test_park_layout.py index f3bdf37..bd430b6 100644 --- a/tools/extract/tests/test_park_layout.py +++ b/tools/extract/tests/test_park_layout.py @@ -137,3 +137,12 @@ def test_service_ways_become_six_metre_service_surfaces(): (service,) = result.service assert service.contains(Point(1100, 1042.9)) and not service.contains(Point(1100, 1043.1)) assert result.paths == [] + + +def test_keepouts_cut_service_surfaces_and_warn(): + keepout = Keepout("ort", (1100.0, 1100.0), 0.0, (-10.0, 10.0, -10.0, 10.0)) # Welt x 1090–1110, y 1090–1110 + result = layout([way({"highway": "service"}, (30, 50), (70, 50))], # Welt x 1080–1120, y 1100 + keepouts=[keepout]) + hole = keepout_polygon(keepout) + assert result.service and all(poly.intersection(hole).area < 1e-6 for poly in result.service) + assert result.warnings == ["Zufahrt schneidet die Sperrfläche ort"]