rr-stars

R stars - how to set affine values based on a rotation angle


I am trying to rotate an R stars grid using the affine transformation values, similar to what is shown in this stars vignette except the difference is I know the rotation angle I want, but I just don't know (or lack the linear algebra skills) how to convert these into a pair of affine transformation values "a1" and "a2".

From the above link, the example given shows:

attr(attr(s, "dimensions"), "raster")$affine = c(0.1, 0.1)

#The rotation angle, in degrees, is

atan2(0.1, 1) * 180 / pi
## [1] 5.710593

In effect, I need to reverse this procedure given the known rotation angle. The convention for the rotation is positive counterclockwise with 0 being "up" or "true north".

Below is a complete reprex, see the commented block where affine matrix is setup:

library(stars)

# define grid
xorg <- 576206  
yorg <- 4412742
nrows <- 8 
ncols <- 5
dim <- 10   # size of cell

####
rot <- 265   # Rotation angle in degrees, relative to "up/North, counterclockwise positive"
aff_mat <-  c(0,0)  # HOW DO I SET THIS TO ACHIEVE THE ROTATION ANGLE ABOVE?
#aff_mat <- c(?, ?)
####

# build a grid
x <- seq(xorg, xorg+((ncols-1)*dim), dim)
y <- seq(yorg, yorg+((nrows-1)*dim), dim)

d <- st_dimensions(x = x, y = y, .raster = c("x", "y"), affine = aff_mat)
m <- matrix(seq(1,length(x)*length(y),1),length(x),length(y))

r1 <- st_as_stars(r = m, dimensions = d)
#plot(r1, axes=TRUE)

# plot
library(ggplot2)
p <- ggplot() + 
  geom_stars(data = r1) + 
  coord_equal() +
  scale_fill_viridis_c() +
  theme_void() +
  theme(legend.position = 'none') 

p

enter image description here

What it should look like though is something like:

# output should look something like:
print(p, vp=grid::viewport(angle=rot))

enter image description here


Solution

  • Answer from stars author on github: here

    # define grid
    library(stars)                                                                        
    xorg <- 576206
    yorg <- 4412742                                                                       
    nrows <- 8                                                                            
    ncols <- 5  
    dim <- 10   # size of cell                                                            
    
    ####
    rot <- 265   # Rotation angle in degrees, relative to "up/North, counterclockwise positive"
                                                                  
    ####                                                                                  
                                                                                          
    # build a grid                                                                        
    x <- seq(xorg, xorg+((ncols-1)*dim), dim)                                             
    y <- seq(yorg, yorg+((nrows-1)*dim), dim)                                             
                                                                                          
    d <- st_dimensions(x = x, y = y, .raster = c("x", "y"))                               
    m <- matrix(seq(1,length(x)*length(y),1),length(x),length(y))                         
                                                                                          
    th = rot / 180 * pi # rad                                                             
    R = matrix(c(cos(th), sin(th), -sin(th), cos(th)), 2) * dim
    r1 <- st_as_stars(r = m, dimensions = d)                                              
                                                                                                                                         
                                                                                          
    attr(attr(r1, "dimensions"), "raster")$affine = c(R[1,2], R[2,1])                     
    attr(r1, "dimensions")$x$delta = R[1,1]                                               
    attr(r1, "dimensions")$y$delta = R[2,2]                                               
    plot(r1, axes=TRUE, reset = FALSE)