Skip to contents

SpatVolume is a class union over SpatVoxel and SpatEnvelope. It exists as a dispatch target for operations that are meaningful on either representation because both determine a 3D domain over a 2D grid: volume, volumetric overlap, vertical extent, printing.

Details

It deliberately asserts no shared structure. The two members store depth in dual roles (layer index vs. cell value), so any operation that touches the depth axis directly should dispatch on the concrete class instead.

See also

SpatVoxel and SpatEnvelope, the two members; envelope_to_voxel() and voxel_to_envelope() convert between them.

Examples

# The same 3D domain in both representations.
fp <- terra::rast(nrows = 1, ncols = 2, xmin = 0, xmax = 2, ymin = 0, ymax = 1)
terra::values(fp) <- c(1, 1)
e <- as_envelope(fp, depth_min = 0, depth_max = 200)
v <- envelope_to_voxel(e, depths = c(0, 100, 200))

# Neither inherits from the other; both belong to the union.
methods::is(e, "SpatVolume")
#> [1] TRUE
methods::is(v, "SpatVolume")
#> [1] TRUE
methods::is(v, "SpatEnvelope")
#> [1] FALSE

# `SpatVolume` is a dispatch target, so a generic written against it accepts
# either representation.
setGeneric("n_depth_layers", function(x) standardGeneric("n_depth_layers"))
#> [1] "n_depth_layers"
setMethod("n_depth_layers", "SpatVolume", function(x) terra::nlyr(x))
n_depth_layers(e)
#> [1] 2
n_depth_layers(v)
#> [1] 3

# But the depth axis itself is stored differently in the two, so anything
# reading depths must dispatch on the concrete class rather than the union.
names(e)
#> [1] "depth_min" "depth_max"
names(v)
#> [1] "presence_depth=0"   "presence_depth=100" "presence_depth=200"