Relief: the Mercator correction and vertical exaggeration
argus-atlas 0.3.2.dev6+g77cc8fd @ 77cc8fdPyPI (opens in new tab)Source (opens in new tab)Changelog (opens in new tab)
Imported from docs/relief.md on argus-atlas's dev branch at that commit. Fixes go upstream, not here.
Why relief flattens away from the equator
controls warps the DEM onto the Web Mercator (EPSG:3857) canvas, then runs gdaldem hillshade and gdaldem slope on it. Web Mercator keeps shapes but stretches horizontal distances by 1/cos(latitude). On the canvas a hill is that much wider while its height in metres stays the same, so a slope computed there is too shallow:
Before 0.3.0, a bake near the poles got a much flatter hillshade, and so a flatter painting, than the same terrain at the equator.
What atlas does about it
Since 0.3.0 the heights are multiplied by the stretch at the canvas centre before shading (--z-factor auto, the default). That restores the true slope, so the same mountain range is shaded the same way in Iceland or in Réunion. It is a per-canvas constant: across a 1024 px chunk at z10 the stretch changes by well under 1 %.
On top of that, --vertical-exaggeration (--ve) is the cartographer's knob. Relief maps commonly exaggerate gentle terrain 1.5–3× so that low hills read at all:
z = mercator correction × vertical exaggeration
The hillshade gets gdaldem hillshade -z <z>. The slope gets gdaldem slope -s <1/z>, because slope has no -z and dividing horizontal distances by z gives the same result.
They are on controls, chunk and chunks, and on POST /controls as z_factor ("auto" or a number) and vertical_exaggeration.
Where it is recorded
job.jsonhas areliefrecord:mode(autoorfixed), the canvas-centrelatitude, thebasefactor (the correction, or the fixed value),vertical_exaggeration, and the effectivez_factor. Thegdaldemargv incommandscarries the same numbers. A job from before 0.3.0 has norelief, which means z = 1.- A style recipe has
z_factor(default"auto") andvertical_exaggeration(default 1). Onchunkandchunks, the flags override the recipe's values. Both fields are part of the recipe digest, so a recipe with other relief is a different recipe: its chunks are not "done" for this one, and a re-run re-bakes them. - Chunks painted over differently scaled hillshades must not be stitched together.
chunkrefuses a neighbour with other relief instead of pasting it into the seam margin, andmosaicrefuses a style dir that mixes reliefs. Underauto, chunks match when their exaggeration matches, because the correction follows each chunk's own latitude.
Old blocks
A style dir baked before 0.3.0 has no correction. To extend it seamlessly, pin the old relief in its recipe with "z_factor": 1, or pass --z-factor off. A recipe at z 1 with no exaggeration keeps the digest its chunks were baked under, so they still count as done and as neighbours. To get the corrected relief, bake into a new style dir.