Skip to content

Commit e2eeb6a

Browse files
authored
use sf::sf_project. closes #4090. (#4091)
1 parent ccd94e1 commit e2eeb6a

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

R/coord-sf.R

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -470,11 +470,15 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
470470
#' Transform spatial position data
471471
#'
472472
#' Helper function that can transform spatial position data (pairs of x, y
473-
#' values) among coordinate systems.
473+
#' values) among coordinate systems. This is implemented as a thin wrapper
474+
#' around [sf::sf_project()].
474475
#'
475476
#' @param data Data frame or list containing numerical columns `x` and `y`.
476477
#' @param target_crs,source_crs Target and source coordinate reference systems.
477478
#' If `NULL` or `NA`, the data is not transformed.
479+
#' @param authority_compliant logical; `TRUE` means handle axis order authority
480+
#' compliant (e.g. EPSG:4326 implying `x = lat`, `y = lon`), `FALSE` means use
481+
#' visualisation order (i.e. always `x = lon`, `y = lat`). Default is `FALSE`.
478482
#' @return A copy of the input data with `x` and `y` replaced by transformed values.
479483
#' @examples
480484
#' if (requireNamespace("sf", quietly = TRUE)) {
@@ -494,24 +498,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
494498
#' }
495499
#' @keywords internal
496500
#' @export
497-
sf_transform_xy <- function(data, target_crs, source_crs) {
501+
sf_transform_xy <- function(data, target_crs, source_crs, authority_compliant = FALSE) {
498502
if (identical(target_crs, source_crs) ||
499503
is.null(target_crs) || is.null(source_crs) || is.null(data) ||
500504
is.na(target_crs) || is.na(source_crs) ||
501505
!all(c("x", "y") %in% names(data))) {
502506
return(data)
503507
}
504508

505-
# by turning the data into a geometry list column of individual points,
506-
# we can make sure that the output length equals the input length, even
507-
# if the transformation fails in some cases
508-
sf_data <- sf::st_sfc(
509-
mapply(function(x, y) sf::st_point(as.numeric(c(x, y))), data$x, data$y, SIMPLIFY = FALSE),
510-
crs = source_crs
509+
sf_data <- cbind(data$x, data$y)
510+
out <- sf::sf_project(
511+
sf::st_crs(source_crs), sf::st_crs(target_crs),
512+
sf_data,
513+
keep = TRUE, warn = FALSE,
514+
authority_compliant = authority_compliant
511515
)
512-
sf_data_trans <- sf::st_transform(sf_data, target_crs)
513-
data$x <- vapply(sf_data_trans, function(x) x[1], numeric(1))
514-
data$y <- vapply(sf_data_trans, function(x) x[2], numeric(1))
516+
out <- ifelse(is.finite(out), out, NA) # replace any infinites with NA
517+
518+
data$x <- out[, 1]
519+
data$y <- out[, 2]
515520

516521
data
517522
}

man/sf_transform_xy.Rd

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)