| Title: | A Lightweight Implementation of the Geomorphon Algorithm |
|---|---|
| Description: | A lightweight implementation of the geomorphon terrain form classification algorithm of Jasiewicz and Stepinski (2013) <doi:10.1016/j.geomorph.2012.11.005> based largely on the 'GRASS GIS' 'r.geomorphon' module. This implementation employs a novel algorithm written in C++ and 'RcppParallel'. |
| Authors: | Andrew Brown [aut, cre] (ORCID: <https://orcid.org/0000-0002-4565-533X>) |
| Maintainer: | Andrew Brown <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.3.1 |
| Built: | 2026-05-25 07:50:29 UTC |
| Source: | https://github.com/brownag/rgeomorphon |
forms_matrix objectThis constructor function wraps a 9x9 integer matrix and associates it with a set of levels, creating a 'forms_matrix' object.
forms_matrix(x, levels = get_forms_grass_enum())forms_matrix(x, levels = get_forms_grass_enum())
x |
Integer. A 9x9 matrix. |
levels |
Named integer vector. Map of integer values to their string
names. Default: |
This function is intended for custom classification matrix based on positive
and negative overlooks. See forms_matrix_get() for a convenient accessor
for the standard classification systems with 4, 5, 6 or 10 forms.
An object of class c("forms_matrix", "matrix", "array").
library(terra) library(rgeomorphon) # default values x <- forms_matrix_get(num_forms = 10, levels = get_forms_grass_enum()) # inspect x # create a 9-class system where PEAK is combined with RIDGE x[x == 2] <- 3 a <- get_forms_grass_enum() a <- a[!names(a) == "G_PK"] # create a forms matrix with custom levels fm <- forms_matrix(x, a) # run geomorphon algorithm SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" # include original forms, positive, and negative output res <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE, forms = TRUE, positive = TRUE, negative = TRUE ) # apply custom classification to positive and negative res2 <- geomorphon_theme( forms_matrix_apply( x = res[[c("positive", "negative")]], rcl = fm ) ) # compare with default terra::plot(terra::rast(c(`10 form`=res$forms, `9 form`=res2)))library(terra) library(rgeomorphon) # default values x <- forms_matrix_get(num_forms = 10, levels = get_forms_grass_enum()) # inspect x # create a 9-class system where PEAK is combined with RIDGE x[x == 2] <- 3 a <- get_forms_grass_enum() a <- a[!names(a) == "G_PK"] # create a forms matrix with custom levels fm <- forms_matrix(x, a) # run geomorphon algorithm SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" # include original forms, positive, and negative output res <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE, forms = TRUE, positive = TRUE, negative = TRUE ) # apply custom classification to positive and negative res2 <- geomorphon_theme( forms_matrix_apply( x = res[[c("positive", "negative")]], rcl = fm ) ) # compare with default terra::plot(terra::rast(c(`10 form`=res$forms, `9 form`=res2)))
forms_matrix to Positive and Negative OverlooksThis function applies a forms_matrix to reclassify a SpatRaster object with
2 layers containing positive and negative overlooks.
forms_matrix_apply( x, rcl = forms_matrix_get(), positive = "positive", negative = "negative", ... )forms_matrix_apply( x, rcl = forms_matrix_get(), positive = "positive", negative = "negative", ... )
x |
SpatRaster containing two layers with names specified in |
rcl |
forms_matrix. Matrix to use for classification of x. Rows are "negative" and columns are "positive". |
positive |
Character. Layer name of positive count. Default:
|
negative |
Character. Layer name of negative count. Default:
|
... |
Additional arguments passed to |
A SpatRaster containing the classification result.
library(terra) library(rgeomorphon) SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" res <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE, forms = TRUE, ternary = TRUE, positive = TRUE, negative = TRUE ) res2 <- terra::rast(lapply(c(4, 5, 6), function(n) { geomorphon_theme( forms_matrix_apply( x = res[[c("positive", "negative")]], rcl = forms_matrix_get(n) ) ) })) names(res2) <- c("forms4", "forms5", "forms6") terra::plot(c(res, res2))library(terra) library(rgeomorphon) SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" res <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE, forms = TRUE, ternary = TRUE, positive = TRUE, negative = TRUE ) res2 <- terra::rast(lapply(c(4, 5, 6), function(n) { geomorphon_theme( forms_matrix_apply( x = res[[c("positive", "negative")]], rcl = forms_matrix_get(n) ) ) })) names(res2) <- c("forms4", "forms5", "forms6") terra::plot(c(res, res2))
forms_matrix for Geomorphon ClassificationGets one of the internally defined forms matrices. A form matrix is defined for the classic 10-form output (default; Jasiewicz & Stepinski, 2013) as well as three simplified classes: 4-form, 5-form, and 6-form (Masetti et al., 2018)
forms_matrix_get(num_forms = 10, levels = get_forms_grass_enum())forms_matrix_get(num_forms = 10, levels = get_forms_grass_enum())
num_forms |
Integer. The number of forms to classify, one of |
levels |
Named integer with values between 0 and 10 corresponding to
form class labels. Default: |
For creating custom classification systems see the forms_matrix() constructor.
An object of class forms_matrix
Stepinski, T., Jasiewicz, J., 2011, Geomorphons - a new approach to classification of landform, in : Eds: Hengl, T., Evans, I.S., Wilson, J.P., and Gould, M., Proceedings of Geomorphometry 2011, Redlands, 109-112. Available online: https://www.geomorphometry.org/uploads/pdf/pdf2011/StepinskiJasiewicz2011geomorphometry.pdf
Jasiewicz, J., Stepinski, T., 2013, Geomorphons - a pattern recognition approach to classification and mapping of landforms, Geomorphology, vol. 182, 147-156. (doi:10.1016/j.geomorph.2012.11.005)
Masetti, G., Mayer, L. A., & Ward, L. G. 2018, A Bathymetry- and Reflectivity-Based Approach for Seafloor Segmentation. Geosciences, 8(1), 14. (doi:10.3390/geosciences8010014)
forms_matrix_get()forms_matrix_get()
Applies standard class names and colors to a SpatRaster, or creates a factor matrix. Input values should be integers between 1 and 10.
geomorphon_categories() geomorphon_colors() geomorphon_theme(x, forms = "forms10")geomorphon_categories() geomorphon_colors() geomorphon_theme(x, forms = "forms10")
x |
A SpatRaster or matrix object. |
forms |
character. One of: |
When x is a matrix the result is a factor using geomorphon_categories().
Values are integers 1 to 10 and labels are the geomorphon form names.
A SpatRaster or matrix object with geomorphon class names (and colors for SpatRaster) applied.
geomorphon_theme(1:10)geomorphon_theme(1:10)
geomorphon_chunks_needed() is a heuristic for number of tiles needed to
calculate geomorphons on larger-than-memory rasters. Allows for scaling by
number of parallel workers, a multiplicative factor for the memory needs, and
a multiplicative factor for worker needs.
geomorphon_chunks_needed( x, workers = Sys.getenv("R_RGEOMORPHON_N_WORKERS", unset = 1), scl_need = Sys.getenv("R_RGEOMORPHON_MEM_SCALE_NEED", unset = 10), scl_workers = Sys.getenv("R_RGEOMORPHON_MEM_SCALE_WORKERS", unset = 1), pow_total = Sys.getenv("R_RGEOMORPHON_MEM_POWER", unset = 0.5) )geomorphon_chunks_needed( x, workers = Sys.getenv("R_RGEOMORPHON_N_WORKERS", unset = 1), scl_need = Sys.getenv("R_RGEOMORPHON_MEM_SCALE_NEED", unset = 10), scl_workers = Sys.getenv("R_RGEOMORPHON_MEM_SCALE_WORKERS", unset = 1), pow_total = Sys.getenv("R_RGEOMORPHON_MEM_POWER", unset = 0.5) )
x |
A SpatRaster object. |
workers |
integer. Number of parallel workers. Default uses value of
environment variable |
scl_need |
numeric. Scaling factor for memory needs. Default uses
value of environment variable |
scl_workers |
numeric. Scaling factor for each worker. Default uses
value of environment variable |
pow_total |
numeric. Exponent for scaling total number of chunks.
Default uses value of environment variable |
integer. Number of tile chunks to divide x into.
data("salton", package = "rgeomorphon") x <- terra::rast(salton) terra::ext(x) <- attr(salton, "extent") terra::crs(x) <- attr(salton, "crs") geomorphon_chunks_needed(x)data("salton", package = "rgeomorphon") x <- terra::rast(salton) terra::ext(x) <- attr(salton, "extent") terra::crs(x) <- attr(salton, "crs") geomorphon_chunks_needed(x)
'Rcpp' implementation of the geomorphon terrain classification system based on 'r.geomorphon' algorithm of Jasiewicz and Stepinski (2013) from 'GRASS GIS'.
geomorphons( elevation, filename = NULL, search = 3, skip = 0, flat_angle_deg = 1, dist = 0, comparison_mode = "anglev1", tdist = 0, forms = TRUE, ternary = FALSE, positive = FALSE, negative = FALSE, use_meters = FALSE, nodata_val = NA_integer_, xres = NULL, yres = xres, simplify = FALSE, LAPPLY.FUN = lapply, nchunk = geomorphon_chunks_needed(elevation) )geomorphons( elevation, filename = NULL, search = 3, skip = 0, flat_angle_deg = 1, dist = 0, comparison_mode = "anglev1", tdist = 0, forms = TRUE, ternary = FALSE, positive = FALSE, negative = FALSE, use_meters = FALSE, nodata_val = NA_integer_, xres = NULL, yres = xres, simplify = FALSE, LAPPLY.FUN = lapply, nchunk = geomorphon_chunks_needed(elevation) )
elevation |
matrix or SpatRaster object. Digital Elevation Model values. It is STRONGLY recommended to use a grid in a projected coordinate system. |
filename |
character. Output filename. Default |
search |
numeric. User input for search radius (default: |
skip |
numeric. User input for skip radius (default: |
flat_angle_deg |
numeric. Flatness angle threshold in degrees.
Default: |
dist |
numeric. Flatness distance (default: |
comparison_mode |
Character. One of |
tdist |
numeric. Terrain distance factor. When greater than 0, overrides
Z tolerance from angular logic. Default: |
forms |
character. Number of geomorphon forms to identify. One of
|
ternary |
logical. Include "ternary" output? Default: |
positive |
logical. Include "positive" output? Default: |
negative |
logical. Include "negative" output? Default: |
use_meters |
Logical. Default: |
nodata_val |
numeric. NODATA value. Default: |
xres |
numeric. X grid resolution (used only when |
yres |
numeric. Y grid resolution (used only when |
simplify |
logical. If result is length |
LAPPLY.FUN |
An |
nchunk |
Number of tile chunks to use. Default: |
List of SpatRaster or matrix of geomorphon algorithm outputs. When
more than one of forms, ternary, positive, negative are set the
result is a list. For one result type, and default simplify argument, the
result is the first (and only) element of the list.
The algorithm assumes planar distances and angles are calculated based on cell resolutions, so it is strongly recommended that elevation data be in a projected coordinate system.
For reliable geomorphon classification, especially near study area
boundaries, it is recommended to use a raster that includes a buffer of at
least search + 1 cells around the area of interest. This implementation
utilizes all available DEM data up to the specified search radius.
A buffer of search + skip + 1 cells is automatically applied when
processing SpatRaster input, as this is necessary to avoid edge effects when
processing large rasters in tiles. Matrix input is not altered.
For Digital Elevation Models (DEMs) that are too large to fit into available
memory, rgeomorphon employs an automatic tiled processing workflow. This
method breaks the large raster into a grid of smaller, manageable chunks that
are processed sequentially.
The premise of this approach is the use of buffered tiles. To ensure seamless results and avoid edge artifacts, a buffer of surrounding data is added to each chunk before the geomorphon calculation is performed. This provides the necessary neighborhood of cells for the algorithm to work correctly. After each tile is processed, the buffer region is removed from the result. Finally, the clean, processed tiles are mosaicked back together into a single, complete output raster that perfectly matches the extent of the original input DEM.
This entire workflow is handled internally by the main geomorphons()
function, which can also leverage parallel processing to speed up the
operation on multi-core systems. See the vignette on parallel processing with
'future' package.
The number of chunks needed can be controlled by setting several environment variables. These variables are read by the function at runtime.
By default, the function assumes a single worker, scales the estimated memory needed by a factor of 10, and applies the square root to the total number of chunks. This can be replicated with the following settings:
Sys.setenv(R_RGEOMORPHON_N_WORKERS = 1) Sys.setenv(R_RGEOMORPHON_MEM_SCALE_NEED = 10) Sys.setenv(R_RGEOMORPHON_MEM_SCALE_WORKERS = 1) Sys.setenv(R_RGEOMORPHON_MEM_POWER = 0.5)
You can customize the tiling behavior by setting the environment variables to different values. For example, to use four workers, scale memory needs by a factor of five, apply a worker scaling factor of two, and a power of 1.5 to the total, you would set the following:
Sys.setenv(R_RGEOMORPHON_N_WORKERS = 4) Sys.setenv(R_RGEOMORPHON_MEM_SCALE_NEED = 5) Sys.setenv(R_RGEOMORPHON_MEM_SCALE_WORKERS = 2) Sys.setenv(R_RGEOMORPHON_MEM_POWER = 1.5)
This implementation achieves very high agreement with the classification logic of 'GRASS GIS' 'r.geomorphon' when using equivalent parameters and data in a projected coordinate system.
'r.geomorphon' employs a row buffering strategy which can, for cells near the edges of a raster, result in a truncated line-of-sight compared to the full raster extent. This may lead GRASS to classify edge-region cells differently or as NODATA where this implementation may produce a more 'valid' geomorphon form given the available data.
More information about the 'r.geomorphon' module can be found in the GRASS GIS manual: https://grass.osgeo.org/grass-stable/manuals/r.geomorphon.html
Stepinski, T., Jasiewicz, J., 2011, Geomorphons - a new approach to classification of landform, in : Eds: Hengl, T., Evans, I.S., Wilson, J.P., and Gould, M., Proceedings of Geomorphometry 2011, Redlands, 109-112. Available online: https://www.geomorphometry.org/uploads/pdf/pdf2011/StepinskiJasiewicz2011geomorphometry.pdf
Jasiewicz, J., Stepinski, T., 2013, Geomorphons - a pattern recognition approach to classification and mapping of landforms, Geomorphology, vol. 182, 147-156. (doi:10.1016/j.geomorph.2012.11.005)
geomorphon_theme() geomorphon_chunks_needed()
library(terra) library(rgeomorphon) SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" system.time({ rg <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE ) }) plot(c(dem, rg))library(terra) library(rgeomorphon) SEARCH = 7 # outer search radius (cells) SKIP = 1 # inner skip radius (cells) DIST = 0 # flatness distance (cells) FLAT = 1 # flat angle threshold MODE = "anglev1" # comparison mode ## classic volcano elevation data data("volcano", package = "datasets") # construct and georeference a SpatRaster object dem <- terra::flip(terra::rast(volcano)) terra::crs(dem) <- terra::crs("EPSG:27200") terra::ext(dem) <- c(2667400, 2668010, 6478700, 6479570) names(dem) <- "Elevation (meters)" system.time({ rg <- geomorphons( dem, search = SEARCH, skip = SKIP, dist = DIST, flat = FLAT, comparison_mode = MODE ) }) plot(c(dem, rg))
Controls how the 'forms_matrix' object is displayed in the console.
## S3 method for class 'forms_matrix' print(x, show_values = FALSE, ...)## S3 method for class 'forms_matrix' print(x, show_values = FALSE, ...)
x |
The |
show_values |
A logical value. If |
... |
Additional arguments passed to print (not used here). |
Invisibly returns the original object x.
print(forms_matrix_get(num_forms = 4))print(forms_matrix_get(num_forms = 4))
Matrix derived from one foot contours of the Salton Sea floor. These data were
created with the vertical datum NGVD29 and NAD83 California Teale Albers
(EPSG:3110) projection. Each value in the matrix represents the elevation, in
feet, of a 300 m x 300 m cell. Cell values are interpolated using a thin
plate spline fit to an exhaustive sample of contour line vertices.
saltonsalton
matrix, with cells representing X, Y grid locations, and attributes
"crs" (containing WKT2019 string with coordinate reference system
information) and "extent" (named numeric of length 4, containing xmin,
xmax, ymin, ymax)
California Division of Fish and Wildlife. 2007. Bathymetric Contours (1 foot) - Salton Sea (ds426). Available online: https://map.dfg.ca.gov/metadata/ds0426.html
str(salton) # construct and georeference a SpatRaster object dem <- terra::rast(salton) terra::crs(dem) <- attr(salton, "crs") terra::ext(dem) <- attr(salton, "extent") names(dem) <- "Elevation (feet)" demstr(salton) # construct and georeference a SpatRaster object dem <- terra::rast(salton) terra::crs(dem) <- attr(salton, "crs") terra::ext(dem) <- attr(salton, "extent") names(dem) <- "Elevation (feet)" dem