Skip to content

Building Processors

Load OpenBuildingMap footprints, extrude them onto the DEM, and construct meshes with optional pitched (hip) roofs from the footprint's straight skeleton. See Buildings.

Footprints & meshes

s2gos_generator.processors.buildings.meshing.quadkeys_for_bbox

quadkeys_for_bbox(
    bbox: tuple[float, float, float, float], zoom: int
) -> set[str]

Quadkeys of every tile at zoom overlapping a WGS84 lon/lat bbox.

s2gos_generator.processors.buildings.meshing.select_tile_files

select_tile_files(
    tile_dir: Path,
    bbox: tuple[float, float, float, float],
    index_csv: str,
) -> list[Path]

Pick the building tiles overlapping bbox from a quadkey-indexed dir.

Reads the index CSV (quadkey -> filename), figures out which tiles the AOI touches via :func:quadkeys_for_bbox, and returns the matching files that are actually present in tile_dir. Index-listed tiles that are missing are warned about and skipped.

s2gos_generator.processors.buildings.meshing.load_building_footprints

load_building_footprints(
    file_paths: list[Path],
    layer: str,
    bbox: tuple[float, float, float, float],
) -> gpd.GeoDataFrame

Read each GPKG with a bbox prefilter and concat into a single frame.

s2gos_generator.processors.buildings.meshing.make_dem_elevation_sampler

make_dem_elevation_sampler(
    dem_path,
) -> Callable[[np.ndarray], np.ndarray]

Open the DEM zarr and return a fast bilinear elevation sampler.

s2gos_generator.processors.buildings.meshing.build_meshes

build_meshes(
    gdf: GeoDataFrame,
    elev_fn: Callable[[ndarray], ndarray],
    cfg: "BuildingsConfig",
) -> BuildingMeshes

Build combined building meshes from scene-local footprints.

gdf must already be reprojected to scene-local meters. Each footprint is placed on the DEM (its centroid sampled via elev_fn), extruded to a parsed height, optionally given a hip roof, and assigned a material. Footprints are grouped into one combined mesh per material (plus one combined roof mesh). When cfg.material is a {name: weight} mapping, each building is assigned one material by weighted random draw before grouping.

s2gos_generator.processors.buildings.meshing.BuildingMeshes dataclass

BuildingMeshes(
    material_meshes: dict[str, Trimesh],
    roof_mesh: Optional[Trimesh],
    single_material: bool,
    stats: BuildingMeshStats,
)

Combined building geometry, grouped one mesh per material plus one roof mesh.

s2gos_generator.processors.buildings.meshing.BuildingMeshStats dataclass

BuildingMeshStats(
    total: int,
    per_material_counts: dict[str, int],
    pitched: int,
    flat_fallback: int,
    skipped: int,
    unparsed_height: int,
)

Per-run counts gathered while building footprint meshes.

Hip roofs

s2gos_generator.processors.buildings.roof.build_hip_roof

build_hip_roof(
    poly: Polygon,
    eaves_z: float,
    apex_z: float,
    pitch_deg: float,
) -> Optional[trimesh.Trimesh]

Hipped roof: every wall slopes up to the skeleton ridge.

s2gos_generator.processors.buildings.roof.compute_pitched_geometry

compute_pitched_geometry(
    total_height: float,
    pitch_deg: float,
    target_roof_height: float,
) -> Optional[dict]

s2gos_generator.processors.buildings.skeleton.Skeleton

Skeleton(
    poly: Union[Polygon, MultiPolygon],
    tol_dist: float = 1e-08,
    tol_angle: float = 1e-19,
    tol_time: float = 0,
)