Product
Socket Now Supports uv.lock Files
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
@acalcutt/maplibre-contour-pmtiles
Advanced tools
Render contour lines from raster elevation tiles in maplibre-gl-js from pmtiles terrain sources
maplibre-contour-pmtiles is a plugin to render contour lines in MapLibre GL JS from raster-dem
pmtiles sources. It was forked to support pmtiles with http support on the web and http and local supoort in node.js.
Live example #1 (Just Terrain) | Code
Live example #2 (w/ OpenMapTiles Style) | Code | Style
To use it, import the @acalcutt/maplibre-contour-pmtiles package with a script tag:
<script src="https://unpkg.com/@acalcutt/maplibre-contour-pmtiles@latest/dist/maplibre-contour-pmtiles.min.js"></script>
Or as an ES6 module: npm add @acalcutt/maplibre-contour-pmtiles
import mlcontour from "@acalcutt/maplibre-contour-pmtiles";
Then to use, first create a DemSource
and register it with maplibre:
var demSource = new mlcontour.DemSource({
url: "pmtiles://https://url/of/dem/source.pmtiles",
encoding: "mapbox", // "mapbox" or "terrarium" default="terrarium"
maxzoom: 12,
worker: true, // offload isoline computation to a web worker to reduce jank
cacheSize: 100, // number of most-recent tiles to cache
timeoutMs: 10_000, // timeout on fetch requests
});
demSource.setupMaplibre(maplibregl);
When using scripts locally with node, url can also use the format
url: "pmtiles:///local/path/to/pmtiles/source.pmtiles",
url: "pmtiles://C://local//path//to//pmtiles//source.pmtiles",
You should also be able to use a regular non-pmtiles source with
url: "https://url/of/dem/source/{z}/{x}/{y}.png",
Then configure a new contour source and add it to your map:
map.addSource("contour-source", {
type: "vector",
tiles: [
demSource.contourProtocolUrl({
// convert meters to feet, default=1 for meters
multiplier: 3.28084,
thresholds: {
// zoom: [minor, major]
11: [200, 1000],
12: [100, 500],
14: [50, 200],
15: [20, 100],
},
// optional, override vector tile parameters:
contourLayer: "contours",
elevationKey: "ele",
levelKey: "level",
extent: 4096,
buffer: 1,
}),
],
maxzoom: 15,
});
Then add contour line and label layers:
map.addLayer({
id: "contour-lines",
type: "line",
source: "contour-source",
"source-layer": "contours",
paint: {
"line-color": "rgba(0,0,0, 50%)",
// level = highest index in thresholds array the elevation is a multiple of
"line-width": ["match", ["get", "level"], 1, 1, 0.5],
},
});
map.addLayer({
id: "contour-labels",
type: "symbol",
source: "contour-source",
"source-layer": "contours",
filter: [">", ["get", "level"], 0],
layout: {
"symbol-placement": "line",
"text-size": 10,
"text-field": ["concat", ["number-format", ["get", "ele"], {}], "'"],
"text-font": ["Noto Sans Bold"],
},
paint: {
"text-halo-color": "white",
"text-halo-width": 1,
},
});
You can also share the cached tiles with other maplibre sources that need elevation data:
map.addSource("dem", {
type: "raster-dem",
encoding: "terrarium",
tiles: [demSource.sharedDemProtocolUrl],
maxzoom: 13,
tileSize: 256,
});
DemSource.setupMaplibre
uses MapLibre's addProtocol
utility to register a callback to provide vector tile for the contours source. Each time maplibre requests a vector tile:
DemManager
fetches (and caches) the raster-dem image tile and its neighbors so that contours are continuous across tile boundaries.
DemSource
is configured with worker: true
, it uses RemoteDemManager
to spawn worker.ts
in a web worker. The web worker runs LocalDemManager
locally and uses the Actor
utility to send cancelable requests and responses between the main and worker thread.decode-image.ts
decodes the raster-dem image RGB values to meters above sea level for each pixel in the tile.HeightTile
stitches those raw DEM tiles into a "virtual tile" that contains the border of neighboring tiles, aligns elevation measurements to the tile grid, and smooths the elevation measurements.isoline.ts
generates contour isolines from a HeightTile
using a marching-squares implementation derived from d3-contour.vtpbf.ts
encodes the contour isolines as mapbox vector tile bytes.MapLibre sends that vector tile to its own worker, decodes it, and renders as if it had been generated by a server.
There are a lot of parameters you can tweak when generating contour lines from elevation data like units, thresholds, and smoothing parameters. Pre-generated contour vector tiles require 100+gb of storage for each variation you want to generate and host. Generating them on-the-fly in the browser gives infinite control over the variations you can use on a map from the same source of raw elevation data that maplibre uses to render hillshade.
maplibre-contour-pmtiles is licensed under the BSD 3-Clause License. It includes code adapted from:
FAQs
Render contour lines from raster elevation tiles in maplibre-gl-js from pmtiles terrain sources
The npm package @acalcutt/maplibre-contour-pmtiles receives a total of 18 weekly downloads. As such, @acalcutt/maplibre-contour-pmtiles popularity was classified as not popular.
We found that @acalcutt/maplibre-contour-pmtiles demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.