Skip to content

BUILD_CONTOURS

Generates contour line vector tiles from a LAS/LAZ point cloud. The input is rasterized into a Digital Surface Model, smoothed to reduce noise, then passed through gdal_contour to extract isolines. The resulting lines are simplified, classified as major or minor, and smoothed again with a Chaikin corner-cutting pass to produce publication-quality contours.

The final output is a pair of vector tile packages — MBTiles and PMTiles v3 — ready for direct delivery to web mapping clients.

Typical use: generating contour maps from LiDAR or MBES surveys for web publishing, engineering deliverables, and GIS workflows.


Contract

TypeBUILD_CONTOURS
Acceptsinput_las: las
Producescontours_mbtiles: mbtiles, contours_pmtiles: pmtiles
Paramsall optional†

† all parameters have executor defaults and may be omitted.


Inputs

SlotTypeDescription
input_laslasSource point cloud dataset

Outputs

SlotTypeDescription
contours_mbtilesmbtilesVector tile package (MBTiles) — contours layer
contours_pmtilespmtilesVector tile package (PMTiles v3) — contours layer

Parameters

All parameters are optional. Omitting them applies the defaults shown below.

NameTypeDefaultDescription
resolutionnumber1DSM raster cell size in CRS units
output_typestring"mean"DSM height aggregation per cell — mean suppresses single-return outliers better than max; other options: min, idw, count, stdev, all
smoothing_factornumber5Raster smoothing factor: the DSM is downsampled to resolution × smoothing_factor before contouring. Higher values produce smoother, more generalised contours
contour_intervalnumber5Elevation interval between contour lines in CRS units
major_interval_multipliernumber5Every Nth contour is classified as major. With contour_interval=5 and major_interval_multiplier=5, every 25-unit contour is major
simplify_tolerancenumber1ogr2ogr -simplify tolerance in CRS units — reduces vertex count while preserving shape
chaikin_iterationsnumber3Number of Chaikin corner-cutting passes. Each pass doubles the vertex count and rounds corners. Values above 4–5 produce diminishing returns and significantly larger geometries

Units note: all defaults with a horizontal or vertical dimension (resolution, contour_interval, simplify_tolerance) are tuned for LAS data in US survey feet (ftUS). The executor does not auto-detect units — adjust these values when processing metric datasets.


Output layer schema

Both tile packages expose a single vector layer named contours with three fields:

FieldTypeDescription
idintegerRow number ordered by elevation
elevfloatContour elevation in CRS units
typestring"major" or "minor" — based on whether elev is divisible by contour_interval × major_interval_multiplier

What it does internally

  1. Downloads the input LAS from MinIO

  2. Builds a PDAL pipeline using readers.laswriters.gdal with the configured resolution and output_type, writing raw_dsm.tif; stamps nodata with gdal_edit.py -a_nodata -9999

  3. Smooths the DSM: gdalwarp downsamples to resolution × smoothing_factor using average resampling, then upsamples back to resolution using cubic spline → smoothed_dsm.tif

  4. Runs gdal_contour -a elev -i {contour_interval} -f GPKG on the smoothed DSM → raw_contours.gpkg

  5. Runs ogr2ogr -simplify {simplify_tolerance} with the SQLite dialect: assigns a stable id via ROW_NUMBER() OVER (ORDER BY elev), classifies type as major/minor, and simplifies geometry → contours.gpkg

  6. Applies Chaikin corner-cutting in-place (Python/OGR): replaces each segment with two points at 25% and 75%, repeated chaikin_iterations times — handles both LINESTRING and MULTILINESTRING geometries

  7. Reprojects the smoothed contours to EPSG:4326 with ogr2ogr -t_srs EPSG:4326 -lco RFC7946=YES -lco WRITE_BBOX=YEScontours_4326.geojson

  8. Runs tippecanoe -zg --drop-densest-as-needed --extend-zooms-if-still-droppingcontours.mbtiles

    The bundled tippecanoe (v1.36.0) predates native PMTiles output and always writes MBTiles regardless of output extension. PMTiles conversion is handled in the next step.

  9. Converts MBTiles → PMTiles v3 with pmtiles convert (the go-pmtiles CLI). Verifies the output magic number (PMTiles) as a sanity check → contours.pmtiles

  10. Uploads both files to MinIO and returns artifact descriptors with md5sum hashes and ogrinfo metadata captured from the GeoJSON


Recipe usage

json
{
  "id": "build_contours",
  "type": "BUILD_CONTOURS",
  "inputs":  { "input_las": "job:input_las" },
  "outputs": {
    "contours_mbtiles": "step:build_contours.contours_mbtiles",
    "contours_pmtiles": "step:build_contours.contours_pmtiles"
  }
}

With explicit params (all optional):

json
"params": {
  "build_contours": {
    "resolution": 1,
    "output_type": "mean",
    "smoothing_factor": 5,
    "contour_interval": 5,
    "major_interval_multiplier": 5,
    "simplify_tolerance": 1,
    "chaikin_iterations": 3
  }
}

Artifact storage paths

text
artifacts/job_{id}/build_contours/contours.mbtiles
artifacts/job_{id}/build_contours/contours.pmtiles

  • BUILD_HILLSHADE_DSM — shares the same LAS-to-DSM rasterization first stage; produces a raster instead of vector tiles
  • BUILD_COLORED_DSM — shares the same first stage; produces a color-relief raster
  • BUILD_COLORED_HILLSHADE_DSM — shares the same first stage; produces a colored shaded-relief raster