@@ -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}
0 commit comments