rspatial / terra

R package for spatial data handling https://rspatial.github.io/terra/reference/terra-package.html
GNU General Public License v3.0
544 stars 90 forks source link

Warn users of possible invalid geometries after `simplifyGeom` #692

Closed AMBarbosa closed 2 years ago

AMBarbosa commented 2 years ago

Hi! I'm making leaflet maps, but some detailed polygons take too long to plot. I thus used simplifyGeom, but it sometimes produces invalid geometries that cause somewhat obscure errors downstream:

library(terra)
library(geodata)
library(raster)
library(leaflet)

v <- gadm("Uganda", level = 1, path = tempdir())

leaflet() %>%
  addTiles() %>%
  addPolygons(data = as(v, "Spatial"))   # OK but slow

vs <- simplifyGeom(v, 5)

leaflet() %>%
  addTiles() %>%
  addPolygons(data = as(vs, "Spatial"))   # Error in rgeos::createPolygonsComment(pgons) : rgeos_PolyCreateComment: orphaned hole, cannot find containing polygon for hole at index 5

I found I can solve this by fixing the geometry:

unique(is.valid(vs))  # TRUE FALSE
vs <- makeValid(vs)

leaflet() %>%
  addTiles() %>%
  addPolygons(data = as(vs, "Spatial"))  # OK

But it took me a while to figure this out, so it might be worth to at least add a Note to the simplifyGeom help file, with something like "You may want to check the output with is.valid(), and fix it with makeValid()". Cheers!

rhijmans commented 2 years ago

I have added an argument makeValid (default is TRUE) to simplifyGeom so that you get:

library(terra)
library(geodata)
library(raster)
library(leaflet)

v <- gadm("Uganda", level = 1, path = tempdir())

vs <- simplifyGeom(v, 0.01, makeValid=FALSE)
leaflet() |> addTiles() |> addPolygons(data = as(vs, "Spatial")) 
#Error in rgeos::createPolygonsComment(pgons) : 
#  rgeos_PolyCreateComment: orphaned hole, cannot find containing polygon for hole at index 4

But this works:

vs <- simplifyGeom(v, 0.01)
leaflet() |> addTiles() |> addPolygons(data = as(vs, "Spatial")) 

Thank you for another great suggestion!