Roads Module
Road network visualization using the data layer pipeline.
This module provides efficient road rendering by rasterizing OpenStreetMap road networks as geographic data layers. Roads are automatically aligned with the DEM through the transform pipeline, handling reprojection and downsampling correctly.
Much more efficient than creating individual Blender objects - rasterizes roads in ~5 seconds and automatically handles coordinate transformations.
Quick Start
Simple API for adding roads to terrain:
from src.terrain.roads import add_roads_layer
from examples.detroit_roads import get_roads
# Get roads from OpenStreetMap
roads_geojson = get_roads(bbox)
# Add as a data layer (automatic alignment)
add_roads_layer(
terrain=terrain,
roads_geojson=roads_geojson,
bbox=bbox, # (south, west, north, east) in WGS84
road_types=['motorway', 'trunk', 'primary'],
road_width=3,
colormap_name="viridis"
)
See Combined Render: Full-Featured Example for full example.
Core Functions
- src.terrain.roads.add_roads_layer(terrain, roads_geojson, bbox, resolution=30.0, road_width_pixels=3)[source]
Add roads as a data layer to terrain with automatic coordinate alignment.
This is the high-level API for road integration. Roads are rasterized to a grid with proper geographic metadata and added as a data layer. The library’s data layer pipeline ensures proper alignment even if terrain is downsampled or reprojected.
To color roads, use the multi-overlay color mapping system:
roads_geojson = get_roads(bbox) terrain.add_roads_layer(terrain, roads_geojson, bbox, road_width_pixels=3) terrain.set_multi_color_mapping( base_colormap=lambda dem: elevation_colormap(dem, 'michigan'), base_source_layers=['dem'], overlays=[{ 'colormap': road_colormap, 'source_layers': ['roads'], 'priority': 10, }], ) terrain.compute_colors()
- Parameters:
terrain – Terrain object (must have DEM data layer)
roads_geojson (Dict[str, Any]) – GeoJSON FeatureCollection with road LineStrings
bbox (Tuple[float, float, float, float]) – Bounding box as (south, west, north, east) in WGS84 degrees
resolution (float) – Pixel size in meters for rasterization (default: 30.0)
road_width_pixels (int) – Width of roads in raster pixels (default: 3). Higher values make roads more visible. At 30m resolution, 3 pixels ≈ 90m visual width.
- Raises:
ValueError – If terrain missing DEM data layer
- Return type:
None
High-level function to rasterize and add roads as a data layer. Used in Combined Render: Full-Featured Example.
- src.terrain.roads.rasterize_roads_to_layer(roads_geojson, bbox, resolution=30.0, road_width_pixels=3)[source]
Rasterize GeoJSON roads to a layer grid with proper geographic transform.
Converts vector road data (GeoJSON LineStrings) to a raster grid where each pixel represents road presence/type. The result includes an Affine transform in WGS84 (EPSG:4326) coordinates for proper geographic alignment.
This is the key function that treats roads as a data layer - the output can be added to terrain via add_data_layer() and will automatically align to the DEM through reprojection and resampling.
- Parameters:
roads_geojson (Dict[str, Any]) – GeoJSON FeatureCollection with road LineStrings
bbox (Tuple[float, float, float, float]) – Bounding box as (south, west, north, east) in WGS84 degrees
resolution (float) – Pixel size in meters (default: 30.0). At Detroit latitude, ~30m/pixel gives good detail without excessive memory use.
road_width_pixels (int) – Width of roads in raster pixels (default: 3). Draws roads with thickness instead of 1-pixel lines. Use 1 for thin roads, 3-5 for more visible roads. At 30m resolution, 3 pixels ≈ 90m visual width.
- Returns:
road_grid: 2D array of uint8, values 0=no road, 1-4=road type (motorway > trunk > primary > secondary)
road_transform: rasterio.Affine transform mapping pixels to WGS84 coordinates
- Return type:
Tuple of
Rasterize road geometries to a grid with proper geographic transform.
Returns road grid and Affine transform in WGS84 (EPSG:4326). Use with
add_data_layer()to add to terrain.Example:
road_grid, road_transform = rasterize_roads_to_layer( roads_geojson, bbox=(south, west, north, east), resolution=30.0, # 30m pixels road_types=['motorway', 'trunk'], road_width=3 ) terrain.add_data_layer( "roads", road_grid, road_transform, "EPSG:4326", target_layer="dem" )
Vertex Smoothing
- src.terrain.roads.smooth_road_vertices(vertices, road_mask, y_valid, x_valid, smoothing_radius=2)[source]
Smooth Z coordinates of mesh vertices that are on roads.
Reconstructs a 2D Z grid from vertex positions, applies 2D Gaussian smoothing in grid space, then writes smoothed values back to road vertices only. Non-road vertices are unchanged.
This ensures smoothing follows the spatial layout of the road rather than the arbitrary vertex index order.
- Parameters:
vertices (ndarray) – Mesh vertex positions (N, 3) array with [x, y, z] coords
road_mask (ndarray) – 2D array (H, W) where >0.5 indicates road pixels
y_valid (ndarray) – Array (N,) of y indices mapping vertices to road_mask rows
x_valid (ndarray) – Array (N,) of x indices mapping vertices to road_mask columns
smoothing_radius (int) – Gaussian smoothing sigma (default: 2, use 0 to disable)
- Returns:
Modified vertices array with smoothed Z values on roads. X and Y coordinates are never modified.
- Return type:
Smooth road elevations to eliminate sudden height changes. Used in Combined Render: Full-Featured Example.
Example:
smooth_road_vertices( terrain, road_mask, kernel_size=5, iterations=2 )
- src.terrain.roads.offset_road_vertices(vertices, road_mask, y_valid, x_valid, offset=0.0)[source]
Offset Z coordinates of mesh vertices that are on roads by a fixed amount.
A simpler alternative to smooth_road_vertices. Raises or lowers all road vertices by a constant offset, making roads visually distinct from terrain.
- Parameters:
vertices (ndarray) – Mesh vertex positions (N, 3) array with [x, y, z] coords
road_mask (ndarray) – 2D array (H, W) where >0.5 indicates road pixels
y_valid (ndarray) – Array (N,) of y indices mapping vertices to road_mask rows
x_valid (ndarray) – Array (N,) of x indices mapping vertices to road_mask columns
offset (float) – Z offset to apply to road vertices. Positive = raise, negative = lower. Default: 0.0 (no change)
- Returns:
Modified vertices array with offset Z values on roads. X and Y coordinates are never modified.
- Return type:
Lower road vertices to create embankment effect.
Example:
offset_road_vertices( terrain, road_mask, offset_meters=-2.0 # Lower by 2 meters )
DEM Smoothing
- src.terrain.roads.smooth_dem_along_roads(dem, road_mask, smoothing_radius=2)[source]
Smooth the DEM along roads to reduce elevation detail (GPU-accelerated).
Applies Gaussian smoothing only to road pixels. Non-road pixels are unchanged. The smoothing kernel should be about half the road width.
Uses PyTorch GPU acceleration when available (6x speedup on CUDA).
- Parameters:
- Returns:
Smoothed DEM array (same shape as input)
- Return type:
Smooth DEM elevation data along roads before mesh creation.
Mask Operations
- src.terrain.roads.smooth_road_mask(road_mask, sigma=1.0)[source]
Apply Gaussian blur to road mask for anti-aliased edges (GPU-accelerated).
The Bresenham line algorithm creates stair-step (aliased) edges. Applying Gaussian smoothing creates soft anti-aliased boundaries that render more smoothly, especially after the mask goes through resampling.
Uses PyTorch GPU acceleration when available (6x speedup on CUDA).
- Parameters:
- Returns:
Smoothed road mask as float32 array. Values are now continuous (not binary) and may need thresholding if binary mask is needed.
- Return type:
Smooth road mask to avoid harsh transitions.
Example:
smoothed_mask = smooth_road_mask( road_mask, kernel_size=5, threshold=0.3 )
Colormaps
- src.terrain.roads.road_colormap(road_grid, score=None)[source]
Map roads to a distinctive red color for special material treatment.
The red color (180, 30, 30) is used as a marker so the Blender material shader can identify road pixels and apply a glassy/emissive effect.
- Parameters:
road_grid – 2D array of road values (0=no road, >0=road)
score – Unused, kept for API compatibility.
- Returns:
Array of RGB colors with shape (height, width, 3) as uint8
Map roads to distinctive marker color for shader detection.