fix(extract): Sperrflächen auch aus Zufahrtsflächen ausschneiden und davor warnen
Zufahrtsflächen (highway=service) wurden bisher ungeschnitten ausgegeben und nicht auf
Überschneidung mit Sperrflächen geprüft. Am echten Stand überlappte eine Zufahrt die
Sperrfläche "tribuene" um 42,17 m² ohne Schnitt und ohne Warnung. build_layout wendet
difference(blocked) jetzt auch auf Zufahrten an, die Warnschleife prüft Wege und
Zufahrten getrennt ("Parkweg schneidet ..." / "Zufahrt schneidet ...").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
26aafbbbd5
commit
d756eccd77
2 files changed
+22
-4
No files matched your search
@@ -338,23 +338,32 @@ def build_layout(elements: list[dict], config, fit: ParkFit) -> ParkLayout:
|
|||||||
if kind is not None:
|
if kind is not None:
|
||||||
surfaces[kind].extend(_polygons(game_poly.difference(blocked)))
|
surfaces[kind].extend(_polygons(game_poly.difference(blocked)))
|
||||||
|
|
||||||
warnings, paths = [], []
|
warnings, paths, service_polys = [], [], []
|
||||||
if footways:
|
if footways:
|
||||||
union = unary_union(footways)
|
union = unary_union(footways)
|
||||||
warnings = [f"Parkweg schneidet die Sperrfläche {k.name}"
|
warnings += _keepout_warnings(union, config.keepouts, keepouts, "Parkweg")
|
||||||
for k, polygon in zip(config.keepouts, keepouts) if union.intersects(polygon)]
|
|
||||||
paths = _polygons(union.difference(blocked))
|
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(
|
return ParkLayout(
|
||||||
lawn=fit.game_quad,
|
lawn=fit.game_quad,
|
||||||
surfaces=[(poly, kind) for kind in SURFACE_ORDER for poly in surfaces[kind]],
|
surfaces=[(poly, kind) for kind in SURFACE_ORDER for poly in surfaces[kind]],
|
||||||
paths=paths,
|
paths=paths,
|
||||||
service=_polygons(unary_union(service)) if service else [],
|
service=service_polys,
|
||||||
buildings=buildings,
|
buildings=buildings,
|
||||||
keepouts=keepouts,
|
keepouts=keepouts,
|
||||||
warnings=warnings,
|
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:
|
def _surface_kind(tags: dict) -> str | None:
|
||||||
sports = set(tags.get("sport", "").split(";"))
|
sports = set(tags.get("sport", "").split(";"))
|
||||||
leisure = tags.get("leisure")
|
leisure = tags.get("leisure")
|
||||||
|
|||||||
@@ -137,3 +137,12 @@ def test_service_ways_become_six_metre_service_surfaces():
|
|||||||
(service,) = result.service
|
(service,) = result.service
|
||||||
assert service.contains(Point(1100, 1042.9)) and not service.contains(Point(1100, 1043.1))
|
assert service.contains(Point(1100, 1042.9)) and not service.contains(Point(1100, 1043.1))
|
||||||
assert result.paths == []
|
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"]
|
||||||
Reference in new issue
Block a user