Skip to content

Terrain Mesh Processors

Turn DEM elevation grids into 3D triangle meshes via an adaptive quadtree, orchestrated by build_refined_mesh. See Adaptive terrain mesh.

Orchestration

s2gos_generator.processors.terrain_mesh.builder.build_refined_mesh

build_refined_mesh(
    dem_data: DataArray,
    operations: list[TerraformOperation] | None,
    config,
    handle_nans: bool = True,
) -> trimesh.Trimesh

Build an adaptive quadtree mesh with optional terraforming operations.

Orchestrates: DEM extraction -> decimated grid -> operation refinement -> triangulation + flatten -> NaN cleanup.

Parameters:

Name Type Description Default
dem_data DataArray

DEM elevation DataArray.

required
operations list[TerraformOperation] | None

List of :class:TerraformOperation to apply; pass None or an empty list to skip road-influence refinement and flattening.

required
config

:class:MeshRefinementConfig (decimation_depth, decimation_tolerance_m, max_depth, flatten, …).

required
handle_nans bool

Remove faces whose vertices contain NaN elevations.

True

Returns:

Name Type Description
Adaptive Trimesh

class:trimesh.Trimesh.

s2gos_generator.processors.terrain_mesh.builder.extract_dem

extract_dem(
    dem_data: DataArray,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]

Load and extract coordinate arrays from a DEM DataArray.

Returns:

Type Description
tuple[ndarray, ndarray, ndarray]

(x, y, elev) — 1-D coordinate arrays and 2-D elevation array.

Decimation & grid

s2gos_generator.processors.terrain_mesh.adaptive_grid.AdaptiveGrid

AdaptiveGrid(
    x_coords: ndarray, y_coords: ndarray, max_depth: int
)

Quadtree over a regular DEM grid.

Cells are stored as packed uint64 integers: bits 63-60 : depth level bits 59-30 : column index i bits 29-0 : row index j

Functions

balance

balance() -> None

Ensure 2:1 maximum-grade across all quadtree boundaries.

refine

refine(
    predicate: Callable[
        [ndarray, ndarray, ndarray, ndarray], ndarray
    ],
    max_level: int | None = None,
) -> None

Batch-subdivide leaves using the supplied spatial predicate.

to_mesh

to_mesh(
    elevation_fn: Callable[[ndarray], ndarray],
) -> tuple[np.ndarray, np.ndarray]

Emit a crack-free triangle mesh from the current quadtree.

s2gos_generator.processors.terrain_mesh.builder.build_decimated_grid

build_decimated_grid(
    x: ndarray,
    y: ndarray,
    elev: ndarray,
    decimation_depth: int,
    decimation_tolerance_m: float,
    extra_max_depth: int = 0,
) -> AdaptiveGrid

Build an adaptive quadtree coarsened by 2^decimation_depth, then refined back where the local plane-residual exceeds decimation_tolerance_m.

With decimation_depth=0 this returns a native-resolution grid, same cost as a plain uniform grid construction. extra_max_depth reserves additional refinement headroom for downstream feature-based passes.

Parameters:

Name Type Description Default
x ndarray

1-D x coordinate array (DEM native resolution).

required
y ndarray

1-D y coordinate array (DEM native resolution).

required
elev ndarray

2-D elevation array matching (y × x) shape.

required
decimation_depth int

Coarsening factor in powers of 2.

required
decimation_tolerance_m float

Max plane-residual (metres) before a cell is refined back. 0 disables pyramid-driven refinement.

required
extra_max_depth int

Additional depth levels reserved beyond decimation_depth for downstream refinement passes.

0

Returns:

Type Description
AdaptiveGrid

Unbalanced, untriangulated AdaptiveGrid.

s2gos_generator.processors.terrain_mesh.error_pyramid.DemErrorPyramid

DemErrorPyramid(
    elev: ndarray,
    x0: float,
    y0: float,
    dx: float,
    dy: float,
    decimation_depth: int,
)

Precomputed per-level max plane-residual errors for adaptive-quadtree decimation.

Each level L stores, for every cell of size K×K DEM pixels (K = 2^(D-L)), the maximum absolute deviation of the DEM from the least-squares plane fitted to that cell. Errors are saturated top-down (parent ≥ max of children) so top-down refinement decisions are monotone — no cracks arise from coarse cells being mis-classified as flat after their children were already refined.

D (decimation_depth) is the number of refinement levels used for terrain decimation (matches MeshRefinementConfig.decimation_depth). At the finest level D, cells are 1×1 DEM pixels and the residual is 0.

Functions

query

query(
    xmin: ndarray,
    ymin: ndarray,
    xmax: ndarray,
    ymax: ndarray,
    tolerance_m: float,
) -> np.ndarray

Vectorized predicate: True where max plane-residual > tolerance_m.

Cell sizes are inferred from the world-coordinate extents so this method can be used directly as a refine predicate without knowing the current level explicitly.

Feature refinement & meshing

s2gos_generator.processors.terrain_mesh.builder.refine_grid_for_operations

refine_grid_for_operations(
    grid: AdaptiveGrid,
    operations: list[TerraformOperation] | None,
) -> None

Refine the grid where any operation's influence_zone intersects (in-place).

No-op when operations is falsy.

s2gos_generator.processors.terrain_mesh.builder.grid_to_terrain_mesh

grid_to_terrain_mesh(
    grid: AdaptiveGrid,
    elevation_fn,
    operations: list[TerraformOperation] | None = None,
    flatten: bool = False,
    handle_nans: bool = True,
) -> trimesh.Trimesh

Balance, triangulate, optionally flatten along operation centrelines, and remove NaN-containing faces.

Parameters:

Name Type Description Default
grid AdaptiveGrid

Populated AdaptiveGrid (balanced in-place here).

required
elevation_fn

Callable mapping (N, 2) xy array -> (N,) elevations.

required
operations list[TerraformOperation] | None

TerraformOperations used for flatten; ignored when flatten=False.

None
flatten bool

Apply batch vertex flattening along operation centrelines.

False
handle_nans bool

Remove faces whose vertices contain NaN elevations.

True

Returns:

Type Description
Trimesh

Cleaned trimesh.Trimesh.

s2gos_generator.processors.terrain_mesh.mesh_generator.MeshGenerator

MeshGenerator()

Converts DEM data to 3D meshes

Initialize the mesh generator.

Functions

adaptive_dem_to_mesh

adaptive_dem_to_mesh(
    dem_data: DataArray,
    operations,
    refinement_config,
    handle_nans: bool = True,
) -> trimesh.Trimesh

Build an adaptive quadtree mesh with terraforming operations.

Parameters:

Name Type Description Default
dem_data DataArray

DEM elevation DataArray.

required
operations

list[TerraformOperation] — one per road segment, or None for a uniform mesh.

required
refinement_config

MeshRefinementConfig instance.

required
handle_nans bool

Whether to remove NaN-containing faces.

True

Returns:

Type Description
Trimesh

Adaptive Trimesh object.

add_uv_coordinates

add_uv_coordinates(mesh: Trimesh) -> trimesh.Trimesh

Adds planar UV coordinates to a mesh based on its bounding box.

Parameters:

Name Type Description Default
mesh Trimesh

The input mesh.

required

Returns:

Type Description
Trimesh

The mesh with UV coordinates added.

dem_to_mesh

dem_to_mesh(
    dem_data: DataArray, handle_nans: bool = True
) -> trimesh.Trimesh

Convert a DEM DataArray to a Trimesh object.

generate_mesh_from_dem_file

generate_mesh_from_dem_file(
    dem_file_path: UPath,
    output_path: UPath,
    add_uvs: bool = True,
    handle_nans: bool = True,
) -> trimesh.Trimesh

Complete pipeline: loads DEM from file, generates mesh, and saves.

Parameters:

Name Type Description Default
dem_file_path UPath

UPath to the DEM NetCDF file.

required
output_path UPath

UPath where the mesh will be saved.

required
add_uvs bool

Whether to add UV coordinates.

True
handle_nans bool

Whether to handle NaN values in the DEM.

True

Returns:

Type Description
Trimesh

The generated mesh.

get_mesh_info

get_mesh_info(mesh: Trimesh) -> dict

Returns summary information about a mesh.

Parameters:

Name Type Description Default
mesh Trimesh

The mesh to analyze.

required

Returns:

Type Description
dict

Dictionary containing mesh statistics.

save_mesh

save_mesh(
    mesh: Trimesh, output_path: UPath, format: str = "ply"
) -> None

Saves a mesh to file.

Parameters:

Name Type Description Default
mesh Trimesh

The mesh to save.

required
output_path UPath

UPath where the mesh will be saved.

required
format str

File format (e.g., 'ply', 'obj', 'stl').

'ply'

Terrain flattening

s2gos_generator.processors.terrain_mesh.terraforming.GradientFilter

GradientFilter(elev: ndarray, x: ndarray, y: ndarray)

Filter road segments by DEM gradient magnitude along the centerline.

Roads whose max gradient is below threshold are skipped (flat terrain, flattening would be a no-op) Args: elev: 2-D elevation array, shape (ny, nx). x: 1-D x coordinates, length nx. y: 1-D y coordinates, length ny.

Functions

build_operations

build_operations(
    centerlines: list,
    half_widths: list[float],
    buffer_m: float,
    threshold: float,
    thin_road_skip_m: float = 0.0,
) -> list[RoadFlattenOperation]

Build a :class:RoadFlattenOperation for each segment above threshold.

Parameters:

Name Type Description Default
centerlines list

Per-road centerline geometries.

required
half_widths list[float]

Per-road half-widths in metres.

required
buffer_m float

Blend-zone width outside road edge.

required
threshold float

Gradient threshold (m/m). 0.0 keeps all segments.

required
thin_road_skip_m float

If > 0, roads narrower than this width (m) are skipped (excluded from flattening). Set to 0.0 to disable.

0.0

Returns:

Type Description
list[RoadFlattenOperation]

Filtered list of :class:RoadFlattenOperation objects.

exceeds_threshold

exceeds_threshold(
    centerline: Geometry, threshold: float
) -> bool

Return True if the max gradient magnitude along centerlinethreshold.

A threshold of 0.0 always returns True (disables filtering).

s2gos_generator.processors.terrain_mesh.terraforming.RoadFlattenOperation

RoadFlattenOperation(
    centerline: LineString | MultiLineString,
    half_width: float,
    buffer_m: float,
)

Flatten terrain cross-slope under a single road segment.

For each vertex inside the influence zone the elevation is blended toward the elevation of the nearest point on the road centerline:

  • Within half_width of the centerline -> fully flattened (alpha = 1).
  • Between half_width and half_width + buffer_m -> linearly blended.
  • Beyond that -> unchanged.

Functions

apply

apply(
    vertices: ndarray,
    elevation_fn: Callable[[ndarray], ndarray],
) -> np.ndarray

Apply flattening. For single-op use; prefer :func:apply_road_flatten_batch when applying multiple operations to avoid recreating shapely points per road.

apply_to_subset

apply_to_subset(
    vertices: ndarray,
    vertex_indices: ndarray,
    inside_points,
    elevation_fn: Callable[[ndarray], ndarray],
) -> None

Apply flattening for a pre-filtered subset of vertices (in-place).

Called by both :meth:apply and :func:apply_road_flatten_batch.

s2gos_generator.processors.terrain_mesh.terraforming.apply_road_flatten_batch

apply_road_flatten_batch(
    vertices: ndarray,
    operations: list[RoadFlattenOperation],
    elevation_fn: Callable[[ndarray], ndarray],
) -> np.ndarray

Apply road-flatten operations efficiently with a single batched elevation sample.

Parameters:

Name Type Description Default
vertices ndarray

(N, 3) mesh vertex array — modified in-place.

required
operations list[RoadFlattenOperation]

List of :class:RoadFlattenOperation to apply.

required
elevation_fn Callable[[ndarray], ndarray]

(M, 2) XY -> (M,) Z elevation sampler.

required

Returns:

Type Description
ndarray

The same vertices array (modified in-place).

s2gos_generator.processors.terrain_mesh.terraforming.make_refinement_predicate

make_refinement_predicate(
    influence_zone: Geometry,
) -> Callable[
    [np.ndarray, np.ndarray, np.ndarray, np.ndarray],
    np.ndarray,
]

Return a vectorised predicate for :class:AdaptiveGrid.refine.

Parameters:

Name Type Description Default
influence_zone Geometry

Merged polygon/multipolygon covering all road buffers.

required

Returns:

Type Description
Callable[[ndarray, ndarray, ndarray, ndarray], ndarray]

predicate(xmin, ymin, xmax, ymax) -> bool[N]

s2gos_generator.processors.terrain_mesh.terraforming.make_roughness_predicate

make_roughness_predicate(
    pyramid: "DemErrorPyramid", tolerance_m: float
) -> Callable[
    [np.ndarray, np.ndarray, np.ndarray, np.ndarray],
    np.ndarray,
]

Predicate returning True for cells whose max plane-residual exceeds tolerance_m.

Parameters:

Name Type Description Default
pyramid 'DemErrorPyramid'

Precomputed DEM error pyramid.

required
tolerance_m float

Max allowed plane-residual in metres before a cell is subdivided. Replaces the old peak-to-peak tolerance; typical values are 0.1–1.0 m depending on scene scale.

required

s2gos_generator.processors.terrain_mesh.terraforming.compute_gradient

compute_gradient(
    elev: ndarray, x: ndarray, y: ndarray
) -> np.ndarray

Compute DEM gradient magnitude in m/m.

Parameters:

Name Type Description Default
elev ndarray

2-D elevation array, shape (ny, nx).

required
x ndarray

1-D x coordinates, length nx.

required
y ndarray

1-D y coordinates, length ny.

required

Returns:

Type Description
ndarray

Gradient magnitude array with the same shape as elev.

s2gos_generator.processors.terrain_mesh.terraforming.TerraformOperation

Bases: Protocol

A terrain modification applied to mesh vertices.

Implementations must provide: - influence_zone: the spatial region this operation may alter. - apply(): modifies vertices in-place and returns the array. - apply_to_subset(): same, but for a pre-filtered vertex subset (used by :func:apply_road_flatten_batch for the STRtree fast path).

Attributes

influence_zone property

influence_zone: Geometry

Region where this operation may modify vertices.

Functions

apply

apply(
    vertices: ndarray,
    elevation_fn: Callable[[ndarray], ndarray],
) -> np.ndarray

Apply terrain modification.

Parameters:

Name Type Description Default
vertices ndarray

(N, 3) array of mesh vertices — may be modified in-place.

required
elevation_fn Callable[[ndarray], ndarray]

maps (M, 2) XY coordinates -> elevation array of length M.

required

Returns:

Type Description
ndarray

Modified vertices array (may be the same object).

apply_to_subset

apply_to_subset(
    vertices: ndarray,
    vertex_indices: ndarray,
    inside_points,
    elevation_fn: Callable[[ndarray], ndarray],
) -> None

Apply modification for a pre-filtered subset of vertices (in-place).

Called by :func:apply_road_flatten_batch to avoid re-creating shapely points per operation when many operations share the same vertex array.

Parameters:

Name Type Description Default
vertices ndarray

Full (N, 3) vertex array — modified in-place.

required
vertex_indices ndarray

Indices into vertices that fall inside this operation's influence zone.

required
inside_points

Shapely point array corresponding to vertex_indices.

required
elevation_fn Callable[[ndarray], ndarray]

maps (M, 2) XY coordinates -> elevation array of length M.

required