2

I have a matrix that would like to display as a raster, in a 45 degree rotated fashion and it should stretch along the x- and y- directions to fit the graphics device.

Questions that I've found that are somewhat related are here, here and here, but don't adress the stretching part.

Here is an example an unrotated raster that stretches with the graphics window:

library(grid)

# Make dummy raster
set.seed(1234)
x <- cumsum(rnorm(10))
x <- x %*% t(x)
x <- scales::rescale(x)

grid.newpage()
grid.raster(x, interpolate = F,
            width = unit(1, "npc"),
            height = unit(1, "npc"))

enter image description here

I can rotate this raster 45 degrees by adjusting the viewport. This works well if the aspect ratio of the graphics device is 1:1. However, this raster doesn't stretch if the graphics device is resized.

grid.newpage()
grid.rect(gp = gpar(col = "red")) # To illustrate boundaries
grid.raster(x, interpolate = F,
            vp = viewport(angle = 45,
                          width = unit(1, "npc"),
                          height = unit(1, "npc")))

enter image description here

I can get the exact graphical output that I want by converting each pixel in the raster to polygons and applying a linear transformation to these coordinates.

df <- reshape2::melt(x)

# Convert pixels to vertex coordinates
coords <- matrix(
  c(rep(df$Var1 - 0.5, 2),
    rep(df$Var1 + 0.5, 2),
    df$Var2 - 0.5, 
    rep(df$Var2 + 0.5, 2),
    df$Var2 - 0.5),
  ncol = 2
)

# Rotate coordinates
rotmat <- matrix(c(0.5, -1, 0.5, 1), ncol = 2)
coords <- t(rotmat %*% (t(coords)))

# Re-assemble data
df <- rbind(df, df, df, df)
df$Var1 <- scales::rescale(coords[, 1])
df$Var2 <- scales::rescale(coords[, 2])
df$id <- rep(seq_len(length(x)), 4)
df <- df[order(df$id), ]

grid.newpage()
grid.rect(gp = gpar(col = "red")) # To illustrate boundaries
grid.polygon(
  x = df$Var1, y = df$Var2,
  id = df$id,
  gp = gpar(col = NA,
            fill = rgb(df$value, df$value, df$value)[!duplicated(df$id)])
)

enter image description here

However, this seems like an inefficient way of doing this and it doesn't scale very well if the original raster gets quite large. Also, when exported to pngs and pdfs, you can sometimes notice the artifacts of these polygons. I would definitely like to stay within the realm of the grid package, because my end-goal is to build a ggplot2 geom that supports this rotation.

If there is no real solution within grid, that is fine as well, but I'd like to know. I'll just stick to the inefficient solution in that case.

teunbrand
  • 33,645
  • 4
  • 37
  • 63

0 Answers0