cir {SpaDES.tools} | R Documentation |
Identify pixels in a circle or ring (doughnut) around an object.
Description
Identify the pixels and coordinates that are at a (set of) buffer distance(s)
of the objects passed into coords
.
This is similar to sf::st_buffer
but much faster and without the georeferencing information.
In other words, it can be used for similar problems, but where speed is important.
This code is substantially adapted from PlotRegionHighlighter::createCircle
.
Usage
cir(
landscape,
coords,
loci,
maxRadius = ncol(landscape)/4,
minRadius = maxRadius,
allowOverlap = TRUE,
allowDuplicates = FALSE,
includeBehavior = "includePixels",
returnDistances = FALSE,
angles = NA_real_,
returnAngles = FALSE,
returnIndices = TRUE,
closest = FALSE,
simplify = TRUE
)
Arguments
landscape |
Raster on which the circles are built. |
coords |
Either a matrix with 2 (or 3) columns, |
loci |
Numeric. An alternative to |
maxRadius |
Numeric vector of length 1 or same length as |
minRadius |
Numeric vector of length 1 or same length as |
allowOverlap |
Logical. Should duplicates across id be removed or kept. Default TRUE. |
allowDuplicates |
Logical. Should duplicates within id be removed or kept. Default FALSE. This is useful if the actual x, y coordinates are desired, rather than the cell indices. This will increase the size of the returned object. |
includeBehavior |
Character string. Currently accepts only |
returnDistances |
Logical. If |
angles |
Numeric. Optional vector of angles, in radians, to use. This will create
"spokes" outward from |
returnAngles |
Logical. If |
returnIndices |
Logical or numeric. If |
closest |
Logical. When determining non-overlapping circles, should the function
give preference to the closest |
simplify |
logical. If |
Details
This function identifies all the pixels as defined by a donut
with inner radius minRadius
and outer radius of maxRadius
.
The includeBehavior
defines whether the cells that intersect the radii
but whose centres are not inside the donut are included includePixels
or not excludePixels
in the returned pixels identified.
If this is excludePixels
, and if a minRadius
and
maxRadius
are equal, this will return no pixels.
Value
A matrix
with 4 columns, id
, indices
,
x
, y
. The x
and y
indicate the exact coordinates of
the indices
(i.e., cell number) of the landscape
associated with the ring or circle being identified by this function.
See Also
rings()
which uses spread
internally.
cir
tends to be faster when there are few starting points, rings
tends to be faster
when there are many starting points. cir
scales with maxRadius^2
and coords
.
Another difference between the two functions is that rings
takes the centre of the pixel
as the centre of a circle, whereas cir
takes the exact coordinates.
See example. For the specific case of creating distance surfaces from specific
points, see distanceFromEachPoint()
, which is often faster.
For the more general GIS buffering, see sf::st_buffer
.
Examples
library(data.table)
library(terra)
origDTThreads <- data.table::setDTthreads(2L)
origNcpus <- options(Ncpus = 2L)
set.seed(1462)
# circle centred
ras <- rast(ext(0, 15, 0, 15), res = 1, val = 0)
middleCircle <- cir(ras)
ras[middleCircle[, "indices"]] <- 1
circlePoints <- vect(middleCircle[, c("x", "y")])
if (interactive()) {
# clearPlot()
terra::plot(ras)
terra::plot(circlePoints, add = TRUE)
}
# circles non centred
ras <- randomPolygons(ras, numTypes = 4)
n <- 2
agent <- vect(cbind(x = stats::runif(n, xmin(ras), xmax(ras)),
y = stats::runif(n, xmin(ras), xmax(ras))))
cirs <- cir(ras, agent, maxRadius = 15, simplify = TRUE) ## TODO: empty with some seeds! e.g. 1642
cirsSP <- vect(cirs[, c("x", "y")]) ## TODO: error with some seeds! e.g. 1642
cirsRas <- rast(ras)
cirsRas[] <- 0
cirsRas[cirs[, "indices"]] <- 1
if (interactive()) {
terra::plot(ras)
terra::plot(cirsRas, add = TRUE, col = c("transparent", "#00000055"))
terra::plot(agent, add = TRUE)
terra::plot(cirsSP, add = TRUE)
}
# Example comparing rings and cir
hab <- rast(system.file("extdata", "hab1.tif", package = "SpaDES.tools"))
radius <- 4
n <- 2
coords <- vect(cbind(x = stats::runif(n, xmin(hab), xmax(hab)),
y = stats::runif(n, xmin(hab), xmax(hab))))
# cirs
cirs <- cir(hab, coords, maxRadius = rep(radius, length(coords)), simplify = TRUE)
ras1 <- rast(hab)
ras1[] <- 0
ras1[cirs[, "indices"]] <- cirs[, "id"]
if (interactive()) {
terra::plot(ras1)
}
# rings
loci <- cellFromXY(hab, crds(coords))
cirs2 <- rings(hab, loci, maxRadius = radius, minRadius = radius - 1, returnIndices = TRUE)
ras2 <- rast(hab)
ras2[] <- 0
ras2[cirs2$indices] <- cirs2$id
if (interactive()) {
terra::plot(c(ras1, ras2))
}
hab <- rast(system.file("extdata", "hab2.tif", package = "SpaDES.tools"))
cirs <- cir(hab, coords, maxRadius = 44, minRadius = 0)
ras1 <- rast(hab)
ras1[] <- 0
cirsOverlap <- data.table::data.table(cirs)[, list(sumIDs = sum(id)), by = indices]
ras1[cirsOverlap$indices] <- cirsOverlap$sumIDs
if (interactive()) {
terra::plot(ras1)
}
# Provide a specific set of angles
ras <- rast(ext(0, 330, 0, 330), res = 1)
ras[] <- 0
n <- 2
coords <- cbind(x = stats::runif(n, xmin(ras), xmax(ras)),
y = stats::runif(n, xmin(ras), xmax(ras)))
circ <- cir(ras, coords, angles = seq(0, 2 * pi, length.out = 21),
maxRadius = 200, minRadius = 0, returnIndices = FALSE,
allowOverlap = TRUE, returnAngles = TRUE)
# clean up
data.table::setDTthreads(origDTThreads)
options(Ncpus = origNcpus)