-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Patterned fills don't render segmentsGrobs. #5710
Comments
It seems it's not that these Grobs don't work, but the parameters are a bit tricky. I'm not familiar with these things, and don't figure out the rule here (I'm also on Windows and use the AGG device, so it's possible the result is different on macOS or Linux). library(grid)
library(ggplot2)
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
do_plot <- function(x0, y0, x1, y1) {
checkered <- pattern(
rectGrob(x = c(0.25, 0.75), y = c(0.25, 0.75), width = 0.5, height = 0.5, gp = gp),
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp
)
striped <- pattern(
segmentsGrob(x0 = x0, y0 = y0, x1 = x1, y1 = y1, gp = gp),
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp
)
ggplot(mpg, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
scale_fill_manual(values = list(striped, checkered, striped, checkered)) +
ggtitle(glue::glue("({x0}, {y0}) - ({x1}, {y1})"))
}
patchwork::wrap_plots(
do_plot(0, 0, 1, 1 ),
do_plot(0, 0, 1, 0.9),
do_plot(0, 0, 1, 0.8),
do_plot(0, 0, 1, 0.7)
) Created on 2024-02-24 with reprex v2.1.0 To be clear, ggplot2 does nothing here. You can experiment with grid like this: library(grid)
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
striped <- pattern(
segmentsGrob(x0 = c(0, 0.5), y0 = c(0.5, 0), x1 = c(0.5, 1), y1 = c(1, 0.5), gp = gp),
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp )
grid.newpage()
grid.rect(width = 0.5, height = 0.5, gp = gpar(fill = striped)) |
Okay, I think now I understand. library(grid)
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
seg <- segmentsGrob(x0 = c(0, 0.5), y0 = c(0.5, 0), x1 = c(0.5, 1), y1 = c(1, 0.5), gp = gp)
grid.newpage()
grid.draw(seg)
grid.rect(
x = 0.5, y = 0.5, # default value of pattern()
width = unit(5, "mm"), height = unit(5, "mm"),
gp = gpar(col = "red", fill = "transparent")
) Created on 2024-02-24 with reprex v2.1.0 So, if you tweak the position of the segments, the pattern should be drawn. library(grid)
library(ggplot2)
# gpar everywhere to rule out an "invisible lines" issue
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
checkered <- pattern(
rectGrob(x = c(0.25, 0.75), y = c(0.25, 0.75), width = 0.5, height = 0.5, gp = gp),
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp )
mm_rel <- function(...) {
unit(0.5, "npc") + unit((base::c(...) - 0.5) * 5, "mm")
}
striped <- pattern(
segmentsGrob(x0 = mm_rel(0, 0.5), y0 = mm_rel(0.5, 0), x1 = mm_rel(0.5, 1), y1 = mm_rel(1, 0.5), gp = gp),
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp )
ggplot(mpg, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
scale_fill_manual(values = list(striped, checkered, striped, checkered)) Created on 2024-02-24 with reprex v2.1.0 |
Wow! Thanks so much for this! I'd written off those parameters as not the problem since they worked for the checkered pattern, but if I understand correctly, it was clipping to just the center corners of the checkered pattern too? Thanks again!! 😃 |
Yeah. You should have noticed if the checkered pattern has an odd number of rectangles. library(grid)
library(ggplot2)
# gpar everywhere to rule out an "invisible lines" issue
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
rect2 <- rectGrob(x = c(0.25, 0.75), y = c(0.25, 0.75), width = 0.5, height = 0.5, gp = gp)
checkered2 <- pattern(rect2, width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp)
rect3 <- rectGrob(x = c(1, 3, 5) / 6, y = c(1, 3, 5) / 6, width = 1 / 3, height = 1 / 3, gp = gp)
checkered3 <- pattern(rect3, width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat", gp = gp)
ggplot(mpg, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
scale_fill_manual(values = list(checkered2, checkered3, checkered2, checkered3)) grid.newpage()
grid.draw(rect2)
grid.rect(x = 0.5, y = 0.5, width = unit(5, "mm"), height = unit(5, "mm"), gp = gpar(col = "red", fill = "transparent")) grid.newpage()
grid.draw(rect3)
grid.rect(x = 0.5, y = 0.5, width = unit(5, "mm"), height = unit(5, "mm"), gp = gpar(col = "red", fill = "transparent")) Created on 2024-02-24 with reprex v2.1.0 |
Anyway, I'm closing as this is not a problem. I found these resources useful. Hope this helps! https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/vecpat/vecpat.html |
Yes, it's definitely not any kind of bug with ggplot2. And thank you so much for the help! It makes a lot more sense to me now how to proceed. For anyone coming across this post in the future - I found that defining a viewport is another solution: library(grid)
library(ggplot2)
# Graphics parameters and viewport
gp <- gpar(col = "black", fill = "black", lwd = 2, lty = "solid")
vp <- viewport(width = unit(5, "mm"), height = unit(5, "mm"))
striped <- pattern(
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat",
segmentsGrob(gp = gp, vp = vp, x0 = 0, y0 = 0, x1 =1, y1 = 1) )
shingle <- pattern(
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat",
segmentsGrob(gp = gp, vp = vp,
x0 = c(0, 0, 0, 0.6), y0 = c(0, 0.5, 0, 0.5),
x1 = c(1, 1, 0.2, 0.8), y1 = c(0, 0.5, 0.5, 1) ))
fish <- pattern(
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat",
bezierGrob(gp = gp, vp = vp, id = rep(1:3, each = 4),
x = {x <- c(0, .25, .75, 1); c(x, x - 0.5, x + 0.5) },
y = {y <- c(0.5, -0.19, -0.19, 0.5); c(y, y + 0.5, y + 0.5) } ))
checkered <- pattern(
width = unit(5, "mm"), height = unit(5, "mm"), extend = "repeat",
rectGrob(gp = gp, vp = vp,
x = c(0.25, 0.75), y = c(0.25, 0.75), width = 0.5, height = 0.5 ))
ggplot(mpg, aes(factor(cyl), fill = factor(cyl))) +
geom_bar(color = "black") +
scale_fill_manual(values = list(striped, shingle, fish, checkered)) Getting the striped tiles to transition seamlessly is my next challenge. |
I was excited to read the recent blog post announcing support for patterned fills! However, it doesn't seem to be working with line, segment, or bezier grobs.
Below is some code adapted from the blog post linked above.
The segment grob draws fine on it's own:
I'm working with RStudio 2023.12.1 on Windows 10. R 4.3.2, ggplot2 3.5.0, all other packages up to date as well. I've tried switching RStudio to both "Cairo PNG" and "AGG" in the General/Graphics options.
The text was updated successfully, but these errors were encountered: