Short answer
A terrain cross section is an elevation-versus-distance plot sampled from a DEM along a chosen line. You draw the line, sample the raster at regular intervals (ideally at the DEM cell size), and plot the surface profile; for a geological cross section you then hang subsurface interpretations — contacts, faults, borehole logs — below that surface on the same section plane. The two judgment calls that decide whether it is useful are sampling density (too coarse and you miss terrain breaks) and vertical exaggeration (necessary for low relief, but it distorts apparent dip).
This covers the sampling math, exaggeration, a QGIS and a GDAL/PostGIS workflow, building a geological section, and the pitfalls.
What a profile samples
Given a polyline from A to B and a DEM, the profile is the function elevation(distance) along the line. The tool densifies the line into points spaced at some step s, reads the DEM value at each point (nearest-cell or bilinear), and records cumulative distance. The honest sampling step is the DEM cell size: sampling finer than the cell size just interpolates the same cells and invents nothing; sampling coarser than the cell size skips ridges and gullies between samples.
So for a 10 m DEM, step ~10 m. For a long regional section over a 30 m DEM, 30 m is correct; densifying to 1 m gives a smoother-looking but no more accurate line.
The sampling rule (nearest vs bilinear) matters at fine scale: bilinear gives a smoother profile by blending the four surrounding cells, nearest preserves exact DEM values (useful when you must reproduce a known cell elevation). For visual sections, bilinear; for QA against raw cells, nearest.
Vertical exaggeration
Real terrain is mostly far wider than it is tall, so a 1:1 profile of a 5 km transect with 80 m of relief is a nearly flat line. Vertical exaggeration (VE) scales the vertical axis: VE = (vertical scale) / (horizontal scale). At VE = 5x, 1 m of elevation occupies the screen space of 5 m of horizontal distance.
Two rules:
- Always label the VE. An unlabeled exaggerated section misleads about slope.
- Exaggeration distorts angles. A true 10-degree dip drawn at 5x VE appears far steeper (apparent dip ≈ atan(5 × tan 10°) ≈ 41 degrees). For structural cross sections where dip angles must be read, prefer 1:1 (no exaggeration) so bedding and fault dips are geometrically correct; reserve exaggeration for low-relief geomorphic display only.
Worked workflow in QGIS
QGIS includes a dedicated Elevation Profile panel (View > Elevation Profile):
- Set the DEM as an elevation source: in the layer's Elevation properties, set it to Represents elevation surface.
- Open the Elevation Profile panel, choose the DEM, and draw the profile line on the canvas.
- The panel plots elevation vs distance live; toggle vertical exaggeration in the panel toolbar.
- Add other layers (e.g., point layers with Z, or vector geology) as elevation sources to overlay them on the same section.
- Export the profile as an image or the underlying points/lines for a layout.
For a repeatable, non-interactive sample, use the Processing tool Draped (set Z value from raster) on a densified line (native:densifygeometry with an interval = cell size), then read the Z values.
Worked workflow with GDAL and PostGIS
For scripted, reproducible sections, sample explicitly.
GDAL point query for a single coordinate:
gdallocationinfo -valonly -geoloc dem_utm.tif 412300 5650120
PostGIS, sampling a profile line every 10 m and returning distance + elevation:
WITH line AS (
SELECT ST_Segmentize(geom, 10.0) AS geom
FROM sections WHERE id = 1
),
pts AS (
SELECT (dp).path[1] AS i, (dp).geom AS pt
FROM line, ST_DumpPoints(line.geom) dp
)
SELECT
i,
ST_Distance(pt, ST_StartPoint((SELECT geom FROM line))) AS dist_m,
ST_Value(d.rast, pt) AS elev_m
FROM pts
JOIN dem d ON ST_Intersects(d.rast, pts.pt)
ORDER BY i;
Keep the line and raster in the same projected CRS (e.g., EPSG:32633) so dist_m and elev_m are both true meters and VE is meaningful. The output table feeds straight into a plotting step or a CAD/illustration cross section.
Building a geological cross section
A terrain profile is the roof of a geological section. To complete it:
- Fix the section line and datum. Choose the line perpendicular to regional strike where possible, so true dips project with minimal distortion. Record start/end coordinates and the vertical datum.
- Plot the ground surface from the DEM samples (1:1 VE for structural work).
- Project nearby data onto the plane. Boreholes, dip readings, and contacts within a swath of the line are projected perpendicularly onto it; note the projection distance, since data far off-line introduces error.
- Draw subsurface contacts and faults consistent with surface dips and borehole intercepts, honoring apparent-dip geometry on the section plane (apparent dip < true dip unless the line is exactly down-dip).
- Keep one vertical reference for surface and subsurface; mixing ellipsoidal and orthometric heights, or different VEs between surface and structure, breaks the geometry.
Common pitfalls and why they happen
- Coarse, blocky profile. The sampling step is larger than the cell size, skipping terrain. Set step = cell size.
- Misleading slopes. Vertical exaggeration applied but unlabeled, or used on a structural section where dips must be read. Label VE; use 1:1 for dip-critical sections.
- Profile distances in degrees. The line and DEM are in EPSG:4326, so distance is in degrees, not meters. Reproject to a metric CRS first.
- Surface and subsurface in different datums. Borehole collars in orthometric height plotted against an ellipsoidal-height DEM, or vice versa, shift the whole section vertically. Unify the vertical reference.
- Projecting distant data onto the line. Boreholes far from the section appear at wrong relative positions because apparent dip and offset are ignored. Limit the projection swath and record it.
QA and validation
- Endpoint elevations on the profile should match
gdallocationinfovalues at A and B. - Total horizontal length equals the line's true length in projected meters.
- No vertical spikes at NoData; confirm the line does not cross voids or set NoData handling.
- Apparent vs true dip check: if the section is oblique to strike, verify that drawn dips are apparent dips, not true dips copied directly.
- State VE, CRS, vertical datum, DEM source, and projection swath in the section caption.
Bathyl perspective
A cross section is where a 2D map becomes an explicit 3D interpretation, and small inconsistencies — a wrong datum, a hidden exaggeration — quietly corrupt the geometry. Bathyl samples profiles at the DEM cell size in a projected CRS, defaults to 1:1 vertical exaggeration for any section where dips are read, and unifies the vertical reference across surface and subsurface so the section is geometrically defensible.
Related reading
- Raster Cell Alignment and Snap Raster Concepts
- When Contours Are Better Than Hillshade
- Borehole Data in GIS
- Terrain intelligence