How do I simplify an
sf polygon without introducing gaps and slivers?
With a shapefile, for example, I would use
library("pryr") library("rgdal") library("rmapshaper") download.file("https://borders.ukdataservice.ac.uk/ukborders/easy_download/prebuilt/shape/England_gor_2011.zip", destfile = "regions.zip") unzip("regions.zip") regions <- readOGR(".", "england_gor_2011") object_size(regions) # ~13MB regions <- ms_simplify(regions) object_size(regions) # < 1MB
sf::st_cast() which, from the man pages, states:
Cast geometry to another type: either simplify, or cast explicitly
to argument: character; target type, if missing, simplification is tried; when x is of type sfg (i.e., a single geometry) then to needs to be specified.
When I've left
to as missing this hasn't worked as expected though (I knew it was too good to be true!):
library("sf") regions <- sf::read_sf("england_gor_2011.shp") object_size(regions) # ~13MB regions <- sf::st_cast(regions) object_size(regions) # Still 13MB
Currently I'm opening the file with
rgdal::readOGR(), simplifying it, saving this, then loading this again with
Is there a better way?
@s.k 's suggestion of
rgeos::gSimplify() can do topologically-aware simplifications (i.e. simplifies without creating slivers) when specified with the following arguments:
library("rgeos") regions_gSimplify <- gSimplify(regions, tol = 0.05, topologyPreserve = TRUE)
gSimplify doesn't preserve the
@data frame, though, so we should re-create it:
regions_df <- regions@data regions_gSimplify <- sp::SpatialPolygonsDataFrame(regions_gSimplify, regions_df)
And this does indeed result in a smaller file size (can tweak
tol argument to get it smaller) and I confirmed this hadn't created any slivers by examining it in QGIS.
object_size(regions_gSimplify) # ~8MB
So although this is a valid alternative to
rmapshaper::ms_simplify() I still have the same problem, namely that it doesn't work with
regions_sf <- sf::read_sf("england_gor_2011.shp") object_size(regions_sf) regions_gSimplify <- gSimplify(regions_sf, topologyPreserve = TRUE, tol = 0.05) # Error in gSimplify(regions_sf, topologyPreserve = TRUE, tol = 0.05) : # no slot of name "proj4string" for this object of class "sf"
@obrl_soil 's answer can also be applied to
gSimplify(), just use it in place of