Add feature registry dispatch

This commit is contained in:
2026-08-03 14:02:28 +08:00
parent dd50d3aae3
commit ff18217af5
12 changed files with 417 additions and 46 deletions

View File

@@ -34,6 +34,7 @@ if _HERE not in sys.path:
sys.path.insert(0, _HERE)
from osmassets import catalog # noqa: E402
from osmassets import features as _features # noqa: E402
from osmassets.geom import ( # noqa: E402 (needs the sys.path line above)
distance_to_ring,
point_in_polygon,
@@ -669,46 +670,71 @@ def build(args):
return obj
focus_points = []
for way in ways:
coords = way["coords"]
if not any(projector.inside(c) for c in coords):
continue
ring = projector.ring(coords)
tag = way["tags"]
if tag.get("natural") == "water" or tag.get("water") == "lake":
counts["lake_count"] += _water.assemble(ring, scene_xmin, scene_xmax,
scene_ymin, scene_ymax,
water_c, water_mat)
elif tag.get("landuse") == "grass":
added, tufts, ring_pts = _grass.assemble(
ring, way["id"], scene_xmin, scene_xmax, scene_ymin, scene_ymax,
green_c, grass_mat, tuft_variants, add_grass_tufts)
counts["grass_count"] += added
counts["grass_tuft_count"] += tufts
if ring_pts:
grass_rings.append(ring_pts)
focus_points.extend(ring_pts)
elif tag.get("natural") == "scrub" and len(ring) >= 3:
added, ring_pts = _scrub.assemble(ring, way["id"], scene_xmin, scene_xmax,
scene_ymin, scene_ymax, green_c, scrub_mat,
add_scrub_patch_with_bushes)
counts["scrub_count"] += added
if ring_pts:
focus_points.extend(ring_pts)
new_scrub_trees = sample_scrub_interior_trees(ring_pts, way["id"])
scrub_trees.extend(new_scrub_trees)
counts["scrub_tree_count"] += len(new_scrub_trees)
elif tag.get("natural") == "tree_row":
tree_rows.append((ring, tag))
focus_points.extend(ring)
elif "building" in tag and len(ring) >= 3:
added, ind_added, ring_pts = _building.assemble(
ring, str(way["id"]), tag, args["office_overrides"],
buildings_c, building_mats)
counts["building_count"] += added
counts["industrial_count"] += ind_added
if ring_pts:
focus_points.extend(ring_pts)
def handle_water(way, tag, ring):
counts["lake_count"] += _water.assemble(ring, scene_xmin, scene_xmax,
scene_ymin, scene_ymax,
water_c, water_mat)
def handle_grass(way, tag, ring):
added, tufts, ring_pts = _grass.assemble(
ring, way["id"], scene_xmin, scene_xmax, scene_ymin, scene_ymax,
green_c, grass_mat, tuft_variants, add_grass_tufts)
counts["grass_count"] += added
counts["grass_tuft_count"] += tufts
if ring_pts:
grass_rings.append(ring_pts)
focus_points.extend(ring_pts)
def handle_scrub(way, tag, ring):
added, ring_pts = _scrub.assemble(ring, way["id"], scene_xmin, scene_xmax,
scene_ymin, scene_ymax, green_c, scrub_mat,
add_scrub_patch_with_bushes)
counts["scrub_count"] += added
if ring_pts:
focus_points.extend(ring_pts)
new_scrub_trees = sample_scrub_interior_trees(ring_pts, way["id"])
scrub_trees.extend(new_scrub_trees)
counts["scrub_tree_count"] += len(new_scrub_trees)
def handle_tree_row(way, tag, ring):
tree_rows.append((ring, tag))
focus_points.extend(ring)
def handle_building(way, tag, ring):
added, ind_added, ring_pts = _building.assemble(
ring, str(way["id"]), tag, args["office_overrides"],
buildings_c, building_mats)
counts["building_count"] += added
counts["industrial_count"] += ind_added
if ring_pts:
focus_points.extend(ring_pts)
way_handlers = (
_features.FeatureHandler(
"water",
lambda way, tag, ring: tag.get("natural") == "water"
or tag.get("water") == "lake",
handle_water),
_features.FeatureHandler(
"grass",
lambda way, tag, ring: tag.get("landuse") == "grass",
handle_grass),
_features.FeatureHandler(
"scrub",
lambda way, tag, ring: tag.get("natural") == "scrub"
and len(ring) >= 3,
handle_scrub),
_features.FeatureHandler(
"tree_row",
lambda way, tag, ring: tag.get("natural") == "tree_row",
handle_tree_row),
_features.FeatureHandler(
"building",
lambda way, tag, ring: "building" in tag and len(ring) >= 3,
handle_building),
)
_features.dispatch_ways(ways, projector, way_handlers)
geojson_dir = args.get("geojson")
road_counts = {}

View File

@@ -0,0 +1,20 @@
"""Feature registry and dispatch helpers for scene assembly phases."""
from collections import namedtuple
FeatureHandler = namedtuple("FeatureHandler", ("name", "matches", "handle"))
def dispatch_ways(ways, projector, handlers):
"""Dispatch OSM ways to the first matching handler, preserving order."""
for way in ways:
coords = way["coords"]
if not any(projector.inside(c) for c in coords):
continue
ring = projector.ring(coords)
tag = way["tags"]
for handler in handlers:
if handler.matches(way, tag, ring):
handler.handle(way, tag, ring)
break