Example
Derived Terrain Layer
Some layers encode data in their pixel values rather than showing an image directly. The Mapbox Terrain-RGB layer stores elevation as a number spread across the red, green, and blue channels. This configuration decodes it, converts elevation into average air pressure, and renders the result in grayscale, then lays it over OpenStreetMap.
Using the Terrain-RGB layer requires a Mapbox access token, supplied through the MAPBOX_KEY environment variable.
|
Configuration
-
YAML
-
JSON
cache:
name: disk
path: ./terrain_cache
layers:
- id: osm
provider:
name: proxy
url: https://tile.openstreetmap.org/{z}/{x}/{y}.png
- id: air_pressure
provider:
name: transform
threads: 8 (1)
formula: | (2)
import "math"
func transform(r, g, b, a uint8) (uint8, uint8, uint8, uint8) {
elevation := -10000 + ((float64(r)*256*256 + float64(g)*256 + float64(b)) * 0.1)
pressure := 101325 * math.Pow(1-.0000225577*elevation, 5.25588)
c := uint8(pressure / 1000)
return c, c, c, 255
}
provider:
name: fallback
primary:
name: proxy
url: https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token={env.MAPBOX_KEY} (3)
secondary:
name: static
color: "0186a0" (4)
- id: air_pressure_over_osm
provider:
name: blend
mode: opacity (5)
opacity: 0.5
providers:
- name: ref (6)
layer: air_pressure
- name: ref
layer: osm
| 1 | A tile has 65,536 pixels. Splitting them across 8 goroutines makes each tile faster to produce at the cost of more CPU per request. |
| 2 | The function is called once per pixel. Darker pixels are lower pressure, meaning higher ground. See Transform. |
| 3 | {env.MAPBOX_KEY} keeps the token out of the configuration file. The pngraw format matters, as other formats can alter the pixel values and so the decoded elevation. |
| 4 | Mapbox returns an error for tiles entirely over the sea. This color decodes to an elevation of 0, so sea level pressure is shown instead of an error. |
| 5 | Mixes the two images half and half rather than drawing one over the other, since both layers are fully opaque. |
| 6 | Each referenced layer is cached on its own, so osm and air_pressure can also be requested directly without generating them again. |
{
"cache": {
"name": "disk",
"path": "./terrain_cache"
},
"layers": [
{
"id": "osm",
"provider": {
"name": "proxy",
"url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
}
},
{
"id": "air_pressure",
"provider": {
"name": "transform",
"threads": 8, (1)
"formula": "import \"math\"\nfunc transform(r, g, b, a uint8) (uint8, uint8, uint8, uint8) {\n elevation := -10000 + ((float64(r)*256*256 + float64(g)*256 + float64(b)) * 0.1)\n pressure := 101325 * math.Pow(1-.0000225577*elevation, 5.25588)\n c := uint8(pressure / 1000)\n return c, c, c, 255\n}\n", (2)
"provider": {
"name": "fallback",
"primary": {
"name": "proxy",
"url": "https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token={env.MAPBOX_KEY}" (3)
},
"secondary": {
"name": "static",
"color": "0186a0" (4)
}
}
}
},
{
"id": "air_pressure_over_osm",
"provider": {
"name": "blend",
"mode": "opacity", (5)
"opacity": 0.5,
"providers": [
{
"name": "ref", (6)
"layer": "air_pressure"
},
{
"name": "ref",
"layer": "osm"
}
]
}
}
]
}
| 1 | A tile has 65,536 pixels. Splitting them across 8 goroutines makes each tile faster to produce at the cost of more CPU per request. |
| 2 | The function is called once per pixel. Darker pixels are lower pressure, meaning higher ground. See Transform. |
| 3 | {env.MAPBOX_KEY} keeps the token out of the configuration file. The pngraw format matters, as other formats can alter the pixel values and so the decoded elevation. |
| 4 | Mapbox returns an error for tiles entirely over the sea. This color decodes to an elevation of 0, so sea level pressure is shown instead of an error. |
| 5 | Mixes the two images half and half rather than drawing one over the other, since both layers are fully opaque. |
| 6 | Each referenced layer is cached on its own, so osm and air_pressure can also be requested directly without generating them again. |
Try it
export MAPBOX_KEY=your-token
tilegroxy test -c terrain.yml
tilegroxy serve -c terrain.yml
The test command confirms all three layers generate before you start the server. Be mindful of the OpenStreetMap tile usage policy.