|
16 | 16 | #' @param crs {`object`}\cr{} |
17 | 17 | #' Coordinate reference system (CRS) passed to [sf::st_crs()], used to |
18 | 18 | #' transform `points` and `polygon`. |
| 19 | +#' @param remove_outsiders {`logical`}\cr{} |
| 20 | +#' Remove points outside the polygion. An error will be thrown if all points |
| 21 | +#' are rejected. Default is `FALSE`. |
| 22 | +#' |
19 | 23 | #' |
20 | 24 | #' @details |
21 | 25 | #' Wind fetch is the unobstructed distance over which wind travels |
|
88 | 92 | #' plot(res$transect_lines |> sf::st_geometry(), add = TRUE, col = 2, lwd = 0.5) |
89 | 93 | #' } |
90 | 94 | compute_fetch <- function( |
91 | | - points, polygon, max_dist = 15, n_bearings = 16, wind_weights = NULL, crs = NULL) { |
| 95 | + points, polygon, max_dist = 15, n_bearings = 16, wind_weights = NULL, crs = NULL, remove_outsiders = FALSE) { |
92 | 96 | valid_points(points) |
93 | 97 | points$id_point <- seq_len(nrow(points)) |
94 | 98 | valid_polygon(polygon) |
@@ -130,7 +134,7 @@ compute_fetch <- function( |
130 | 134 | } |
131 | 135 | } |
132 | 136 |
|
133 | | - valid_polygon_contains_points(points, polygon) |
| 137 | + valid_polygon_contains_points(points, polygon, remove_outsiders) |
134 | 138 |
|
135 | 139 | if (is.null(wind_weights)) { |
136 | 140 | d_direction <- data.frame( |
@@ -187,14 +191,32 @@ compute_fetch <- function( |
187 | 191 | ) |
188 | 192 | ), |
189 | 193 | by = "id_point" |
190 | | - ) |> |
| 194 | + ) |> |
191 | 195 | dplyr::select( |
192 | 196 | c("id_point", "fetch_km", "weighted_fetch_km") |
193 | 197 | ), |
194 | 198 | transect_lines = transect_lines |
195 | 199 | ) |
196 | 200 | } |
197 | 201 |
|
| 202 | + |
| 203 | +#' @describeIn compute_fetch Identify outsiders using a plot where points |
| 204 | +#' located outside the polygon are highlighted in red. |
| 205 | +#' @export |
| 206 | +identify_outsiders <- function(points, polygon) { |
| 207 | + plot(polygon |> sf::st_geometry(), border = 1) |
| 208 | + plot( |
| 209 | + points |> sf::st_geometry(), |
| 210 | + # there godd be more than one polygon |
| 211 | + col = suppressMessages( |
| 212 | + 2 - apply(sf::st_within(points, polygon, sparse = FALSE), 1, any) |
| 213 | + ), |
| 214 | + pch = 19, |
| 215 | + cex = 2, |
| 216 | + add = TRUE |
| 217 | + ) |
| 218 | +} |
| 219 | + |
198 | 220 | # HELPERS |
199 | 221 |
|
200 | 222 | is_proj_unit_meter <- function(x) { |
@@ -227,19 +249,33 @@ valid_polygon <- function(x) { |
227 | 249 | } |
228 | 250 | } |
229 | 251 |
|
230 | | -valid_polygon_contains_points <- function(points, polygon) { |
| 252 | +valid_polygon_contains_points <- function(points, polygon, remove_outsiders = FALSE) { |
| 253 | + if (remove_outsiders) { |
| 254 | + points <- remove_points_outside_polygon(points, polygon) |
| 255 | + if (!(points |> nrow())) { |
| 256 | + rlang::abort("All points were outside the polygon considered.") |
| 257 | + } |
| 258 | + } |
231 | 259 | chk <- suppressMessages({ |
232 | 260 | sf::st_contains(polygon, points, sparse = FALSE) |> |
233 | | - apply(2, any) |> |
234 | | - all() |
| 261 | + apply(2, any) |
235 | 262 | }) |
236 | | - if (chk) { |
| 263 | + if (all(chk)) { |
237 | 264 | TRUE |
238 | 265 | } else { |
239 | | - rlang::abort("`polygon` must include `points`.") |
| 266 | + rlang::abort("`polygon` must include all points in `points`. |
| 267 | + Use `remove_outsiders = TRUE` to remove points outside the polygon. |
| 268 | + Alternatively use `identify_outsiders()` to vizualize outsiders. |
| 269 | + ") |
240 | 270 | } |
241 | 271 | } |
242 | 272 |
|
| 273 | +remove_points_outside_polygon <- function(points, polygon) { |
| 274 | + suppressMessages( |
| 275 | + points[apply(sf::st_within(points, polygon, sparse = FALSE), 1, any), ] |
| 276 | + ) |
| 277 | +} |
| 278 | + |
243 | 279 | valid_direction <- function(direction) { |
244 | 280 | if (!all(direction >= 0 & direction <= 360)) { |
245 | 281 | rlang::abort("All directions must be within the range [0, 360].") |
|
0 commit comments