@@ -222,16 +222,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
222222 x_range [2 ], y_range [2 ]
223223 )
224224
225+ breaks <- sf_breaks(scale_x , scale_y , bbox , params $ crs )
226+
225227 # Generate graticule and rescale to plot coords
226228 graticule <- sf :: st_graticule(
227229 bbox ,
228230 crs = params $ crs ,
229- lat = scale_y $ breaks %| W | % NULL ,
230- lon = scale_x $ breaks %| W | % NULL ,
231+ lat = breaks $ y %| W | % NULL ,
232+ lon = breaks $ x %| W | % NULL ,
231233 datum = self $ datum ,
232234 ndiscr = self $ ndiscr
233235 )
234236
237+ if (is.null(breaks $ x )) {
238+ graticule <- vec_slice(graticule , graticule $ type != " E" )
239+ }
240+ if (is.null(breaks $ y )) {
241+ graticule <- vec_slice(graticule , graticule $ type != " N" )
242+ }
243+
235244 # override graticule labels provided by sf::st_graticule() if necessary
236245 graticule <- self $ fixup_graticule_labels(graticule , scale_x , scale_y , params )
237246
@@ -580,6 +589,53 @@ parse_axes_labeling <- function(x) {
580589 list (top = labs [1 ], right = labs [2 ], bottom = labs [3 ], left = labs [4 ])
581590}
582591
592+ # This function does two things differently from standard breaks:
593+ # 1. It does not resolve `waiver()`, unless `n.breaks` is given. In the case
594+ # that breaks are `waiver()`, we use the default graticule breaks.
595+ # 2. It discards non-finite breaks because they are invalid input to the
596+ # graticule. This may cause atomic `labels` to be out-of-sync.
597+ sf_breaks <- function (scale_x , scale_y , bbox , crs ) {
598+
599+ has_x <- ! is.null(scale_x $ breaks ) || ! is.null(scale_x $ n.breaks )
600+ has_y <- ! is.null(scale_y $ breaks ) || ! is.null(scale_y $ n.breaks )
601+
602+ x_breaks <- if (has_x ) waiver() else NULL
603+ y_breaks <- if (has_y ) waiver() else NULL
604+
605+
606+ if (has_x || has_y ) {
607+ if (! is.null(crs )) {
608+ # Atomic breaks input are assumed to be in long/lat coordinates.
609+ # To preserve that assumption for function breaks, the bounding box
610+ # needs to be translated to long/lat coordinates.
611+ if (! is_named(bbox )) {
612+ names(bbox ) <- c(" xmin" , " ymin" , " xmax" , " ymax" )
613+ }
614+ # Convert bounding box to long/lat coordinates
615+ bbox <- sf :: st_as_sfc(sf :: st_bbox(bbox , crs = crs ))
616+ bbox <- sf :: st_bbox(sf :: st_transform(bbox , 4326 ))
617+ bbox <- as.numeric(bbox )
618+
619+ # If any bbox is NA the transformation has probably failed.
620+ # (.e.g from IGH to long/lat). In this case, just provide full long/lat.
621+ bbox [is.na(bbox )] <- c(- 180 , - 90 , 180 , 90 )[is.na(bbox )]
622+ }
623+
624+ if (! (is.waive(scale_x $ breaks ) && is.null(scale_x $ n.breaks ))) {
625+ x_breaks <- scale_x $ get_breaks(limits = bbox [c(1 , 3 )])
626+ finite <- is.finite(x_breaks )
627+ x_breaks <- if (any(finite )) x_breaks [finite ] else NULL
628+ }
629+
630+ if (! (is.waive(scale_y $ breaks ) && is.null(scale_y $ n.breaks ))) {
631+ y_breaks <- scale_y $ get_breaks(limits = bbox [c(2 , 4 )])
632+ finite <- is.finite(y_breaks )
633+ y_breaks <- if (any(finite )) y_breaks [finite ] else NULL
634+ }
635+ }
636+
637+ list (x = x_breaks , y = y_breaks )
638+ }
583639
584640# ' ViewScale from graticule
585641# '
0 commit comments