@@ -470,11 +470,15 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
470
470
# ' Transform spatial position data
471
471
# '
472
472
# ' 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()].
474
475
# '
475
476
# ' @param data Data frame or list containing numerical columns `x` and `y`.
476
477
# ' @param target_crs,source_crs Target and source coordinate reference systems.
477
478
# ' 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`.
478
482
# ' @return A copy of the input data with `x` and `y` replaced by transformed values.
479
483
# ' @examples
480
484
# ' if (requireNamespace("sf", quietly = TRUE)) {
@@ -494,24 +498,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
494
498
# ' }
495
499
# ' @keywords internal
496
500
# ' @export
497
- sf_transform_xy <- function (data , target_crs , source_crs ) {
501
+ sf_transform_xy <- function (data , target_crs , source_crs , authority_compliant = FALSE ) {
498
502
if (identical(target_crs , source_crs ) ||
499
503
is.null(target_crs ) || is.null(source_crs ) || is.null(data ) ||
500
504
is.na(target_crs ) || is.na(source_crs ) ||
501
505
! all(c(" x" , " y" ) %in% names(data ))) {
502
506
return (data )
503
507
}
504
508
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
511
515
)
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 ]
515
520
516
521
data
517
522
}
0 commit comments