Skip to content

Commit d9c35ac

Browse files
authored
Merge pull request #335 from r-spatialecology/main
landscapemetrics 2.2
2 parents 8c31a0a + 0091fa9 commit d9c35ac

22 files changed

+351
-73
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: landscapemetrics
33
Title: Landscape Metrics for Categorical Map Patterns
4-
Version: 2.1.4
4+
Version: 2.2
55
Authors@R: c(person("Maximilian H.K.", "Hesselbarth",
66
role = c("aut", "cre"),
77
email = "[email protected]",

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export(proj_info)
172172
export(raster_to_points)
173173
export(rcpp_get_nearest_neighbor)
174174
export(sample_lsm)
175+
export(scale_sample)
175176
export(show_cores)
176177
export(show_correlation)
177178
export(show_lsm)

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# landscapemetrics 2.2
2+
* New functions
3+
* Adding `scale_sample` again
4+
* Improvements
5+
* Better handling of point features
6+
17
# landscapemetrics 2.1.4
28
* Various
39
* Adding `landscape_as_list()` method for `PackedSpatRaster`

R/construct_buffer.R

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
#'
33
#' @description Internal function to construct plot area around coordinates
44
#'
5-
#' @param coords SpatVector, sf object or 2-column matrix with coordinates of sample points
6-
#' @param shape String specifying plot shape. Either "circle" or "square"
5+
#' @param coords Point geometry as SpatVector or sf object or 2-column matrix with coordinates.
6+
#' @param shape String specifying plot shape. Either "circle" or "square".
77
#' @param size Size of sample plot. Equals the radius for circles or the
8-
#' side-length for squares in map units
8+
#' side-length for squares in map units.
99
#' @param return_vec If TRUE, vector objects are returned.
1010
#' @param crs The coordinate reference system used for vector objects.
1111
#' @param verbose Print warning messages.
@@ -28,7 +28,6 @@ construct_buffer <- function(coords, shape , size, return_vec = TRUE, crs="", ve
2828
if (verbose) {
2929

3030
if (ncol(coords) != 2) {
31-
3231
warning("'coords' should be a two column matrix including x- and y-coordinates.",
3332
call. = FALSE)
3433
}

R/extract_lsm.R

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#' @description Extract metrics
44
#'
55
#' @param landscape A categorical raster object: SpatRaster; Raster* Layer, Stack, Brick; stars or a list of SpatRasters.
6-
#' @param y 2-column matrix with coordinates or sf point geometries.
6+
#' @param y Point geometry as SpatVector or sf object or 2-column matrix with coordinates.
77
#' @param extract_id Vector with id of sample points. If not provided, sample
88
#' points will be labelled 1...n.
99
#' @param metric Abbreviation of metrics (e.g. 'area').
@@ -138,13 +138,14 @@ extract_lsm_internal <- function(landscape, y, extract_id, metric, name, type, w
138138

139139
# calculate metrics
140140
# can we somehow calculate only the patches we actually want?
141+
# MH: Extract id and set all others to NA?
141142
metrics <- calculate_lsm(landscape,
142143
what = metrics_list,
143144
directions = directions,
144145
verbose = verbose,
145146
progress = progress, ...)
146147

147-
# only patchs that contain a sample point
148+
# only patches that contain a sample point
148149
extract_metrics <- merge(x = metrics, y = point_id,
149150
by = "id", all.x = FALSE, all.y = FALSE, sort = FALSE)
150151

R/points_as_mat.R

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#'
33
#' @description Points as matrix
44
#'
5-
#' @param pts SpatVector points or sf object
5+
#' @param pts Point geometry as SpatVector or sf object.
66
#'
77
#' @details
88
#' Converts sf points to coordinates matrix
@@ -15,14 +15,13 @@
1515
points_as_mat = function(pts) {
1616

1717
# convert to coords if sf object is provided
18-
if (inherits(x = pts, what = "sf") | inherits(x = pts, what = "sfc") | inherits(x = pts, what = "sfg") |
19-
inherits(x = pts, what = "SpatialPoints") | inherits(x = pts, what = "SpatVector")) {
18+
if (inherits(x = pts, what = c("sf", "sfc", "sfg", "SpatialPoints", "SpatVector"))) {
2019

2120
# convert to terra
2221
pts <- methods::as(pts, "SpatVector")
2322

2423
# check of points
25-
if (terra::geomtype(pts) != "points") stop("landscapemetrics currently only supports point or polygon features.",
24+
if (terra::geomtype(pts) != "points") stop("landscapemetrics currently only supports point features.",
2625
call. = FALSE)
2726

2827
# get coords
@@ -34,7 +33,7 @@ points_as_mat = function(pts) {
3433
} else if (inherits(x = pts, what = "matrix")) {
3534

3635
# return error if not just two cols
37-
if (ncol(pts) != 2) stop("Please provide a matrix with coords, point or polygon object.", call. = FALSE)
36+
if (ncol(pts) != 2) stop("Please provide a matrix with coords or point object.", call. = FALSE)
3837

3938
return(pts)
4039

R/sample_lsm.R

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#' @description Sample metrics
44
#'
55
#' @param landscape A categorical raster object: SpatRaster; Raster* Layer, Stack, Brick; stars or a list of SpatRasters.
6-
#' @param y 2-column matrix with coordinates or sf point geometries.
6+
#' @param y 2-column matrix with coordinates or spatial object.
77
#' @param plot_id Vector with id of sample points. If not provided, sample
88
#' points will be labelled 1...n.
99
#' @param shape String specifying plot shape. Either "circle" or "square"
@@ -25,7 +25,7 @@
2525
#' landscape boundary. Therefore, we report the actual clipped sample plot area relative
2626
#' in relation to the theoretical, maximum sample plot area e.g. a sample plot only half
2727
#' within the landscape will have a `percentage_inside = 50`. Additionally, if the polygon
28-
#' representing the sample plot is smaller than the cell size of the raster,
28+
#' representing the sample plot is smaller than the cell size of the raster,
2929
#' the `percentage_inside` may exceed 100%.Please be aware that the
3030
#' output is slightly different to all other `lsm`-function of `landscapemetrics`.
3131
#'
@@ -106,16 +106,16 @@ sample_lsm_int <- function(landscape, y, plot_id, shape, size,
106106

107107
}
108108

109-
# check if y is sf object
110-
if (inherits(x = y, what = "sf") | inherits(x = y, what = "sfc") | inherits(x = y, what = "sfg") |
111-
inherits(x = y, what = "SpatialPolygons") | inherits(x = y, what = "SpatVector")) {
109+
# check if y is spatial object
110+
if (inherits(x = y, what = c("sf", "sfc", "sfg", "SpatialPoints", "SpatialPolygons", "SpatVector"))) {
112111

113112
# convert to terra
114113
y <- methods::as(y, "SpatVector")
115114

116115
# get crs
117116
crs <- terra::crs(y)
118117

118+
# points provided
119119
if (terra::geomtype(y) == "points") {
120120

121121
if (is.null(size) | size == 0) stop("Please provide size argument size > 0.", call. = FALSE)
@@ -125,7 +125,7 @@ sample_lsm_int <- function(landscape, y, plot_id, shape, size,
125125

126126
}
127127

128-
# y should be matrix or points
128+
# y should be matrix
129129
} else if (inherits(x = y, what = "matrix")) {
130130

131131
if (is.null(size)) stop("Please provide size argument.", call. = FALSE)
@@ -135,12 +135,12 @@ sample_lsm_int <- function(landscape, y, plot_id, shape, size,
135135

136136
} else {
137137

138-
stop("Please provide a matrix with coords, points or polygons object.", call. = FALSE)
138+
stop("Please provide a matrix with coords or spatial object.", call. = FALSE)
139139

140140
}
141141

142142
# check if y is a polygon
143-
if (terra::geomtype(y) != "polygons") stop("Please provide polygon object.", call. = FALSE)
143+
if (terra::geomtype(y) != "polygons") stop("Please provide a matrix with coords or spatial object.", call. = FALSE)
144144

145145
# check if length is identical if ids are provided
146146
if (!is.null(plot_id)) {
@@ -165,57 +165,59 @@ sample_lsm_int <- function(landscape, y, plot_id, shape, size,
165165
warning_messages <- character(0)
166166

167167
# loop through each sample point and calculate metrics
168-
result <- withCallingHandlers(expr = {do.call(rbind, lapply(X = 1:number_plots,
169-
FUN = function(current_plot) {
168+
result <- withCallingHandlers(expr = {
169+
do.call(rbind, lapply(X = 1:number_plots, FUN = function(current_plot) {
170170

171-
# print progess using the non-internal name
172-
if (progress) {
171+
# print progess using the non-internal name
172+
if (progress) {
173173

174-
cat("\r> Progress sample plots: ", current_plot, "/", number_plots)
175-
}
174+
cat("\r> Progress sample plots: ", current_plot, "/", number_plots)
176175

177-
# crop sample plot
178-
landscape_mask <- terra::crop(x = landscape, y = y[current_plot, ], mask = TRUE)
176+
}
179177

180-
# calculate actual area of sample plot
181-
area <- lsm_l_ta_calc(landscape_mask, directions = 8)
178+
# crop sample plot
179+
landscape_mask <- terra::crop(x = landscape, y = y[current_plot, ], mask = TRUE)
182180

183-
# calculate lsm
184-
result_current_plot <- calculate_lsm(landscape = landscape_mask,
185-
verbose = verbose,
186-
progress = FALSE,
187-
...)
181+
# calculate actual area of sample plot
182+
area <- lsm_l_ta_calc(landscape_mask, directions = 8)
188183

189-
# add plot id 1...n
190-
if (is.null(plot_id)) {
184+
# calculate lsm
185+
result_current_plot <- calculate_lsm(landscape = landscape_mask,
186+
verbose = verbose,
187+
progress = FALSE,
188+
...)
191189

192-
result_current_plot$plot_id <- current_plot
190+
# add plot id 1...n
191+
if (is.null(plot_id)) {
193192

194-
# add plot_id
195-
} else {
196-
result_current_plot$plot_id <- plot_id[current_plot]
197-
}
193+
result_current_plot$plot_id <- current_plot
198194

199-
# all cells are NA
200-
if (all(is.na(terra::values(landscape_mask, mat = FALSE)))) {
195+
# add plot_id
196+
} else {
197+
result_current_plot$plot_id <- plot_id[current_plot]
198+
}
201199

202-
# calculate ratio between actual area and theoretical area
203-
result_current_plot$percentage_inside <- 0
204-
} else {
200+
# all cells are NA
201+
if (all(is.na(terra::values(landscape_mask, mat = FALSE)))) {
205202

206-
# calculate ratio between actual area and theoretical area
207-
result_current_plot$percentage_inside <- area$value /
208-
maximum_area[[current_plot]] * 100
209-
}
203+
# calculate ratio between actual area and theoretical area
204+
result_current_plot$percentage_inside <- 0
205+
} else {
210206

211-
# add sample plot raster
212-
result_current_plot$raster_sample_plots <- terra::as.list(landscape_mask)
207+
# calculate ratio between actual area and theoretical area
208+
result_current_plot$percentage_inside <- area$value /
209+
maximum_area[[current_plot]] * 100
210+
}
213211

214-
return(result_current_plot)}))}, warning = function(cond) {
212+
# add sample plot raster
213+
result_current_plot$raster_sample_plots <- terra::as.list(landscape_mask)
215214

216-
warning_messages <<- c(warning_messages, conditionMessage(cond))
215+
return(result_current_plot)
216+
})
217+
)}, warning = function(cond) {
218+
warning_messages <<- c(warning_messages, conditionMessage(cond))
217219

218-
invokeRestart("muffleWarning")}
220+
invokeRestart("muffleWarning")}
219221
)
220222

221223
if (progress) {

0 commit comments

Comments
 (0)