Skip to content

Commit 3605a94

Browse files
committed
improved parsing logic, add regression tests
1 parent 6319d3d commit 3605a94

File tree

4 files changed

+191
-18
lines changed

4 files changed

+191
-18
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#2853).
66

77
* `coord_sf()` now respects manual setting of axis tick labels (@clauswilke,
8-
#2857).
8+
#2857, #2881).
99

1010
* `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters
1111
for lines and polygons (@alistaire47, #2826)

R/sf.R

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -451,17 +451,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
451451
x_breaks <- graticule$degree[graticule$type == "E"]
452452
if (is.null(scale_x$labels)) {
453453
x_labels <- rep(NA, length(x_breaks))
454-
} else if (is.character(scale_x$labels)) {
455-
x_labels <- scale_x$labels
456-
needs_parsing[graticule$type == "E"] <- self$parse_E_labels
457-
} else if (is.function(scale_x$labels)){
458-
# all labels need to be character vectors
459-
x_labels <- as.character(scale_x$labels(x_breaks))
460-
needs_parsing[graticule$type == "E"] <- self$parse_E_labels
461-
} else {
454+
} else if (is.waive(scale_x$labels)) {
462455
x_labels <- graticule$degree_label[graticule$type == "E"]
463456
needs_autoparsing[graticule$type == "E"] <- TRUE
457+
} else {
458+
if (is.function(scale_x$labels)) {
459+
x_labels <- scale_x$labels(x_breaks)
460+
} else {
461+
x_labels <- scale_x$labels
462+
}
463+
464+
if (is.character(x_labels)) {
465+
needs_parsing[graticule$type == "E"] <- self$parse_E_labels
466+
} else {
467+
# all labels need to be temporarily stored as character vectors
468+
x_labels <- as.character(x_labels)
469+
needs_parsing[graticule$type == "E"] <- TRUE
470+
}
464471
}
472+
465473
if (length(x_labels) != length(x_breaks)) {
466474
stop("Breaks and labels along x direction are different lengths", call. = FALSE)
467475
}
@@ -471,16 +479,23 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
471479
y_breaks <- graticule$degree[graticule$type == "N"]
472480
if (is.null(scale_y$labels)) {
473481
y_labels <- rep(NA, length(y_breaks))
474-
} else if (is.character(scale_y$labels)) {
475-
y_labels <- scale_y$labels
476-
needs_parsing[graticule$type == "N"] <- self$parse_N_labels
477-
} else if (is.function(scale_y$labels)){
478-
# all labels need to be character vectors
479-
y_labels <- as.character(scale_y$labels(y_breaks))
480-
needs_parsing[graticule$type == "N"] <- self$parse_N_labels
481-
} else {
482+
} else if (is.waive(scale_y$labels)) {
482483
y_labels <- graticule$degree_label[graticule$type == "N"]
483484
needs_autoparsing[graticule$type == "N"] <- TRUE
485+
} else {
486+
if (is.function(scale_y$labels)) {
487+
y_labels <- scale_y$labels(y_breaks)
488+
} else {
489+
y_labels <- scale_y$labels
490+
}
491+
492+
if (is.character(y_labels)) {
493+
needs_parsing[graticule$type == "N"] <- self$parse_N_labels
494+
} else {
495+
# all labels need to be temporarily stored as character vectors
496+
y_labels <- as.character(y_labels)
497+
needs_parsing[graticule$type == "N"] <- TRUE
498+
}
484499
}
485500
if (length(y_labels) != length(y_breaks)) {
486501
stop("Breaks and labels along y direction are different lengths", call. = FALSE)

man/ggsf.Rd

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-coord_sf.R

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,150 @@ test_that("multiplication works", {
1414
skip("sf tests are currently unstable")
1515
expect_doppelganger("sf-polygons", plot)
1616
})
17+
18+
19+
test_that("axis labels can be set manually", {
20+
skip_if_not_installed("sf")
21+
22+
plot <- ggplot(sf::st_polygon(list(matrix(1e3*c(1, 2, 3, 1, 1, 3, 2, 1), ncol = 2)))) +
23+
geom_sf()
24+
25+
# autogenerated labels
26+
b <- ggplot_build(
27+
plot +
28+
scale_x_continuous(breaks = c(1000, 2000, 3000)) +
29+
scale_y_continuous(breaks = c(1000, 1500, 2000))
30+
)
31+
graticule <- b$layout$panel_params[[1]]$graticule
32+
expect_identical(
33+
graticule[graticule$type == "E", ]$degree_label,
34+
c("1000", "2000", "3000")
35+
)
36+
expect_identical(
37+
graticule[graticule$type == "N", ]$degree_label,
38+
c("1000", "1500", "2000")
39+
)
40+
41+
# character labels
42+
b <- ggplot_build(
43+
plot +
44+
scale_x_continuous(
45+
breaks = c(1000, 2000, 3000),
46+
labels = c("A", "B", "C")
47+
) +
48+
scale_y_continuous(
49+
breaks = c(1000, 1500, 2000),
50+
labels = c("D", "E", "F")
51+
)
52+
)
53+
graticule <- b$layout$panel_params[[1]]$graticule
54+
expect_identical(
55+
graticule[graticule$type == "E", ]$degree_label,
56+
c("A", "B", "C")
57+
)
58+
expect_identical(
59+
graticule[graticule$type == "N", ]$degree_label,
60+
c("D", "E", "F")
61+
)
62+
63+
# expressions mixed with character labels
64+
b <- ggplot_build(
65+
plot +
66+
scale_x_continuous(
67+
breaks = c(1000, 2000, 3000),
68+
labels = c("A", "B", "C")
69+
) +
70+
scale_y_continuous(
71+
breaks = c(1000, 1500, 2000),
72+
labels = parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3"))
73+
)
74+
)
75+
graticule <- b$layout$panel_params[[1]]$graticule
76+
expect_identical(
77+
graticule[graticule$type == "E", ]$degree_label,
78+
as.list(c("A", "B", "C"))
79+
)
80+
parsed <- vector("list", 3)
81+
parsed[1:3] <- parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3"))
82+
expect_identical(
83+
graticule[graticule$type == "N", ]$degree_label,
84+
parsed
85+
)
86+
87+
# parsing via coord_sf()
88+
b <- ggplot_build(
89+
plot +
90+
scale_x_continuous(
91+
breaks = c(1000, 2000, 3000),
92+
labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3")
93+
) +
94+
scale_y_continuous(
95+
breaks = c(1000, 1500, 2000),
96+
labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")
97+
) +
98+
coord_sf(parse_E_labels = TRUE, parse_N_labels = FALSE)
99+
)
100+
graticule <- b$layout$panel_params[[1]]$graticule
101+
parsed <- vector("list", 3)
102+
parsed[1:3] <- parse(text = c("10^3", "2 %*% 10^3", "3 %*% 10^3"))
103+
expect_identical(
104+
graticule[graticule$type == "E", ]$degree_label,
105+
parsed
106+
)
107+
expect_identical(
108+
graticule[graticule$type == "N", ]$degree_label,
109+
as.list(c("10^3", "1.5 %*% 10^3", "2 %*% 10^3"))
110+
)
111+
112+
b <- ggplot_build(
113+
plot +
114+
scale_x_continuous(
115+
breaks = c(1000, 2000, 3000),
116+
labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3")
117+
) +
118+
scale_y_continuous(
119+
breaks = c(1000, 1500, 2000),
120+
labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")
121+
) +
122+
coord_sf(parse_E_labels = FALSE, parse_N_labels = TRUE)
123+
)
124+
graticule <- b$layout$panel_params[[1]]$graticule
125+
expect_identical(
126+
graticule[graticule$type == "E", ]$degree_label,
127+
as.list(c("10^3", "2 %*% 10^3", "3 %*% 10^3"))
128+
)
129+
parsed <- vector("list", 3)
130+
parsed[1:3] <- parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3"))
131+
expect_identical(
132+
graticule[graticule$type == "N", ]$degree_label,
133+
parsed
134+
)
135+
136+
# autoparsing of degree labels
137+
data <- sf::st_sfc(
138+
sf::st_polygon(list(matrix(1e1*c(1, 2, 3, 1, 1, 3, 2, 1), ncol = 2))),
139+
crs = 4326 # basic long-lat crs
140+
)
141+
142+
plot <- ggplot(data) + geom_sf()
143+
144+
b <- ggplot_build(
145+
plot +
146+
scale_x_continuous(breaks = c(10, 20, 30)) +
147+
scale_y_continuous(breaks = c(10, 15, 20))
148+
)
149+
graticule <- b$layout$panel_params[[1]]$graticule
150+
parsed <- vector("list", 3)
151+
parsed[1:3] <- parse(text = c("10*degree*E", "20*degree*E", "30*degree*E"))
152+
expect_identical(
153+
graticule[graticule$type == "E", ]$degree_label,
154+
parsed
155+
)
156+
parsed[1:3] <- parse(text = c("10*degree*N", "15*degree*N", "20*degree*N"))
157+
expect_identical(
158+
graticule[graticule$type == "N", ]$degree_label,
159+
parsed
160+
)
161+
162+
})
163+

0 commit comments

Comments
 (0)