SpaDES (version 1.3.1)

distanceFromEachPoint: Calculate distances and directions between many points and many grid cells

Description

This is a modification of distanceFromPoints for the case of many points. This version can often be faster for a single point because it does not return a RasterLayer. This is different than distanceFromPoints because it does not take the minimum distance from the set of points to all cells. Rather this returns the every pair-wise point distance. As a result, this can be used for doing inverse distance weightings, seed rain, cumulative effects of distance-based processes etc. If memory limitation is an issue, maxDistance will keep memory use down, but with the consequences that there will be a maximum distance returned. This function has the potential to use a lot of memory if there are a lot of from and to points.

Usage

distanceFromEachPoint(from, to = NULL, landscape, angles = NA_real_,
  maxDistance = NA_real_, cumulativeFn = NULL, distFn = function(dist)
  1/(1 + dist), cl, ...)

.pointDistance(from, to, angles = NA, maxDistance = NA_real_)

Arguments

from

matrix with 2 or 3 columns, x and y, representing x and y coordinates of "from" cell, and optional "id" which will be matched with "id" from to

to

matrix with 2 or 3 columns (or optionally more, all of which will be returned), x and y, representing x and y coordinates of "to" cells, and optional "id" which will be matched with "id" from from. Default is all cells.

landscape

RasterLayer. optional. This is only used if to is NULL, in which case all cells are considered to

angles

Logical. If TRUE, then the function will return angles in radians, as well as distances.

maxDistance

Numeric in units of number of cells. The algorithm will build the whole surface (from from to to), but will remove all distances that are above this distance. Using this will keep memory use down.

cumulativeFn

A function that can be used to incrementally accumulate values in each to location, as the function iterates through each from. See Details.

distFn

A function. This can be a function of landscape, fromCells, toCells, and dist. If cumulativeFn is supplied, then this will be used to convert the distances to some other set of units that will be accumulated by the cumulativeFn. See Details and examples.

cl

A cluster object. Optional. This would generally be created using parallel::makeCluster or equivalent. This is an alternative way, instead of beginCluster(), to use parallelism for this function, allowing for more control over cluster use.

...

Any additional objects needed for distFn.

Value

A sorted matrix on id with same number of rows as to, but with one extra column, "dists" indicating the distance between from and to.

Details

This function is cluster aware. If there is a cluster running, it will use it. To start a cluster use beginCluster, with N being the number of cores to use. See examples in experiment.

If the user requires an id (indicating the from cell for each to cell) to be returned with the fuction, the user must add an identifier to the from matrix, such as "id". Otherwise, the function will only return the coordinates and distances.

distanceFromEachPoint calls .pointDistance, which is not intended to be called directly by the user.

This function has the potential to return a very large object, as it is doing pairwise distances (and optionally directions) between from and to. If there are memory limitations because there are many from and many to points, then cumulativeFn and distFn can be used. These two functions together will be used iteratively through the from points. The distFn should be a transformation of distances to be used by the cumulativeFn function. For example, if distFn is 1/(1+x), the default, and cumulativeFn is `+`, then it will do a sum of inverse distance weights. See examples.

See Also

rings, cir, distanceFromPoints, which can all be made to do the same thing, under specific combinations of arguments. But each has different primary use cases. Each is also faster under different conditions. For instance, if maxDistance is relatively small compared to the number of cells in the landscape, then cir will likely be faster. If a minimum distance from all cells in the landscape to any cell in from, then distanceFromPoints will be fastest. This function scales best when there are many to points or all cells are used to = NULL (which is default).

Examples

Run this code
# NOT RUN {
library(raster)
N <- 2
distRas <- raster(extent(0,40,0,40), res = 1)
coords <- cbind(x = round(runif(N, xmin(distRas), xmax(distRas)))+0.5,
                y = round(runif(N, xmin(distRas), xmax(distRas)))+0.5)

# inverse distance weights
dists1 <- distanceFromEachPoint(coords, landscape = distRas)
indices <- cellFromXY(distRas,dists1[,c("x","y")])
invDist <- tapply(dists1[,"dists"], indices, function(x) sum(1/(1+x))) # idw function
distRas[] <- as.vector(invDist)
if (interactive()) {
  clearPlot()
  Plot(distRas)
}

# With iterative summing via cumulativeFn to keep memory use low, with same result
dists1 <- distanceFromEachPoint(coords[, c("x", "y"), drop = FALSE],
                                landscape = distRas, cumulativeFn = `+`)
idwRaster <- raster(distRas)
idwRaster[] <- dists1[,"val"]
if (interactive()) Plot(idwRaster)

all(idwRaster[] == distRas[]) # TRUE

# A more complex example of cumulative inverse distance sums, weighted by the value
#  of the origin cell
ras <- raster(extent(0,34, 0,34), res = 1, val = 0)
rp <- randomPolygons(ras, numTypes = 10) ^ 2
N <- 15
cells <- sample(ncell(ras), N)
coords <- xyFromCell(ras, cells)
distFn <- function(landscape, fromCell, dist) landscape[fromCell] / (1 + dist)

# beginCluster(3) # can do parallel
dists1 <- distanceFromEachPoint(coords[, c("x", "y"), drop = FALSE],
               landscape = rp, distFn = distFn, cumulativeFn = `+`)

# endCluster() # if beginCluster was run
idwRaster <- raster(ras)
idwRaster[] <- dists1[,"val"]
if (interactive()) {
  clearPlot()
  Plot(rp, idwRaster)
  sp1 <- SpatialPoints(coords)
  Plot(sp1, addTo="rp")
  Plot(sp1, addTo="idwRaster")
}

# }

Run the code above in your browser using DataLab