GDALRaster Processing

gdal_viewshed

What is gdal_viewshed?

gdal_viewshed computes a viewshed from a digital elevation model: given an observer coordinate and observer height, it produces a raster indicating which cells are line-of-sight visible from that point. It supports curvature-of-earth and atmospheric refraction corrections, observer and target heights, and a configurable maximum distance. The output is either a binary visible/invisible raster or a gradient "height above terrain required to see this cell" raster.

Shell
gdal_viewshed [options] -ox <x> -oy <y> <src_dem> <dst_raster>

Commonly used options:

  • -ox <x> / -oy <y> — observer coordinates in the DEM's CRS
  • -oz <z> — observer height above terrain (default 2 m)
  • -tz <z> — target height above terrain (default 0 m)
  • -md <max_distance> — maximum analysis distance (CRS units)
  • -cc <coef> — atmospheric refraction coefficient (default 0.85714; use 1.0 to ignore)
  • -f <format> — output driver
  • -om <NORMAL|DEM|GROUND|ACCUM> — output mode; NORMAL is binary visibility, DEM returns minimum target height required to be visible, GROUND returns the terrain elevation where visible, ACCUM accumulates visibility over multiple calls
  • -vv <value> / -iv <value> / -ov <value> / -ndv <value> — visible, invisible, out-of-range, and NoData values
  • -b <band> — source band

When would you use gdal_viewshed?

Use gdal_viewshed for any single-observer visibility analysis. Typical jobs: determining what terrain is visible from a proposed observation tower (gdal_viewshed -ox 412000 -oy 6100000 -oz 30 -md 10000 dem.tif viewshed.tif), evaluating wind-turbine visual impact from a nearby village, or computing the visible footprint of a mobile-phone mast at 40 metres. Aggregate several runs (or use -om ACCUM) to produce a cumulative visibility surface across many observers.

For meaningful long-range analysis, pass -oz for eye height (1.7 m pedestrian, 30 m tower) and optionally -tz for the height of the thing you are trying to see (0 for ground features, 20 for forest canopy, 50 for a turbine hub). -cc 0.85714 uses GDAL's default refraction model; set to 1.0 to disable refraction if your reference methodology demands geometric LOS only.

FAQs

Why does my viewshed have a jagged edge?

Viewsheds on pixel grids are inherently stair-stepped because each cell is tested as a discrete line-of-sight. The jagged edge is an artefact of DEM resolution and the LOS sampling density. Higher-resolution input DEM or a post-hoc vector smoothing cleans the appearance; do not simplify if the downstream analysis depends on exact cell-accurate visibility.

How do I compute a cumulative viewshed from many observers?

Use -om ACCUM repeatedly: gdal_viewshed -om ACCUM -ox ... -oy ... dem.tif accum.tif accumulates into accum.tif. Or run many single-observer viewsheds and sum them with gdal_calc.py --calc="A+B". The ACCUM mode is generally faster because it updates in place.

What refraction coefficient should I use?

-cc 0.85714 is GDAL's default, matching the commonly cited value of 1/7 for atmospheric refraction. For comparison against methodologies that use other refraction coefficients (e.g. 0.13 in some civil engineering guidelines), set -cc to match. Setting -cc 1.0 disables the curvature-adjusted refraction calculation altogether.

Can I compute a viewshed from a vector of observers?

Not directly — gdal_viewshed takes a single observer per call. Script a loop over your vector points and either ACCUM into one raster or produce per-observer viewsheds for individual analysis. WhiteboxTools and SAGA GIS offer multi-observer viewshed tools natively if you need a single invocation.