diff --git a/DESCRIPTION b/DESCRIPTION index 51bfd32a..4a7181c5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: stplanr Title: Sustainable Transport Planning -Version: 1.1.2.9000 +Version: 1.2.0 Authors@R: c( person("Robin", "Lovelace", , "rob00x@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5679-6536")), diff --git a/NEWS.md b/NEWS.md index ae633bed..81c02414 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,8 @@ -# stplanr (development version) +# stplanr 1.2.0 -- `line_segment()` now will use `rsgeo::line_segmentize()` if available and only when the input geometry is not in geographic coordinates or does not have a CRS set as it uses euclidean distance - - `line_segment()` becomes an S3 generic which now has methods for `sf` and `sfc` class objects +- `line_segment()` now will use `rsgeo::line_segmentize()` if available +- `line_segment()` becomes an S3 generic which now has methods for `sf` and `sfc` class objects +- `line_segment()` now works around [{rsgeo} issue](https://github.com/JosiahParry/rsgeo/issues/42) with `line_segmentize()` returning fewer segments than requested (#552) # stplanr 1.1.2 (2023-09) diff --git a/R/linefuns.R b/R/linefuns.R index 57d1a3f3..49446aa6 100644 --- a/R/linefuns.R +++ b/R/linefuns.R @@ -154,7 +154,8 @@ line_midpoint <- function(l, tolerance = NULL) { #' This function keeps the attributes. #' Note: results differ when `use_rsgeo` is `TRUE`: #' the `{rsgeo}` implementation is faster and more reliably -#' keeps returned linestrings below a the `segment_length` value. +#' keeps returned linestrings below a the `segment_length` value, +#' but does not always return the number of segments requested. #' #' @inheritParams line2df #' @param segment_length The approximate length of segments in the output (overides n_segments if set) @@ -354,6 +355,7 @@ line_segment_rsgeo <- function(l, n_segments) { # give them them CRS res <- sf::st_set_crs(res, crs) + n_segments <- length(res) # calculate the number of original geometries n_lines <- length(geo) @@ -363,13 +365,12 @@ line_segment_rsgeo <- function(l, n_segments) { # index the original sf object res_tbl <- sf::st_drop_geometry(l)[ids, , drop = FALSE] - # assign the geometry column - nrow(res_tbl) - - res_tbl[[attr(l, "sf_column")]] <- res - # convert to sf and return - res_sf <- sf::st_as_sf(res_tbl) + res_sf <- sf::st_as_sf( + res_tbl, + geometry = res, + crs = crs + ) res_sf } diff --git a/R/rnet_join.R b/R/rnet_join.R index 83874e21..e7e9cd83 100644 --- a/R/rnet_join.R +++ b/R/rnet_join.R @@ -1,7 +1,7 @@ #' Join route networks #' -#' This is a spatial join function that is enables adding columns to a -#' 'target' route network from a 'source' route +#' Join function that adds columns to a +#' 'target' route network `sf` object from a 'source' route #' network that contains the base geometry, e.g. from OSM #' #' The output is an sf object containing polygons representing @@ -180,6 +180,10 @@ line_cast <- function(x) { } #' Merge route networks, keeping attributes with aggregating functions +#' +#' This is a small wrapper around `rnet_join()`. +#' In most cases we recommend using [`rnet_join()`] directly, +#' as it gives more control over the results #' #' @inheritParams rnet_join #' @param sum_flows Should flows be summed? `TRUE` by default. @@ -224,9 +228,6 @@ line_cast <- function(x) { #' # rnet_y = sf::read_sf("rnet_y_ed.geojson") #' # rnet_merged = rnet_merge(rnet_x, rnet_y, dist = 9, segment_length = 20, funs = funs) #' @return An sf object with the same geometry as `rnet_x` -#' - - rnet_merge <- function(rnet_x, rnet_y, dist = 5, funs = NULL, sum_flows = TRUE, crs = geo_select_aeq(rnet_x), ...) { # handle_strings = function(strings) { diff --git a/man/line_segment.Rd b/man/line_segment.Rd index 7ed55816..cabbecc7 100644 --- a/man/line_segment.Rd +++ b/man/line_segment.Rd @@ -21,7 +21,8 @@ If \code{rsgeo} is not available, the \code{lwgeom} package is used.} This function keeps the attributes. Note: results differ when \code{use_rsgeo} is \code{TRUE}: the \code{{rsgeo}} implementation is faster and more reliably -keeps returned linestrings below a the \code{segment_length} value. +keeps returned linestrings below a the \code{segment_length} value, +but does not always return the number of segments requested. } \examples{ library(sf) diff --git a/man/rnet_join.Rd b/man/rnet_join.Rd index 799ccd67..be71a715 100644 --- a/man/rnet_join.Rd +++ b/man/rnet_join.Rd @@ -61,8 +61,8 @@ to be returned} \item{...}{Additional arguments passed to \code{rnet_subset}.} } \description{ -This is a spatial join function that is enables adding columns to a -'target' route network from a 'source' route +Join function that adds columns to a +'target' route network \code{sf} object from a 'source' route network that contains the base geometry, e.g. from OSM } \details{ diff --git a/man/rnet_merge.Rd b/man/rnet_merge.Rd index addbdbbc..c55fce1e 100644 --- a/man/rnet_merge.Rd +++ b/man/rnet_merge.Rd @@ -37,7 +37,9 @@ columns.} An sf object with the same geometry as \code{rnet_x} } \description{ -Merge route networks, keeping attributes with aggregating functions +This is a small wrapper around \code{rnet_join()}. +In most cases we recommend using \code{\link[=rnet_join]{rnet_join()}} directly, +as it gives more control over the results } \examples{ # The source object: diff --git a/reprexes/test-rnet_join.R b/reprexes/test-rnet_join.R index 290f44fd..bd05de70 100644 --- a/reprexes/test-rnet_join.R +++ b/reprexes/test-rnet_join.R @@ -69,3 +69,38 @@ funs = list( } rnet_merge(rnet_x, rnet_y, funs = funs, dist = 20) + +sfc_integer = sf::st_linestring( + cbind( + c(418938.4, 418949.7, 418961), + c(434303.2, 434280.1, 434257) + ) +) |> + sf::st_sfc() |> + sf::st_set_crs(27700) + +line_segment(sfc_integer, 10) + +sfc_no_integer = sf::st_linestring( + cbind( + c(418938.4, 418949.7, 418961.1), + c(434303.2, 434280.1, 434257) + ) +) |> + sf::st_sfc() + + +rsgeo::line_segmentize(rsgeo::as_rsgeo(sfc_integer), n = 6) |> + sf::st_as_sfc() |> + sf::st_cast("LINESTRING") |> + length() + +rsgeo::line_segmentize(rsgeo::as_rsgeo(sfc_no_integer), n = 6) |> + sf::st_as_sfc() |> + sf::st_cast("LINESTRING") |> + length() + +library(stplanr) +rnet_x = sf::read_sf("https://github.com/ropensci/stplanr/releases/download/v1.0.2/rnet_x_ed.geojson") +rnet_y = sf::read_sf("https://github.com/ropensci/stplanr/releases/download/v1.0.2/rnet_y_ed.geojson") +line_segment(rnet_y, 10)