Joao Carreiras
Joao Carreiras

Reputation: 55

R: Square buffer around points

I've been trying to figure it out how to create square buffers around points, but the closest I've came it's to generate a diamond shaped buffer using terra::buffer with quadsegs = 1. Reproducible code below. Any suggestions are much appreciated!

PS. Something went wrong when uploading the plot, but I believe it's a stackoverflow issue

library(terra)
library(geosphere)
create data
lon <- seq(from = 10, by = 3/3600, length.out = 4)
lat <- rep(0, 4)
lon.lat <- cbind(lon, lat)
crs.lon.lat <- "epsg:4326"
grid <- terra::vect(lon.lat, crs = crs.lon.lat)
grid$id <- 1:length(grid)
set buffer size in meters and create buffer
res.7as <- geosphere::distGeo(c(0, 0), c(1, 0))*7/3600
grid.buf <- terra::buffer(grid,
                          width = res.7as,
                          quadsegs = 1)
plot
plot(grid.buf)
plot(grid, add = T)

Upvotes: 2

Views: 2256

Answers (3)

Robert Hijmans
Robert Hijmans

Reputation: 47146

You can use terra::spin to rotate vector geometries.

Example data

library(terra)
lon <- seq(from = 10, by = 3/3600, length.out = 4)
lon.lat <- cbind(lon, 0)
pts <- terra::vect(lon.lat, crs = "epsg:4326")
buf <- buffer(pts, width=50, quadsegs = 1)

The center of rotation is vectorized, so you can do

xy <- crds(pts)
s <- spin(buf, 45, xy[,1], xy[,2])
plot(s); points(pts)

Upvotes: 2

chamaoskurumi
chamaoskurumi

Reputation: 2493

The following is an alternative solution purely based on sf - st_buffer(..., endCapStyle = "SQUARE") does the job for us.

library("sf")

example_point_1 = sf::st_point(c(0, 10)) 
example_point_2 = sf::st_point(c(110, 40))

example_points_sf <- sf::st_sfc(example_point_1, example_point_2) %>% 
                                sf::st_sf()

sf::st_buffer(example_points_sf,
              dist = 50,
              endCapStyle = "SQUARE") %>% plot() 
plot(example_points_sf, add = T)

enter image description here

Upvotes: 4

user18309711
user18309711

Reputation:

e.g. like this, starting from your data:

library(sf)
library(dplyr) ## for convenient dataframe manipulation

angle = pi/4 ## desired angle of rotation

## function to rotate a feature (of class sfc from package sf)
## around its centroid 
rot = function(feature, a = 0){
    cnt  <- st_centroid(feature)
    (feature - cnt) *
        matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2) +
        cnt
}

convert from class SpatVect to class sfc to apply {sf} methods:

grid.buf.sf <- st_as_sf(grid.buf)

rotate as desired:

grid.buf.rotated <- 
    grid.buf.sf %>%
    rowwise %>%
    mutate(geometry = rot(geometry, angle))

re-convert to SpatVect for use with {terra} if desired:

grid.buf.rotated <- vect(grid.buf.rotated)

rotation function adopted from https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations

Upvotes: 2

Related Questions