feat(extract): Parkanlage in die Welt einsetzen, Palmen neu setzen, Ecken prüfen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cfc9fc0690
commit
2ef9e6774a
2 files changed
+115
-1
No files matched your search
@@ -16,7 +16,7 @@ from pathlib import Path
|
||||
from shapely.geometry import LineString, Point, Polygon
|
||||
from shapely.ops import unary_union
|
||||
|
||||
from .heights import PALM_KERB
|
||||
from .heights import PALM_CLEARANCE, PALM_KERB, palm_points
|
||||
|
||||
|
||||
class ParkError(ValueError):
|
||||
@@ -485,3 +485,40 @@ def apply_street(world: World, street: Street) -> World:
|
||||
palms = [p for p in world.palms if corridor.distance(Point(p)) >= PALM_KERB]
|
||||
return replace(world, roads=roads, centerlines=centerlines, buildings=buildings,
|
||||
surfaces=surfaces, palms=palms)
|
||||
|
||||
|
||||
def check_corners(config, roads: list[tuple[Polygon, bool]], tolerance: float = 2.0) -> None:
|
||||
"""Jede Spielecke muss an einer Straße liegen, sonst hat sich die Extraktion geändert."""
|
||||
for name, (x, y) in config.game.items():
|
||||
corner = Point(x, y)
|
||||
if not any(poly.distance(corner) <= tolerance for poly, bridge in roads if not bridge):
|
||||
raise ParkError(f"Spielecke {name} ({x:g} | {y:g}) liegt weiter als {tolerance:g} m von jeder Straße: "
|
||||
"Ecken in flamingo-park.toml neu messen")
|
||||
|
||||
|
||||
def apply_park(world: World, layout: ParkLayout, seed: int) -> World:
|
||||
"""Alte Straßen, Beläge, Gebäude und Palmen im Park weg, neue Anlage hinein, Palmen neu gesetzt."""
|
||||
quad = layout.lawn
|
||||
roads = [(piece, bridge) for poly, bridge in world.roads
|
||||
for piece in (_polygons(poly.difference(quad), MIN_ROAD_AREA) if poly.intersects(quad) else [poly])]
|
||||
centerlines = [piece for line in world.centerlines
|
||||
for piece in (_lines(line.difference(quad)) if line.intersects(quad) else [line])]
|
||||
surfaces = [(piece, kind) for poly, kind in world.surfaces
|
||||
for piece in (_polygons(poly.difference(quad)) if poly.intersects(quad) else [poly])]
|
||||
buildings = [b for b in world.buildings
|
||||
if not b[0].intersects(quad) or b[0].intersection(quad).area <= 0.5 * b[0].area]
|
||||
palms = [p for p in world.palms if not quad.contains(Point(p))]
|
||||
|
||||
roads += [(poly, False) for poly in layout.service]
|
||||
surfaces += [(quad, "park")] + layout.surfaces
|
||||
buildings += [(poly, {"height": height, "source": "osm"}, False) for poly, height in layout.buildings]
|
||||
|
||||
reach = quad.buffer(PALM_CLEARANCE + 1)
|
||||
blocked = unary_union([poly for poly, _ in roads if poly.intersects(reach)]
|
||||
+ [b[0] for b in buildings if b[0].intersects(reach)]
|
||||
+ layout.paths + layout.keepouts).intersection(reach)
|
||||
lawn = quad.difference(unary_union([poly for poly, _ in layout.surfaces]))
|
||||
# Abstand zu einer leeren Geometrie ist in shapely NaN, und NaN > 6 verwürfe jede Palme.
|
||||
palms += palm_points([], _polygons(lawn), [], [] if blocked.is_empty else [blocked], [], [], seed)
|
||||
return replace(world, roads=roads, centerlines=centerlines, surfaces=surfaces,
|
||||
buildings=buildings, palms=palms, paths=world.paths + layout.paths)
|
||||
Reference in new issue
Block a user