Semplifica i poligoni dell'oggetto sf


14

Come posso semplificare un sfpoligono senza introdurre spazi vuoti e scaglie?

Con uno shapefile, ad esempio, vorrei usare 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

Ho provato sf::st_cast()che, dalle pagine man, afferma:

Trasforma la geometria in un altro tipo: semplifica o esegui il cast esplicitamente

e:

all'argomento: carattere; tipo di destinazione, se mancante, si tenta di semplificare; quando x è di tipo sfg (cioè una singola geometria), allora deve essere specificato.

Quando me ne sono andato via toquesto non ha funzionato come previsto (sapevo che era troppo bello per essere vero!):

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

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

Attualmente sto aprendo il file con rgdal::readOGR(), semplificandolo, salvandolo, quindi caricandolo di nuovo con sf.

C'è un modo migliore?


rgeos::gSimplify()

Il suggerimento di @sk rgeos::gSimplify()può fare semplificazioni attente alla topologia (ovvero semplificare senza creare scaglie) se specificato con i seguenti argomenti:

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

gSimplifynon preserva il @dataframe, quindi dovremmo ricrearlo:

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

E questo si traduce in una dimensione del file inferiore (può modificare l' tolargomento per ridurlo) e ho confermato che questo non ha creato alcun frammento esaminandolo in QGIS.

object_size(regions_gSimplify)
# ~8MB

Quindi, sebbene questa sia una valida alternativa, rmapshaper::ms_simplify()ho ancora lo stesso problema, vale a dire che non funziona 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 risposta di @obrl_soil può anche essere applicata gSimplify(), basta usarla al posto di ms_simplify().


1
Hai accesso a un algoritmo Douglas – Peucker? È ampiamente noto per la semplificazione delle funzionalità nel mondo GIS. stackoverflow.com/questions/17217413/... & r-bloggers.com/simplifying-spatial-polygons-in-r
sk

1
Non st_simplifydovrebbe farlo? (non l'ho ancora usato)
lbusett,

2
ooh, non me ne ero accorto st_simplify, grazie per averlo sottolineato. Preferisco l'algoritmo rmapshaper::ms_simplifypredefinito rispetto a tutti gli altri che ho provato finora, ma avrò un gioco con la nuova opzione (aggiornamento: whoa procedere con cautela, preserveTopology = TRUEsicuramente non funziona ancora correttamente)
obrl_soil

1
Buono a sapersi. Che ne dici di aprire una segnalazione di bug al riguardo?
Lbusett,

1
@obrl_soil Funziona con tolleranze fino a circa 1000 sui poligoni che ho usato nella domanda ( regions) ma oltre a ciò non conserva più la topologia. Dato che si rompe a un certo punto, direi che non è un comportamento previsto
Phil

Risposte:


16

Puoi lanciare un oggetto sf su sp, per pacchetti che non supportano ancora sf - lo faccio abbastanza per le interazioni raster / poligoni. Quindi potresti fare:

simplepolys <- rmapshaper::ms_simplify(input = as(sfobj, 'Spatial')) %>%
  st_as_sf()

1
Questa tecnica - casting come oggetto spaziale, semplificazione, quindi re-casting come sfoggetto - ha funzionato perfettamente e può essere utilizzata con rmapshaper::ms_simplify()o rgeos::gSimplify(). Grazie per il suggerimento!
Phil

Cool cool, basta essere consapevoli del fatto che la topologia dei poligoni ad incastro è davvero preservata solo con l'approccio di rmapshaper. Se i tuoi dati di input sono tutti poligoni isolati e non interbloccati, puoi tranquillamente utilizzare uno qualsiasi degli algoritmi di semplificazione disponibili.
obrl_soil,

Sto accettando questa come risposta perché il più canonico sf::st_simplify()non è robusto con tolleranze elevate al momento della scrittura, anche se ovviamente questo può cambiare.
Phil

8
Attualmente sto lavorando su supporto per sfoggetti in rmapshaper . ms_simplifyè disponibile per gli sfoggetti nella versione di sviluppo. Mi piacerebbe i primi tester - se vuoi provarlo, puoi installarlo condevtools::install_github("ateucher/rmapshaper", ref = "sf")
andyteucher

6
A partire dalla rmapshaperversione 0.3.0, la chiamata a as( , "Spatial")non è più necessaria.
Luke1018
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.