Search code examples
rpolygonspatialterra

Remove Overlapping Polygons


I have a large SpatVector with many individual polygons, some of these polygons overlap with eachother and I want to remove all polygons in any location where there is an overlap, leaving the non overlapping portions is preferable but not necessary. Ideally, I will be able to use only the library terra to solve this issue.

Here is a small example of two overlapping polygons within the same SpatVector which contains the same basic information as my larger dataset contains.

library(terra)

coords1 <- matrix(c(0, 0, 4, 0, 4, 4, 0, 4, 0, 0), ncol = 2, byrow = TRUE)
coords2 <- matrix(c(2, 2, 6, 2, 6, 6, 2, 6, 2, 2), ncol = 2, byrow = TRUE)

poly1 <- vect(coords1, type = "polygons")
poly2 <- vect(coords2, type = "polygons")

spatvect <- rbind(poly1, poly2)

spatvect$ID <- c(1, 2)
spatvect$year <- c(2020, 2021)

If I have not explained my issue or goal well enough please let me know so I can clarify better.


Solution

  • Using sf::st_difference(), you can compare your object with itself and return the difference. This removes all areas that intersect.

    library(terra)
    library(sf)
    library(ggplot2)
    library(tidyterra)
    
    coords1 <- matrix(c(0, 0, 4, 0, 4, 4, 0, 4, 0, 0), ncol = 2, byrow = TRUE)
    coords2 <- matrix(c(2, 2, 6, 2, 6, 6, 2, 6, 2, 2), ncol = 2, byrow = TRUE)
    
    poly1 <- vect(coords1, type = "polygons")
    poly2 <- vect(coords2, type = "polygons")
    
    spatvect <- rbind(poly1, poly2)
    
    spatvect$ID <- c(1, 2)
    spatvect$year <- c(2020, 2021)
    
    # Convert SpatVector to sf, get st_difference() of itself, convert back to SpatVector
    spatvect1 <- st_as_sf(spatvect) %>%
      st_difference(., .) %>%
      vect()
    
    # Plot
    ggplot() +
      geom_spatvector(data = spatvect1, aes(fill = factor(ID)))
    

    result