I am using the terra
package in R to get a buffer around polygons. However, I have noticed that terra::buffer()
is not behaving as expected. In particular, for some polygons and buffer widths the buffered polygon does not fully contain a buffer with the same width of its centroid. Is there a bug or am I doing something wrong? I provide reproducible code below and a picture of the nonintuitive area difference. Thanks for your help!
library(terra)
# Define the vertices of the triangle (right-angled at point (0, 0))
vertices <- rbind(
c(-93.746, 46.99), # Vertex 1 (right angle)
c(-93.736, 46.99), # Vertex 2 (height of 10 units)
c(-93.746, 46.9886), # Vertex 3 (base of 5 units)
c(-93.746, 46.99) # Close the polygon by returning to Vertex 1
)
# Create the triangle polygon - EPSG:4269 is lat/lon
triangle_polygon <- vect(vertices, type = "polygons", crs = "EPSG:4269")
# Plot the rectangular triangle
plot(triangle_polygon)
# Get centroids
centroid <- terra::centroids(triangle_polygon)
# Buffer centroid (5000m)
centroid_buffer <- terra::buffer(centroid, 5000)
# Buffer polygon (5000m)
buffer <- terra::buffer(triangle_polygon, 5000)
# Do buffered centroid minus buffered polygon
diff <- terra::erase(centroid_buffer, buffer)
# The picture shows area contained in the buffered centroid, but not in the buffered polygon
plot(diff)
Posted as an issue in the terra github: Here.
**Updated answer as issue no longer occurs using terra_1.8-15
The issue seems to relate to a previous version, and now your code works with terra_1.8-15
. However, you will need to switch the order that you call your buffers in terra::buffer()
.
library(terra)
library(ggplot2)
library(tidyterra)
# Define the vertices of the triangle (right-angled at point (0, 0))
vertices <- rbind(
c(-93.746, 46.99),
c(-93.736, 46.99),
c(-93.746, 46.9886),
c(-93.746, 46.99)
)
# Create the triangle polygon - EPSG:4269 is lat/lon
triangle_polygon <- vect(vertices, type = "polygons", crs = "EPSG:4269")
# Get centroids
centroid <- centroids(triangle_polygon)
# Buffer centroid (5000m)
centroid_buffer <- buffer(centroid, 5000)
# Buffer polygon (5000m)
buffer <- buffer(triangle_polygon, 5000)
# Do buffered centroid minus buffered polygon
diff <- erase(buffer, centroid_buffer)
ggplot() +
geom_spatvector(data = diff) +
scale_x_continuous(
breaks = round(seq(ext(diff)[1], ext(diff)[2], length.out = 5), 2)
) +
theme(panel.background = element_blank())
If you need a smoother edge to your buffers, use the quadsegs
parameter, which controls the number of segments per quarter circle the default is 10):
centroid_buffer <- buffer(centroid, 5000, quadsegs = 1000)
buffer <- buffer(triangle_polygon, 5000, quadsegs = 1000)
diff <- erase(buffer, centroid_buffer)
ggplot() +
geom_spatvector(data = diff) +
scale_x_continuous(
breaks = round(seq(ext(diff)[1], ext(diff)[2], length.out = 5), 2)
) +
theme(panel.background = element_blank())