This function calculates the least-cost distances from a point to all (or some) of the cells in a surrounding raster object, returning a raster. This is the least-cost distance equivalent of distanceFromPoints.

lcp_from_point(
  origin,
  surface,
  destination = NULL,
  cost = NULL,
  graph = NULL,
  use_all_cores = FALSE,
  verbose = TRUE
)

Arguments

origin

A matrix which defines the coordinates (x, y) of the point from which to calculate least-cost distances. Unlike distanceFromPoints, only a single point is expected.

surface

A raster across which to implement least-cost distance calculations. If the cost matrix is derived from lcp_costs (see below), there are some constraints on the form of this surface; namely, equal resolution in x and y directions and a Universal Transverse Mercator coordinate reference system with units of metres. The surface defines the properties of the returned raster (see Value).

destination

(optional) An matrix of destination coordinates; an integer vector of cell IDs; or function that defines a subset of destination cells, given their surface value, for which to implement calculations. For example destination = function(x) x > 0 would restrict least-cost distance calculations to cells of the surface that have a value of more than zero. Other cells are set to NA. This can improve computational efficiency.

cost

(optional) A sparse dsCMatrix-class matrix that defines the cost of movement between connected cells (see lcp_costs). If unsupplied, if the graph is also unsupplied (see below), a matrix of distances from lcp_costs is computed internally and taken to define the cost surface. For this to be appropriate, the surface should have a Universal Transverse Mercator projection, with equal resolution in the x and y directions and units of metres (see surface, above). If a graph is supplied, cost is unnecessary.

graph

(optional) A graph object that defines cell nodes and edge costs for connected cells within the surface (see lcp_graph_surface). If supplied, the calculation of the cost surface and the construction of the graph stages in the computation of least-cost distances are skipped (see Details), which is desirable in iterative applications.

use_all_cores

A logical input that defines whether or not to parallelise least-cost distance calculations across all cores. This is passed to get_distance_matrix which implements calculations.

verbose

A logical input that defines whether or not to print messages to the console to relay function progress.

Value

The function returns a raster in which each cell represents the least-cost distance from a specified origin to that cell. The origin is assigned a value of zero. Any cells excluded by the destination filter have a value of NA.

Details

This function implements routines provided via flapper and the cppRouting package to calculate least-cost distances. The main steps are:

  1. The calculation of distances between adjacent cells (i.e., cost, if not supplied, via lcp_costs);

  2. The construction of a graph that defines cell connections from the origin to surrounding cells on the surface as a network (via makegraph);

  3. The calculation of shortest distances between the origin and surrounding cells from the graph (via get_distance_matrix);

  4. The expression of shortest distances as a raster which is returned.

See also

This function is similar to distanceFromPoints, which returns a Raster* of Euclidean distances. For iterative applications across the same surface, lcp_costs and lcp_graph_surface can be implemented to define the cost matrix and the graph object outside of this function. These can be passed to lcp_from_point, skipping the need to recompute these objects. For shortest-distances and/or paths between specific origin and destination coordinates, the lcp_over_surface can be used. The particle filtering movement algorithms in flapper (i.e., pf) can implement this approach to ensure that movement paths are biologically realistic.

Author

Edward Lavender

Examples

#### Step (1): Define example origin
proj <- sp::CRS(SRS_string = "EPSG:4326")
proj_utm <- sp::CRS(SRS_string = "EPSG:32629")
origin <- matrix(c(-5.616, 56.388), ncol = 2)
origin <- sp::SpatialPoints(origin, proj)
origin <- sp::spTransform(origin, proj_utm)

#### Step (2): Select and process surface
# We will focus on an area within the dat_gebco bathymetry raster
boundaries <- raster::extent(707884.6, 709884.6, 6253404, 6255404)
blank <- raster::raster(boundaries, res = c(5, 5))
r <- raster::resample(dat_gebco, blank)
#> Warning: aggregation factor is larger than the number of columns
#> Warning: aggregation factor is larger than the number of rows
#> Error in .intersectExtent(x, y, validate = TRUE): Objects do not intersect

#### Example (1): Implement function using default options
lcp_dist <- lcp_from_point(origin = origin, surface = r)
#> flapper::lcp_from_point() called (@ 2023-08-29 15:43:56)... 
#> Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'ncell': object 'r' not found
## Visualise outputs
pp <- par(mfrow = c(2, 2))
# Plot surface
raster::plot(r)
#> Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'r' not found
# Examine Euclidean distances from point
raster::plot(raster::distanceFromPoints(r, origin))
#> Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': error in evaluating the argument 'x' in selecting a method for function 'couldBeLonLat': object 'r' not found
# Compare to shortest distances
raster::plot(lcp_dist)
#> Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'lcp_dist' not found
par(pp)

if (flapper_run_slow) {
  #### Example (2): Implement function across specific destinations
  ## Supply destination cell coordinates/IDs directly
  # E.g., consider distances to cells shallower than 125 m
  destination_cells <- raster::Which(r < 125, cells = TRUE, na.rm = TRUE)
  lcp_dist <- lcp_from_point(
    origin = origin,
    surface = r,
    destination = destination_cells
  )
  raster::plot(lcp_dist)
  ## Use a function instead to consider distances to cells shallower than 125 m
  filter_destination_cells <- function(x) x < 125
  lcp_dist <- lcp_from_point(
    origin = origin,
    surface = r,
    destination = filter_destination_cells
  )
  raster::plot(lcp_dist)

  #### Example (3): Define cost surfaces for LCP calculations outside of function
  # This can be implemented internally, but we compute it here via lcp_costs().
  # Note this imposes restrictions on the nature of the surface, such as equal
  # ... resolution, which we have forced above.
  costs <- lcp_costs(r)
  cost <- costs$dist_total
  lcp_dist <- lcp_from_point(
    origin = origin,
    surface = r,
    destination = filter_destination_cells,
    cost = cost
  )

  #### Example (4): Supply a graph object
  graph <- lcp_graph_surface(surface = r, cost = cost)
  lcp_dist <- lcp_from_point(origin = origin, surface = r, graph = graph)

  #### Example (5): Implement algorithm in parallel via use_all_cores
  lcp_dist <- lcp_from_point(origin = origin, surface = r, use_all_cores = TRUE)
}
#> Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'Which': object 'r' not found