RobertoAS
RobertoAS

Reputation: 89

Why does terra in R find the buffer of a polygon to not fully contain the buffer of the centroid?

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!

Buffer Differences

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.

Upvotes: 3

Views: 125

Answers (1)

L Tyrone
L Tyrone

Reputation: 7065

**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())

1

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())

2

Upvotes: 1

Related Questions