Viewshed analysis is a powerful spatial analysis technique used to determine visible areas from a specific observation point, based on the surrounding terrain. This technique uses elevation data to identify areas that have direct line of sight to the observer location while accounting for terrain and/or feature obstructions. The resulting viewshed can be represented as a binary raster, where each pixel indicates whether the corresponding location is visible or not from the observer point. This type of analysis provides a spatial representation of terrain visibility that can be applied to a wide range of scenarios, including telecommunications planning, infrastructure placement, environmental assessment, and landscape analysis.
The viewshed analysis workflow can be broken down into a few key steps:
This tutorial explores how viewshed analysis can be performed using CATALYST's SEENARE algorithm. This function determines the visible pixels in an elevation channel of an input image from a user-defined viewpoint. The output is a binary raster channel where the visible pixels are represented by 1 and obstructed areas by 0. The input file must be a geocoded image and is expected to have an elevation channel with geocoded coordinates.
Before performing a viewshed analysis, the elevation data should be prepared to ensure it is suitable for the visibility calculation. The DEM should cover the area of interest and contain valid elevation values with an appropriate spatial resolution for the analysis. For viewshed analysis, either a Digital Surface Model (DSM) or a Digital Terrain Model (DTM) can be used, depending on the level of obstruction to be accounted for.
As a DSM includes above-ground features such as buildings, trees, and other structures, it allows them to be considered as potential obstructions. On the other hand, a DTM represents the bare-earth terrain and should be used when visibility is intended to account for terrain obstructions only.
CATALYST Professional enables users to generate elevation models using OrthoEngine, among other tools. The tutorials below cover the detailed steps involved in the process:
Since the elevation data is expected to be stored as a raster channel in the input file, an elevation channel must be added if one does not already exist. The PCIMOD algorithm can be used to create an empty raster channel in the input file, while the III algorithm is then used to transfer the elevation data from the DEM into the newly created channel. This prepares the input file so that the elevation data can be used in subsequent processing.
The SEENARE algorithm is used here to evaluate the terrain visibility from a specified observation point. The algorithm takes the elevation channel (dbec) as its input and writes the resulting visibility information to a designated output channel within the same raster file (dboc). The viewpoint is defined in the demvpt parameter as geocoded xy-coordinates and the height above the surface. Finally, radius defines the extent, in georeferenced units, at which the algorithm should search for visibility. When it is left empty, the entire image is searched.
from pci.seenare import seenare
from pci.pcimod import pcimod
from pci.iii import iii
from pci.api import datasource as ds
file = r"H:\Tutorials\Viewshed Analysis\irvine.pix"
with ds.open_dataset(file, ds.eAM_READ) as dataset:
chan_num = dataset.chan_count
# Add 2 empty 16-bit signed channels to file
pciop = 'ADD'
pcival = [0, 2, 0, 0]
pcimod(file, pciop, pcival)
# If DEM isn't in the input image
dem = r"H:\Tutorials\Viewshed Analysis\dem.pix"
fili = dem
filo = file
dbic = [1]
dboc = [chan_num + 1]
dbiw = []
dbow = []
options = ""
iii(fili, filo, dbic, dboc, dbiw, dbow, options)
# Viewshed Analysis
dbec = [chan_num + 1] # elevation channel
dboc = [chan_num + 2] # output viewshed channel
demvpt = [436506, 3727485, 211] # DEM view point
radius = [] # search entire image
seenare(file, dbec, dboc, demvpt, radius)
When viewsheds need to be generated for multiple observation points, the analysis can be automated using a batch script and a CSV file containing the viewpoint coordinates and elevation values. The Python Pandas library is used to read the CSV into a DataFrame and iterate through each viewpoint, updating the demvpt parameter in each iteration. This approach eliminates the need to manually configure and run the analysis for each viewpoint and provides an efficient way to process a large number of observation locations consistently.
import pandas as pd
from pci.seenare import seenare
from pci.pcimod import pcimod
from pci.iii import iii
from pci.api import datasource as ds
file = r"H:\Tutorials\Viewshed Analysis\irvine.pix"
with ds.open_dataset(file, ds.eAM_READ) as dataset:
chan_num = dataset.chan_count
# csv of x, y geocoded coordinates, and z height above surface
obs_points = r"H:\Tutorials\Viewshed Analysis\observer_points.csv"
obs = pd.read_csv(obs_points)
rw_num = len(obs)
# Add empty 16-bit signed channels to file
pciop = 'ADD'
pcival = [0, rw_num + 1, 0, 0]
pcimod(file, pciop, pcival)
# If DEM isn't in the input image
dem = r"H:\Tutorials\Viewshed Analysis\dem.pix"
dem_chn = chan_num + rw_num + 1
# Add DEM to input file
fili = dem
filo = file
dbic = [1]
dboc = [dem_chn]
dbiw = []
dbow = []
options = ""
iii(fili, filo, dbic, dboc, dbiw, dbow, options)
for row in obs.itertuples(index=True):
viewshed_chan = chan_num + row.Index + 1
x = row.x
y = row.y
z = row.z
# Viewshed Analysis
dbec = [dem_chn] # elevation channel
dboc = [viewshed_chan] # output viewshed channel
demvpt = [x, y, z] # DEM view point
radius = [] # search entire image
seenare(file, dbec, dboc, demvpt, radius)

