I get a lot of zonal/polygon shapefiles from clients that have numerous topological issues. The most common (as in it's in all of them) is the existence of gaps (or slivers) between polygon boundaries. It took me a little while to understand the various sf tools I need to fix it, but I finally did it with the following:
shp <- st_buffer(shp, .0001)
shp <- st_difference(shp, shp)
Would it be worthwhile to wrap this in something like an st_squeeze() or st_slivers()? There are tons of google searches for it. One thing I did notice is that the above method is pretty slow for shapefiles with lots of polygons.
If there is a better way (I'm only just getting familiar with geojson and topojson) then I'm all ears. Maybe you even already have a function that I missed.
BTW, can sf read/write/convert geo/topojson? Thanks!
what does "between polygon boundaries" mean? As in you have polygons that should share an edge but actually have a small gap?
I am not sure what the code you provided is supposed to do; with a normal polygon (and I just tried) it buffers it by a small amount (so it gets a bit bigger) and then subtracts it from itself, leaving no geometry behind.
Yes, st_read and st_write deal with geojson well, it will guess the driver if you use a dsn (path) that ends in .geojson. List of extensions and associated drivers in the second vignette.
Yep - small gaps.
Take the NC county shape in the sf package (imagining it had some gaps). If you st_buffer() %>% st_difference each polygon will get buffered (filling in the gaps) and then the st_difference cleans everything up so that the shared boundary is the same. In an effort to make that clearer, I'll take a shapefile I've been given, which is also a bunch of adjacent polygons. I can check for gaps by combining them into a single polygon:
taz[taz$TAZ < 20,] %>%
st_combine() %>%
st_union() %>%
plot()

Instead of getting a nice, clean polygon, the gaps between the original polygons are evident. If instead I start with st_buffer and st_difference:
test <- taz[taz$TAZ < 20,] %>% st_buffer(.00001)
st_difference(test, test) %>%
st_combine() %>%
st_union() %>%
plot()

The buffer/difference made sure that there were no gaps between each polygon. I've heard this referred to as "squeezing" polygons. It would be really handy to have an
st_squeeze(sf = NULL, buffer_dist = .0001)
Anyway, thanks for your time.
RE st_read/write and json: Awesome!
I can see this problem, and agree that a generic solution would be welcome; however, the problem is not specific to this R package, and a solution also supported by e.g. qgis, postgis or spatialite would make life much easier here. Also, package lwgeom has functions st_make_valid and st_snap, which might be useful in some way to this problem. Feel free to reopen here once you have more than an idea.
For posterity:
I was using the squeeze method until I needed to do an intersection with the resulting unioned polygon and found that it wasn't valid. I tried using the st_snap() function instead and got the desired results with a bonus of also getting a valid polygon:
shp <-
shp %>%
st_snap(x = ., y = ., tolerance = 0.0001) %>%
st_union()
Most helpful comment
For posterity:
I was using the squeeze method until I needed to do an intersection with the resulting unioned polygon and found that it wasn't valid. I tried using the
st_snap()function instead and got the desired results with a bonus of also getting a valid polygon: