Simplifica los polígonos del objeto sf

14

¿Cómo simplifico un sfpolígono sin introducir huecos y astillas?

Con un shapefile, por ejemplo, usaría rmapshaper::ms_simplify():

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

He intentado lo sf::st_cast()que, desde las páginas de manual, dice:

Convertir geometría a otro tipo: simplificar o emitir explícitamente

y:

a argumento: personaje; tipo de destino, si falta, se intenta la simplificación; cuando x es de tipo sfg (es decir, una sola geometría), entonces debe especificarse.

Sin toembargo, cuando me fui como desaparecido, esto no funcionó como se esperaba (¡sabía que era demasiado bueno para ser verdad!):

library("sf")
regions <- sf::read_sf("england_gor_2011.shp")
object_size(regions)
# ~13MB

regions <- sf::st_cast(regions)
object_size(regions)
# Still 13MB

Actualmente estoy abriendo el archivo rgdal::readOGR(), lo simplifico, lo guardo y luego lo vuelvo a cargar con sf.

¿Hay una mejor manera?


rgeos::gSimplify()

La sugerencia de @sk de rgeos::gSimplify()puede hacer simplificaciones topológicamente conscientes (es decir, simplifica sin crear fragmentos) cuando se especifica con los siguientes argumentos:

library("rgeos")
regions_gSimplify <- gSimplify(regions, tol = 0.05, topologyPreserve = TRUE)

gSimplifysin embargo, no conserva el @datamarco, por lo que deberíamos volver a crearlo:

regions_df <- regions@data
regions_gSimplify <- sp::SpatialPolygonsDataFrame(regions_gSimplify, regions_df)

Y esto de hecho resulta en un tamaño de archivo más pequeño (puede ajustar el tolargumento para hacerlo más pequeño) y confirmó que no había creado ningún fragmento al examinarlo en QGIS.

object_size(regions_gSimplify)
# ~8MB

Entonces, aunque esta es una alternativa válida rmapshaper::ms_simplify(), sigo teniendo el mismo problema, es decir, que no funciona con sf:

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"

La respuesta de @obrl_soil también se puede aplicar gSimplify(), simplemente úsela en lugar de ms_simplify().

Phil
fuente
1
¿Tiene algún acceso a un algoritmo Douglas-Peucker? Es ampliamente conocido por la simplificación de funciones en el mundo SIG. stackoverflow.com/questions/17217413/… & r-bloggers.com/simplifying-spatial-polygons-in-r
sk
1
¿No se st_simplifysupone que debe hacer eso? (no lo
usé
2
ooh, no me había dado cuenta st_simplify, gracias por señalarlo. Prefiero el algoritmo rmapshaper::ms_simplifypredeterminado que todos los demás que he probado hasta ahora, pero preserveTopology = TRUE
jugaré
1
Bueno saber. ¿Qué hay de abrir un informe de error sobre esto?
lbusett
1
@obrl_soil Funciona para tolerancias de hasta aproximadamente 1000 en los polígonos que he usado en la pregunta ( regions) pero más allá de eso ya no conserva la topología. Como se rompe en cierto punto, diría que no es un comportamiento intencionado
Phil

Respuestas:

16

Puede lanzar un objeto sf a sp, para paquetes que aún no admiten sf. Lo hago bastante bien para las interacciones ráster / polígono. Entonces podrías hacer:

simplepolys <- rmapshaper::ms_simplify(input = as(sfobj, 'Spatial')) %>%
  st_as_sf()
obrl_soil
fuente
1
Esta técnica, lanzar como un objeto espacial, simplificar y luego volver a lanzar como un sfobjeto, funcionó perfectamente y se puede usar con rmapshaper::ms_simplify()o rgeos::gSimplify(). ¡Gracias por la sugerencia!
Phil
Genial, ten en cuenta que la topología de los polígonos entrelazados solo se conserva realmente con el enfoque de rmapshaper. Si sus datos de entrada son todos polígonos aislados que no se entrelazan, puede usar de manera segura cualquiera de los algs de simplificación disponibles.
obrl_soil
Estoy aceptando esto como la respuesta porque el más canónico sf::st_simplify()no es robusto a altas tolerancias al momento de escribir, aunque obviamente esto puede cambiar.
Phil
8
Actualmente estoy trabajando en soporte para sfobjetos en rmapshaper . ms_simplifyestá disponible para sfobjetos en la versión de desarrollo. Me encantaría primeros probadores - si quieres probarlo, que puede instalar condevtools::install_github("ateucher/rmapshaper", ref = "sf")
andyteucher
66
A partir de la rmapshaperversión 0.3.0, la llamada a as( , "Spatial")ya no es necesaria.
Luke1018