@@ -493,10 +493,6 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
493
493
}
494
494
graticule $ degree_label [graticule $ type == " N" ] <- y_labels
495
495
496
- # remove tick labels not on axes 1 (bottom) and 2 (left)
497
- if (! is.null(graticule $ plot12 ))
498
- graticule $ degree_label [! graticule $ plot12 ] <- NA
499
-
500
496
# Parse labels if requested/needed
501
497
has_degree <- grepl(" \\ bdegree\\ b" , graticule $ degree_label )
502
498
needs_parsing <- needs_parsing | (needs_autoparsing & has_degree )
@@ -541,7 +537,9 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
541
537
x_range = x_range ,
542
538
y_range = y_range ,
543
539
graticule = graticule ,
544
- crs = params $ crs
540
+ crs = params $ crs ,
541
+ label_axes = self $ label_axes ,
542
+ label_graticule = self $ label_graticule
545
543
)
546
544
},
547
545
@@ -577,32 +575,158 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
577
575
578
576
render_axis_h = function (self , panel_params , theme ) {
579
577
graticule <- panel_params $ graticule
580
- east <- graticule [graticule $ type == " E" & ! is.na(graticule $ degree_label ), ]
581
578
582
- list (
583
- top = nullGrob(),
584
- bottom = guide_axis(
585
- east $ x_start ,
586
- east $ degree_label ,
579
+ # top axis
580
+ id1 <- id2 <- integer(0 )
581
+ # labels based on panel side
582
+ id1 <- c(id1 , which(graticule $ type == panel_params $ label_axes $ top & graticule $ y_start > 0.999 ))
583
+ id2 <- c(id2 , which(graticule $ type == panel_params $ label_axes $ top & graticule $ y_end > 0.999 ))
584
+
585
+ # labels based on graticule direction
586
+ if (" S" %in% panel_params $ label_graticule ) {
587
+ id1 <- c(id1 , which(graticule $ type == " E" & graticule $ y_start > 0.999 ))
588
+ }
589
+ if (" N" %in% panel_params $ label_graticule ) {
590
+ id2 <- c(id2 , which(graticule $ type == " E" & graticule $ y_end > 0.999 ))
591
+ }
592
+ if (" W" %in% panel_params $ label_graticule ) {
593
+ id1 <- c(id1 , which(graticule $ type == " N" & graticule $ y_start > 0.999 ))
594
+ }
595
+ if (" E" %in% panel_params $ label_graticule ) {
596
+ id2 <- c(id2 , which(graticule $ type == " N" & graticule $ y_end > 0.999 ))
597
+ }
598
+
599
+ ticks1 <- graticule [unique(id1 ), ]
600
+ ticks2 <- graticule [unique(id2 ), ]
601
+ tick_positions <- c(ticks1 $ x_start , ticks2 $ x_end )
602
+ tick_labels <- c(ticks1 $ degree_label , ticks2 $ degree_label )
603
+
604
+ if (length(tick_positions ) > 0 ) {
605
+ top <- guide_axis(
606
+ tick_positions ,
607
+ tick_labels ,
608
+ position = " top" ,
609
+ theme = theme
610
+ )
611
+ } else {
612
+ top <- zeroGrob()
613
+ }
614
+
615
+ # bottom axis
616
+ id1 <- id2 <- integer(0 )
617
+ # labels based on panel side
618
+ id1 <- c(id1 , which(graticule $ type == panel_params $ label_axes $ bottom & graticule $ y_start < 0.001 ))
619
+ id2 <- c(id2 , which(graticule $ type == panel_params $ label_axes $ bottom & graticule $ y_end < 0.001 ))
620
+
621
+ # labels based on graticule direction
622
+ if (" S" %in% panel_params $ label_graticule ) {
623
+ id1 <- c(id1 , which(graticule $ type == " E" & graticule $ y_start < 0.001 ))
624
+ }
625
+ if (" N" %in% panel_params $ label_graticule ) {
626
+ id2 <- c(id2 , which(graticule $ type == " E" & graticule $ y_end < 0.001 ))
627
+ }
628
+ if (" W" %in% panel_params $ label_graticule ) {
629
+ id1 <- c(id1 , which(graticule $ type == " N" & graticule $ y_start < 0.001 ))
630
+ }
631
+ if (" E" %in% panel_params $ label_graticule ) {
632
+ id2 <- c(id2 , which(graticule $ type == " N" & graticule $ y_end < 0.001 ))
633
+ }
634
+
635
+ ticks1 <- graticule [unique(id1 ), ]
636
+ ticks2 <- graticule [unique(id2 ), ]
637
+ tick_positions <- c(ticks1 $ x_start , ticks2 $ x_end )
638
+ tick_labels <- c(ticks1 $ degree_label , ticks2 $ degree_label )
639
+
640
+ if (length(tick_positions ) > 0 ) {
641
+ bottom <- guide_axis(
642
+ tick_positions ,
643
+ tick_labels ,
587
644
position = " bottom" ,
588
645
theme = theme
589
646
)
590
- )
647
+ } else {
648
+ bottom <- zeroGrob()
649
+ }
650
+
651
+ list (top = top , bottom = bottom )
591
652
},
592
653
593
654
render_axis_v = function (self , panel_params , theme ) {
594
655
graticule <- panel_params $ graticule
595
- north <- graticule [graticule $ type == " N" & ! is.na(graticule $ degree_label ), ]
596
656
597
- list (
598
- left = guide_axis(
599
- north $ y_start ,
600
- north $ degree_label ,
657
+ # right axis
658
+ id1 <- id2 <- integer(0 )
659
+ # labels based on panel side
660
+ id1 <- c(id1 , which(graticule $ type == panel_params $ label_axes $ right & graticule $ x_end > 0.999 ))
661
+ id2 <- c(id2 , which(graticule $ type == panel_params $ label_axes $ right & graticule $ x_start > 0.999 ))
662
+
663
+ # labels based on graticule direction
664
+ if (" N" %in% panel_params $ label_graticule ) {
665
+ id1 <- c(id1 , which(graticule $ type == " E" & graticule $ x_end > 0.999 ))
666
+ }
667
+ if (" S" %in% panel_params $ label_graticule ) {
668
+ id2 <- c(id2 , which(graticule $ type == " E" & graticule $ x_start > 0.999 ))
669
+ }
670
+ if (" E" %in% panel_params $ label_graticule ) {
671
+ id1 <- c(id1 , which(graticule $ type == " N" & graticule $ x_end > 0.999 ))
672
+ }
673
+ if (" W" %in% panel_params $ label_graticule ) {
674
+ id2 <- c(id2 , which(graticule $ type == " N" & graticule $ x_start > 0.999 ))
675
+ }
676
+
677
+ ticks1 <- graticule [unique(id1 ), ]
678
+ ticks2 <- graticule [unique(id2 ), ]
679
+ tick_positions <- c(ticks1 $ y_end , ticks2 $ y_start )
680
+ tick_labels <- c(ticks1 $ degree_label , ticks2 $ degree_label )
681
+
682
+ if (length(tick_positions ) > 0 ) {
683
+ right <- guide_axis(
684
+ tick_positions ,
685
+ tick_labels ,
686
+ position = " right" ,
687
+ theme = theme
688
+ )
689
+ } else {
690
+ right <- zeroGrob()
691
+ }
692
+
693
+ # left axis
694
+ id1 <- id2 <- integer(0 )
695
+ # labels based on panel side
696
+ id1 <- c(id1 , which(graticule $ type == panel_params $ label_axes $ left & graticule $ x_end < 0.001 ))
697
+ id2 <- c(id2 , which(graticule $ type == panel_params $ label_axes $ left & graticule $ x_start < 0.001 ))
698
+
699
+ # labels based on graticule direction
700
+ if (" N" %in% panel_params $ label_graticule ) {
701
+ id1 <- c(id1 , which(graticule $ type == " E" & graticule $ x_end < 0.001 ))
702
+ }
703
+ if (" S" %in% panel_params $ label_graticule ) {
704
+ id2 <- c(id2 , which(graticule $ type == " E" & graticule $ x_start < 0.001 ))
705
+ }
706
+ if (" E" %in% panel_params $ label_graticule ) {
707
+ id1 <- c(id1 , which(graticule $ type == " N" & graticule $ x_end < 0.001 ))
708
+ }
709
+ if (" W" %in% panel_params $ label_graticule ) {
710
+ id2 <- c(id2 , which(graticule $ type == " N" & graticule $ x_start < 0.001 ))
711
+ }
712
+
713
+ ticks1 <- graticule [unique(id1 ), ]
714
+ ticks2 <- graticule [unique(id2 ), ]
715
+ tick_positions <- c(ticks1 $ y_end , ticks2 $ y_start )
716
+ tick_labels <- c(ticks1 $ degree_label , ticks2 $ degree_label )
717
+
718
+ if (length(tick_positions ) > 0 ) {
719
+ left <- guide_axis(
720
+ tick_positions ,
721
+ tick_labels ,
601
722
position = " left" ,
602
723
theme = theme
603
- ),
604
- right = nullGrob()
605
- )
724
+ )
725
+ } else {
726
+ left <- zeroGrob()
727
+ }
728
+
729
+ list (left = left , right = right )
606
730
}
607
731
608
732
)
@@ -622,23 +746,85 @@ sf_rescale01_x <- function(x, range) {
622
746
}
623
747
624
748
625
- # ' @param crs Use this to select a specific CRS. If not specified, will
626
- # ' use the CRS defined in the first layer.
749
+ # ' @param crs Use this to select a specific coordinate reference system (CRS).
750
+ # ' If not specified, will use the CRS defined in the first layer.
627
751
# ' @param datum CRS that provides datum to use when generating graticules
752
+ # ' @param label_axes Character vector or named list of character values
753
+ # ' specifying which graticule lines (meridians or parallels) should be labeled on
754
+ # ' which side of the plot. Meridians are indicated by `"E"` (for East) and
755
+ # ' parallels by `"N"` (for North). Default is `"--EN"`, which specifies
756
+ # ' (clockwise from the top) no labels on the top, none on the right, meridians
757
+ # ' on the bottom, and parallels on the left. Alternatively, this setting could have been
758
+ # ' specified with `list(bottom = "E", left = "N")`.
759
+ # '
760
+ # ' This parameter can be used alone or in combination with `label_graticule`.
761
+ # ' @param label_graticule Character vector indicating which graticule lines should be labeled
762
+ # ' where. Meridians run north-south, and the letters `"N"` and `"S"` indicate that
763
+ # ' they should be labeled on their north or south end points, respectively.
764
+ # ' Parallels run east-west, and the letters `"E"` and `"W"` indicate that they
765
+ # ' should be labeled on their east or west end points, respectively. Thus,
766
+ # ' `label_graticule = "SW"` would label meridians at their south end and parallels at
767
+ # ' their west end, whereas `label_graticule = "EW"` would label parallels at both
768
+ # ' ends and meridians not at all. Because meridians and parallels can in general
769
+ # ' intersect with any side of the plot panel, for any choice of `label_graticule` labels
770
+ # ' are not guaranteed to reside on only one particular side of the plot panel.
771
+ # '
772
+ # ' This parameter can be used alone or in combination with `label_axes`.
628
773
# ' @param ndiscr number of segments to use for discretising graticule lines;
629
774
# ' try increasing this when graticules look unexpected
630
775
# ' @inheritParams coord_cartesian
631
776
# ' @export
632
777
# ' @rdname ggsf
633
778
coord_sf <- function (xlim = NULL , ylim = NULL , expand = TRUE ,
634
- crs = NULL , datum = sf :: st_crs(4326 ), ndiscr = 100 ,
635
- default = FALSE ) {
779
+ crs = NULL , datum = sf :: st_crs(4326 ),
780
+ label_graticule = waiver(),
781
+ label_axes = waiver(),
782
+ ndiscr = 100 , default = FALSE ) {
783
+
784
+ if (is.waive(label_graticule ) && is.waive(label_axes )) {
785
+ # if both `label_graticule` and `label_axes` are set to waive then we
786
+ # use the default of labels on the left and at the bottom
787
+ label_graticule <- " "
788
+ label_axes <- " --EN"
789
+ } else {
790
+ # if at least one is set we ignore the other
791
+ label_graticule <- label_graticule %| W | % " "
792
+ label_axes <- label_axes %| W | % " "
793
+ }
794
+
795
+ if (is.character(label_axes )) {
796
+ label_axes <- parse_axes_labeling(label_axes )
797
+ } else if (! is.list(label_axes )) {
798
+ stop(
799
+ " Panel labeling format not recognized." ,
800
+ call. = FALSE
801
+ )
802
+ label_axes <- list (left = " N" , bottom = " E" )
803
+ }
804
+
805
+ if (is.character(label_graticule )) {
806
+ label_graticule <- unlist(strsplit(label_graticule , " " ))
807
+ } else {
808
+ stop(
809
+ " Graticule labeling format not recognized." ,
810
+ call. = FALSE
811
+ )
812
+ label_graticule <- " "
813
+ }
814
+
636
815
ggproto(NULL , CoordSf ,
637
816
limits = list (x = xlim , y = ylim ),
638
817
datum = datum ,
639
818
crs = crs ,
819
+ label_axes = label_axes ,
820
+ label_graticule = label_graticule ,
640
821
ndiscr = ndiscr ,
641
822
expand = expand ,
642
823
default = default
643
824
)
644
825
}
826
+
827
+ parse_axes_labeling <- function (x ) {
828
+ labs = unlist(strsplit(x , " " ))
829
+ list (top = labs [1 ], right = labs [2 ], bottom = labs [3 ], left = labs [4 ])
830
+ }
0 commit comments