Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

geom_cnt_* functions #17

Merged
merged 10 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: centerline
Title: Extract Centerline from Closed Polygons
Version: 0.1.3
Version: 0.2
Authors@R:
c(
person(given = "Anatoly",
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ S3method(cnt_skeleton,sfc)
export(cnt_path)
export(cnt_path_guess)
export(cnt_skeleton)
export(geom_cnt)
export(geom_cnt_label)
export(geom_cnt_text)
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
centerline 0.2 (2024-10-01)
=========================

### UPDATES

* `geom_cnt_*` function family for plotting centerlines with ggplot2

centerline 0.1.3 (2024-09-29)
=========================

Expand Down
83 changes: 51 additions & 32 deletions R/cnt_path_guess.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#' @param skeleton \code{NULL} (default) or [centerline::cnt_skeleton()] output.
#' If \code{NULL} then polygon's skeleton would be estimated in the background
#' using specified parameters (see inherit params below).
#' @param return_geos \code{FALSE} (default). A logical flag that controls
#' whether the \code{geos_geometry} should be returned.
#'
#' @inheritDotParams cnt_skeleton
#'
Expand All @@ -28,18 +30,18 @@
#' system.file("extdata/example.gpkg", package = "centerline"),
#' layer = "lake",
#' quiet = TRUE
#' ) |>
#' ) |>
#' geos::as_geos_geometry()
#' # Find lake's centerline
#' lake_centerline <- cnt_path_guess(input = lake, keep = 1)
#' # Plot
#' plot(lake)
#' plot(lake_centerline, col = "firebrick", lwd = 2, add = TRUE)
#'

#'
cnt_path_guess <-
function(input,
skeleton = NULL,
return_geos = FALSE,
...) {
UseMethod("cnt_path_guess")
}
Expand Down Expand Up @@ -86,6 +88,7 @@ cnt_path_guess.geos_geometry <-
cnt_path_guess.sf <-
function(input,
skeleton = NULL,
return_geos = FALSE,
...) {
# Check if input is of class 'sf' or 'sfc' and 'POLYGON'
stopifnot(check_polygons(input))
Expand Down Expand Up @@ -118,17 +121,23 @@ cnt_path_guess.sf <-
longest_path_geos <-
do.call(c, lapply(skeleton_geos, cnt_path_guess_master))

# Return the `sf` object
longest_path_geos |>
sf::st_as_sf() |>
sf::st_set_crs(crs) |>
cbind(sf::st_drop_geometry(input))
if (return_geos) {
# Return the `geos_geometry` object
return(longest_path_geos)
} else {
# Return the `sf` object
longest_path_geos |>
sf::st_as_sf() |>
sf::st_set_crs(crs) |>
cbind(sf::st_drop_geometry(input))
}
}

#' @export
cnt_path_guess.sfc <-
function(input,
skeleton = NULL,
return_geos = FALSE,
...) {
# Check if input is of class 'POLYGON'
stopifnot(check_polygons(input))
Expand Down Expand Up @@ -161,16 +170,22 @@ cnt_path_guess.sfc <-
longest_path_geos <-
do.call(c, lapply(skeleton_geos, cnt_path_guess_master))

# Return `sfc` object
longest_path_geos |>
sf::st_as_sfc() |>
sf::st_set_crs(crs)
if (return_geos) {
# Return the `geos_geometry` object
return(longest_path_geos)
} else {
# Return the `sfc` object
longest_path_geos |>
sf::st_as_sfc() |>
sf::st_set_crs(crs)
}
}

#' @export
cnt_path_guess.SpatVector <-
function(input,
skeleton = NULL,
return_geos = FALSE,
...) {
# Check if input is of class 'POLYGON'
stopifnot(check_polygons(input))
Expand Down Expand Up @@ -204,34 +219,38 @@ cnt_path_guess.SpatVector <-

# Find the longest path
longest_path_geos <-
do.call(c, lapply(skeleton_geos, cnt_path_guess_master)) |>
geos_to_terra()
do.call(c, lapply(skeleton_geos, cnt_path_guess_master))

# Return `SpatVector` object with attribute table
if (nrow(input_data) == 0) {
return(longest_path_geos)
} else if (nrow(input_data) == nrow(longest_path_geos)) {
longest_path_geos <-
longest_path_geos |>
cbind(input_data)
return(longest_path_geos)
} else if (nrow(input_data) == 1 && nrow(longest_path_geos) > 1) {
longest_path_geos <-
longest_path_geos |>
cbind(input_data[rep(1, nrow(longest_path_geos)), ])
if (return_geos) {
# Return the `geos_geometry` object
return(longest_path_geos)
} else {
warning("input and centerline have different number of rows,
returning centerline without attributes")
return(longest_path_geos)
# Return the `SpatVector` object
longest_path_geos <- geos_to_terra(longest_path_geos)

if (nrow(input_data) == 0) {
return(geos_to_terra(longest_path_geos))
} else if (nrow(input_data) == nrow(longest_path_geos)) {
longest_path_geos <-
longest_path_geos |>
cbind(input_data)
return(longest_path_geos)
} else if (nrow(input_data) == 1 && nrow(longest_path_geos) > 1) {
longest_path_geos <-
longest_path_geos |>
cbind(input_data[rep(1, nrow(longest_path_geos)), ])
return(longest_path_geos)
} else {
warning("input and centerline have different number of rows,
returning centerline without attributes")
return(longest_path_geos)
}
}
}

cnt_path_guess_master <-
function(skeleton_geos) {
if (
geos::geos_type(skeleton_geos) == "multilinestring"
) {
if (geos::geos_type(skeleton_geos) == "multilinestring") {
skeleton_geos <-
geos::geos_unnest(skeleton_geos, keep_multi = FALSE)
}
Expand Down
10 changes: 5 additions & 5 deletions R/cnt_skeleton.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#'
#' @param input \code{sf}, \code{sfc}, \code{SpatVector}, or
#' \code{geos_geometry} polygons object
#' @param keep numeric, proportion of points to retain (0.05-Inf; default 0.5).
#' @param keep numeric, proportion of points to retain (0.05-5.0; default 0.5).
#' See Details.
#' @param method character, either \code{"voronoi"} (default) or
#' \code{"straight"}, or just the first letter \code{"v"} or \code{"s"}.
Expand Down Expand Up @@ -80,7 +80,7 @@ cnt_skeleton.geos_geometry <-
method = c("voronoi", "straight")) {
# Check input arguments
stopifnot(check_polygons(input))
checkmate::assert_number(keep, lower = 0, upper = 5)
checkmate::assert_number(keep, lower = 0.05, upper = 5.0)
method <- checkmate::matchArg(method, choices = c("voronoi", "straight"))

# Save CRS
Expand Down Expand Up @@ -116,7 +116,7 @@ cnt_skeleton.sf <-
method = c("voronoi", "straight")) {
# Check input arguments
stopifnot(check_polygons(input))
checkmate::assert_number(keep, lower = 0, upper = 5)
checkmate::assert_number(keep, lower = 0.05, upper = 5.0)
method <- checkmate::matchArg(method, choices = c("voronoi", "straight"))

# Save CRS
Expand Down Expand Up @@ -158,7 +158,7 @@ cnt_skeleton.sfc <-
method = c("voronoi", "straight")) {
# Check input arguments
stopifnot(check_polygons(input))
checkmate::assert_number(keep, lower = 0, upper = 5)
checkmate::assert_number(keep, lower = 0.05, upper = 5.0)
method <- checkmate::matchArg(method, choices = c("voronoi", "straight"))

# Save CRS
Expand Down Expand Up @@ -201,7 +201,7 @@ cnt_skeleton.SpatVector <-

# Check input arguments
stopifnot(check_polygons(input))
checkmate::assert_number(keep, lower = 0, upper = 5)
checkmate::assert_number(keep, lower = 0.05, upper = 5.0)
method <- checkmate::matchArg(method, choices = c("voronoi", "straight"))

# Input attributes
Expand Down
Loading