I'm trying to plot points on top of an imported image, made with ggplot2
and geom_sf()
.
When I do a mock-up (first chunk of code) and import an image that's a simple ggplot()
, everything works - the added points sit right where they should be. But once I switch to using geom_sf()
, something is obviously shifted - the points are in the correct spot on the y-axis, but not the x-axis.
library(ggplot2)
library(magick)
library(sf)
df <- data.frame(x = 1:10, y = 1:10)
ggplot(df) +
geom_point(aes(x = x, y = y)) +
theme_void() +
scale_x_continuous(breaks = 1:10, limits = c(0, 11), expand = c(0, 0)) +
scale_y_continuous(breaks = 1:10, limits = c(0, 11), expand = c(0, 0))
ggsave("My image.png", width = 5, height = 5, units = "in")
img <- image_read("My image.png")
plot(NULL, xlim = c(0, 11), ylim = c(0, 11), axes=FALSE, xlab = "", ylab = "")
rasterImage(img, 0, 0, 11, 11)
points(df$x, df$y, col = "red")
The same approach, but with geom_sf()
and the image fails - the points are plotted, but are offset from their true position (should be plotted on top of the 2 corners).
rect <- data.frame(lon = c(-94.9, -93), lat = c(32, 35))
rect_sf <- st_polygon(list(cbind(
rect$lon[c(1,2,2,1,1)],
rect$lat[c(1,1,2,2,1)]))) %>%
st_sfc(crs = 4326)
ggplot() +
geom_sf(data = rect_sf, fill = "grey85", colour = "black") +
theme_void() +
coord_sf(xlim = rect$lon, ylim = rect$lat, expand = FALSE)
ggsave("My image.png", width = 5, height = 5, units = "in")
img <- image_read("My image.png")
plot(NULL, xlim = rect$lon, ylim = rect$lat, axes=FALSE, xlab = "", ylab = "")
rasterImage(img, rect$lon[1], rect$lat[1], rect$lon[2], rect$lat[2])
points(rect$lon, rect$lat, col = "red")
I think the issue is the aspect ratio of the saved image. Below is the same code with 2 different saving options - one wide, one long. The resulting offset of the red points plotted post-image-read changes accordingly. I think that the "offset" is the white space added around the "offending" axis when the image is generated with the wrong aspect ratio. How do I specify the correct aspect ratio in these cases?
rect <- data.frame(lon = c(-94.9, -93), lat = c(32, 35))
rect_sf <- st_polygon(list(cbind(
rect$lon[c(1,2,2,1,1)],
rect$lat[c(1,1,2,2,1)]))) %>%
st_sfc(crs = 4326)
ggplot() +
geom_sf(data = rect_sf, fill = "grey85", colour = "black") +
theme_void() +
coord_sf(xlim = rect$lon, ylim = rect$lat, expand = FALSE)
ggsave("My image.png", width = 8, height = 2, units = "in")
ggsave("My image.png", width = 3, height = 9, units = "in")
img <- image_read("My image.png")
plot(NULL, xlim = rect$lon, ylim = rect$lat, axes=FALSE, xlab = "", ylab = "")
rasterImage(img, rect$lon[1], rect$lat[1], rect$lon[2], rect$lat[2])
points(rect$lon, rect$lat, col = "red")
you need to trim the whitespace around your plot, using something like magick's image_trim()
img <- image_read("My image.png")
img_trimmed <- magick::image_trim(img)
plot(NULL, xlim = rect$lon, ylim = rect$lat, axes=FALSE, xlab = "", ylab = "")
rasterImage(img_trimmed, rect$lon[1], rect$lat[1], rect$lon[2], rect$lat[2])
points(rect$lon, rect$lat, col = "red")