is_los_visible() is an interface to GDAL's line-of-sight algorithm
implemented by GDALIsLineOfSightVisible() in the Algorithms C API
(https://gdal.org/en/stable/api/gdal_alg.html). It checks line of sight
across a DEM surface using a Bresenham algorithm. The function can operate
pairwise on sets of input points, or one-to-many. Requires GDAL >= 3.9.
Usage
is_los_visible(
dem,
ptsA,
ptsB,
band = 1L,
srsA = NULL,
srsB = NULL,
ZinterpA = "RELATIVE_TO_DEM",
ZinterpB = "RELATIVE_TO_DEM",
quiet = FALSE
)Arguments
- dem
Either a character string giving the filename of the DEM raster, or an object of class
GDALRasterfor the DEM.- ptsA
A data frame or numeric matrix containing geospatial point coordinates, or point geometries (with Z values) as a list of WKB raw vectors or character vector of WKT strings. If data frame or matrix, the number of columns must be three (x, y, z). May be also be given as a numeric vector for one point (
c(x, y, z)). If this argument contains a single point, then line of sight will be checked between it and each point inptsB, otherwiselength(ptsA)must equallength(ptsB), and line of sight will be checked pairwise.- ptsB
The second set of points, as described above for
ptsA.- band
An integer value specifying the band number in
demto use. Defaults to1L.- srsA
An optional character string specifying the spatial reference system for
ptsA. May be in WKT format or any of the formats supported bysrs_to_wkt(). If this argument isNULL(the default), thenptsAare assumed to be in the same coordinate reference system asdem. Otherwise,ptsAwill be reprojected fromsrsAto the spatial reference ofdem.- srsB
An optional character string specifying the spatial reference system for
ptsB(see above). Defaults toNULL. If notNULL,ptsBwill be reprojected fromsrsBto the spatial reference ofdem.- ZinterpA
A character string specifying the interpretation of the Z values for
ptsA. The default is"RELATIVE_TO_DEM", in which case the location heights ofptsAare obtained by querying the DEM surface and adding the Z value given inptsA. Alternatively, the Z values can be interpreted as absolute heights to be used unmodified by setting this argument to"ACTUAL".- ZinterpB
A character string specifying the interpretation of the Z values for
ptsB. See the description above forZinterpA.- quiet
A logical value with default of
FALSE. If set toTRUE, will suppress a progress bar and informational messages.
Value
A logical vector of length(ptsB), TRUE for each pair of points
that are within line of sight, otherwise FALSE.
The checks are done pairwise if (length(ptsA) == length(ptsB)), or
one-to-many if length(ptsA) == 1 and multiple points are given in ptsB.
Note
Input coordinates must be within the raster bounds. NA will be returned if
either coordinate is outside the raster extent, or is missing a Z value.
The GDAL documentation notes that line of sight is computed in raster coordinate space, and thus may not be appropriate for some applications. For example, datasets referenced against geographic coordinates at high latitudes may have issues.
At the time of writing (GDAL 3.9 through 3.12.1), a point exactly on the
surface of the DEM is never visible with GDALIsLineOfSightVisible(), even
if viewed from a point directly above. For a detailed description, see
https://github.com/OSGeo/gdal/issues/12458. A workaround for that case
could be to set a small but negligible postive Z value (if using
"RELATIVE_TO_DEM") for points that are intended to be on the DEM surface,
if appropriate for the use case.
Examples
if (FALSE) { # gdal_version_num() >= gdal_compute_version(3, 9, 0)
dem <- system.file("extdata/storml_elev.tif", package="gdalraster")
## no reprojection, the point coordinates are in the same projection as DEM
## one-to-many
ptA <- c(324625.0, 5104724.0, 1.7)
ptsB <-c(324803.0, 5104517.0, 10,
325286.0, 5102923.0, 10,
323847.0, 5104538.0, 10)
ptsB <- matrix(ptsB, nrow = 3, ncol = 3, byrow = TRUE)
is_los_visible(dem, ptA, ptsB)
## pairwise, same ptA location with varying height
ptsA <- c(324625.0, 5104724.0, 1,
324625.0, 5104724.0, 10,
324625.0, 5104724.0, 1000)
ptsA <- matrix(ptsA, nrow = 3, ncol = 3, byrow = TRUE)
is_los_visible(dem, ptsA, ptsB)
## WKB points
(ptsA_wkb <- g_create("POINT", ptsA))
# as WKT
g_wk2wk(ptsA_wkb)
# or as ISO WKT
g_wk2wk(ptsA_wkb, as_iso = TRUE)
is_los_visible(dem, ptsA_wkb, ptsB)
## reprojecting ptsA, and the DEM given as a dataset object
(ds <- new(GDALRaster, dem))
ptsA_wkb_wgs84 <- g_transform(ptsA_wkb, ds$getSpatialRef(), "WGS84")
g_wk2wk(ptsA_wkb_wgs84)
is_los_visible(ds, ptsA_wkb_wgs84, ptsB, srsA = "WGS84")
## read ptsB from a vector dataset, use original ptA
dsn <- system.file("extdata/storml_los_pts_b.geojson", package="gdalraster")
(lyr <- new(GDALVector, dsn))
(features <- lyr$fetch(-1))
is_los_visible(ds, ptA, features$geom, srsB = lyr$getSpatialRef(),
ZinterpB = "ACTUAL")
ds$close()
lyr$close()
}