@@ -222,16 +222,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
222
222
x_range [2 ], y_range [2 ]
223
223
)
224
224
225
+ breaks <- sf_breaks(scale_x , scale_y , bbox , params $ crs )
226
+
225
227
# Generate graticule and rescale to plot coords
226
228
graticule <- sf :: st_graticule(
227
229
bbox ,
228
230
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 ,
231
233
datum = self $ datum ,
232
234
ndiscr = self $ ndiscr
233
235
)
234
236
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
+
235
244
# override graticule labels provided by sf::st_graticule() if necessary
236
245
graticule <- self $ fixup_graticule_labels(graticule , scale_x , scale_y , params )
237
246
@@ -580,6 +589,53 @@ parse_axes_labeling <- function(x) {
580
589
list (top = labs [1 ], right = labs [2 ], bottom = labs [3 ], left = labs [4 ])
581
590
}
582
591
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
+ }
583
639
584
640
# ' ViewScale from graticule
585
641
# '
0 commit comments