'Finding Overlapping Buffers in R

I have coordinates which I added a 75m buffer around. I want to filter the buffers by year and then determine if any buffers from observations within the same year are overlapping. I want to be able to identify which buffers are overlapping to either omit them if they are repeated observations or merge them if they are touching.

e_af_df <- na.omit(e_af_simp_21)
e_af_obs <- st_as_sf(e_af_df, coords=c(7, 6), crs = st_crs(4326))
e_af_t <- st_transform(e_af_obs, 5070)
e_buffers = st_buffer(e_af_t, dist=75)
e_buffers$Year <- format(as.Date(e_buffers$Date, format="%m/%d/%Y"), "%Y")
b.2016 <- subset(e_buffers, e_buffers$Year == "2016")

So far this works to draw my buffer (sf polygons) and filter by year, using 2016 as an example here. I then try to find the overlapping buffers using st_intersection.

o.2016 = st_intersection(b.2016)
summary(o.2016)

This tells me that 1718 buffers are overlapping, which I find unlikely since there is only a total of 2768 for that year. I think there might be a double-counting of buffer IDs. Regardless, I am unable to see which buffers are intersecting with each other, just that intersections are occurring.

For some other years, doing the same thing results in an error.

Error in CPL_nary_intersection(x) : GEOS exception

I read that changing the precision may fix this so I used st_set_precision. Yet this only fixed the error for certain years as well.

Does anyone know of a simple way to find overlapping buffers or a way to fix this code?



Solution 1:[1]

Let's go step by step. As I don't have access to your data, let's create some dummy polygons:

library(sf)
library(dplyr)
p <- st_point(x=c(10, 10))
area <- st_buffer(p, 10)
polygons <- st_buffer(st_sample(area, 25), 1)

Now, let's calculate intersections between them:

inter <- st_intersection(st_as_sf(polygons))
inter
#> Simple feature collection with 36 features and 2 fields
#> Geometry type: GEOMETRY
#> Dimension:     XY
#> Bounding box:  xmin: -0.264212 ymin: 1.4698 xmax: 19.96589 ymax: 20.05445
#> CRS:           NA
#> First 10 features:
#>     n.overlaps origins                              x
#> 1            1       1 POLYGON ((18.95204 14.79623...
#> 2            1       2 MULTIPOLYGON (((5.254102 3....
#> 3            1       3 POLYGON ((2.574736 14.99139...
#> 4            1       4 POLYGON ((1.735788 12.80523...
#> 5            1       5 POLYGON ((18.25878 13.02976...
#> 6            1       6 POLYGON ((2.64105 10.30672,...
#> 7            1       7 POLYGON ((8.714673 17.29225...
#> 2.1          2    2, 8 POLYGON ((5.154202 2.707236...
#> 8            1       8 POLYGON ((5.592733 3.483773...
#> 9            1       9 POLYGON ((3.852673 16.92456...

Please note columns n.overlaps and origins. Let's filter out only intersections:

a <- inter |>
  filter(n.overlaps > 1)
plot(polygons)
plot(a, col = "blue", add = TRUE)

Created on 2022-02-10 by the reprex package (v2.0.1)

Please note, the functions:

st_intersects(polygons)
st_overlaps(polygons)
st_touches(polygons)

are binary predicates, they can be used to check if geometries intersects, etc. Example:

st_intersects(polygons, sparse = TRUE)
#> Sparse geometry binary predicate list of length 25, where the 
#> predicate was `intersects'
#> first 10 elements:
#>  1: 1, 15, 20, 21
#>  2: 2
#>  3: 3, 9, 14
#> [...]

Based on it you can wrote a simple function which will remove (or union) the geometries.

Regards,
Grzegorz

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1