Skip to content

Commit f468053

Browse files
authored
annotation_raster()/_custom() respond to scale transformations (#6182)
* helper for annotation ranges * use helper * update snapshots * use vctrs rules to preserve AsIs * add test * add news bullet * allow mixing AsIs and numeric * clarify AsIs change in news
1 parent 094b957 commit f468053

File tree

5 files changed

+64
-31
lines changed

5 files changed

+64
-31
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# ggplot2 (development version)
22

3+
* Custom and raster annotation now respond to scale transformations, and can
4+
use AsIs variables for relative placement (@teunbrand based on
5+
@yutannihilation's prior work, #3120)
36
* When discrete breaks have names, they'll be used as labels by default
47
(@teunbrand, #6147).
58
* The helper function `is.waiver()` is now exported to help extensions to work

R/annotation-custom.R

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,12 @@ GeomCustomAnn <- ggproto("GeomCustomAnn", Geom,
7070

7171
draw_panel = function(data, panel_params, coord, grob, xmin, xmax,
7272
ymin, ymax) {
73-
if (!inherits(coord, "CoordCartesian")) {
74-
cli::cli_abort("{.fn annotation_custom} only works with {.fn coord_cartesian}.")
75-
}
76-
corners <- data_frame0(
77-
x = c(xmin, xmax),
78-
y = c(ymin, ymax),
79-
.size = 2
73+
range <- ranges_annotation(
74+
coord, panel_params, xmin, xmax, ymin, ymax,
75+
fun = "annotation_custom"
8076
)
81-
data <- coord$transform(corners, panel_params)
82-
83-
x_rng <- range(data$x, na.rm = TRUE)
84-
y_rng <- range(data$y, na.rm = TRUE)
85-
86-
vp <- viewport(x = mean(x_rng), y = mean(y_rng),
87-
width = diff(x_rng), height = diff(y_rng),
77+
vp <- viewport(x = mean(range$x), y = mean(range$y),
78+
width = diff(range$x), height = diff(range$y),
8879
just = c("center","center"))
8980
editGrob(grob, vp = vp, name = paste(grob$name, annotation_id()))
9081
},
@@ -99,3 +90,21 @@ annotation_id <- local({
9990
i
10091
}
10192
})
93+
94+
ranges_annotation <- function(coord, panel_params, xmin, xmax, ymin, ymax, fun) {
95+
if (!inherits(coord, "CoordCartesian")) {
96+
cli::cli_abort("{.fn {fun}} only works with {.fn coord_cartesian}.")
97+
}
98+
data <- data_frame0(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax)
99+
data <- .ignore_data(data)[[1]]
100+
x <- panel_params$x$scale$transform_df(data)
101+
data[names(x)] <- x
102+
y <- panel_params$y$scale$transform_df(data)
103+
data[names(y)] <- y
104+
data <- .expose_data(data)[[1]]
105+
data <- coord$transform(data, panel_params)
106+
list(
107+
x = range(data$xmin, data$xmax, na.rm = TRUE),
108+
y = range(data$ymin, data$ymax, na.rm = TRUE)
109+
)
110+
}

R/annotation-raster.R

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,13 @@ GeomRasterAnn <- ggproto("GeomRasterAnn", Geom,
7373

7474
draw_panel = function(data, panel_params, coord, raster, xmin, xmax,
7575
ymin, ymax, interpolate = FALSE) {
76-
if (!inherits(coord, "CoordCartesian")) {
77-
cli::cli_abort("{.fn annotation_raster} only works with {.fn coord_cartesian}.")
78-
}
79-
corners <- data_frame0(
80-
x = c(xmin, xmax),
81-
y = c(ymin, ymax),
82-
.size = 2
76+
range <- ranges_annotation(
77+
coord, panel_params, xmin, xmax, ymin, ymax,
78+
fun = "annotation_raster"
79+
)
80+
rasterGrob(raster, range$x[1], range$y[1],
81+
diff(range$x), diff(range$y), default.units = "native",
82+
just = c("left","bottom"), interpolate = interpolate
8383
)
84-
data <- coord$transform(corners, panel_params)
85-
86-
x_rng <- range(data$x, na.rm = TRUE)
87-
y_rng <- range(data$y, na.rm = TRUE)
88-
89-
rasterGrob(raster, x_rng[1], y_rng[1],
90-
diff(x_rng), diff(y_rng), default.units = "native",
91-
just = c("left","bottom"), interpolate = interpolate)
9284
}
9385
)

tests/testthat/_snaps/annotate.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
Problem while converting geom to grob.
44
i Error occurred in the 1st layer.
5-
Caused by error in `draw_panel()`:
5+
Caused by error in `ranges_annotation()`:
66
! `annotation_raster()` only works with `coord_cartesian()`.
77

88
---
99

1010
Problem while converting geom to grob.
1111
i Error occurred in the 1st layer.
12-
Caused by error in `draw_panel()`:
12+
Caused by error in `ranges_annotation()`:
1313
! `annotation_custom()` only works with `coord_cartesian()`.
1414

1515
# annotation_map() checks the input data

tests/testthat/test-annotate.R

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,32 @@ test_that("annotate() warns about `stat` or `position` arguments", {
8686
annotate("point", 1:3, 1:3, stat = "density", position = "dodge")
8787
)
8888
})
89+
90+
test_that("annotation_custom() and annotation_raster() adhere to scale transforms", {
91+
rast <- matrix(rainbow(10), nrow = 1)
92+
93+
p <- ggplot() +
94+
annotation_raster(rast, 1, 10, 1, 9) +
95+
scale_x_continuous(transform = "log10", limits = c(0.1, 100), expand = FALSE) +
96+
scale_y_continuous(limits = c(0, 10), expand = FALSE)
97+
ann <- get_layer_grob(p)[[1]]
98+
99+
expect_equal(as.numeric(ann$x), 1/3)
100+
expect_equal(as.numeric(ann$y), 1/10)
101+
expect_equal(as.numeric(ann$width), 1/3)
102+
expect_equal(as.numeric(ann$height), 8/10)
103+
104+
rast <- rasterGrob(rast, width = 1, height = 1)
105+
106+
p <- ggplot() +
107+
annotation_custom(rast, 1, 10, 1, 9) +
108+
scale_x_continuous(transform = "log10", limits = c(0.1, 100), expand = FALSE) +
109+
scale_y_continuous(limits = c(0, 10), expand = FALSE)
110+
ann <- get_layer_grob(p)[[1]]$vp
111+
112+
expect_equal(as.numeric(ann$x), 1/2)
113+
expect_equal(as.numeric(ann$y), 1/2)
114+
expect_equal(as.numeric(ann$width), 1/3)
115+
expect_equal(as.numeric(ann$height), 8/10)
116+
117+
})

0 commit comments

Comments
 (0)