Sederhanakan poligon dari objek sf

14

Bagaimana cara menyederhanakan sfpoligon tanpa memasukkan celah dan sliver?

Dengan shapefile, misalnya, saya akan menggunakan 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

Saya sudah mencoba sf::st_cast()yang, dari halaman manual, menyatakan:

Transmisikan geometri ke tipe lain: sederhanakan, atau gulirkan secara eksplisit

dan:

argumen: karakter; tipe target, jika hilang, penyederhanaan dicoba; ketika x adalah tipe sfg (yaitu, satu geometri) maka perlu ditentukan.

Namun ketika saya pergi tosebagai hilang, ini tidak berfungsi seperti yang diharapkan (saya tahu itu terlalu bagus untuk menjadi kenyataan!):

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

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

Saat ini saya sedang membuka file dengan rgdal::readOGR(), menyederhanakannya, menyimpan ini, kemudian memuatnya lagi dengan sf.

Apakah ada cara yang lebih baik?


rgeos::gSimplify()

Saran @sk tentang rgeos::gSimplify()dapat melakukan penyederhanaan sadar-topologi (yaitu menyederhanakan tanpa membuat sliver) ketika ditentukan dengan argumen berikut:

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

gSimplifytidak menyimpan @databingkai, jadi kita harus membuatnya kembali:

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

Dan ini memang menghasilkan ukuran file yang lebih kecil (dapat mengubah tolargumen untuk membuatnya lebih kecil) dan saya mengkonfirmasi ini belum membuat sliver dengan memeriksanya di QGIS.

object_size(regions_gSimplify)
# ~8MB

Jadi, meskipun ini merupakan alternatif yang valid untuk rmapshaper::ms_simplify()saya masih memiliki masalah yang sama, yaitu bahwa itu tidak bekerja dengan 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"

Jawaban @obrl_soil juga dapat diterapkan gSimplify(), cukup gunakan sebagai ganti ms_simplify().

Phil
sumber
1
Apakah Anda memiliki akses ke algoritma Douglas-Peucker? Secara luas diketahui penyederhanaan fitur di dunia GIS. stackoverflow.com/questions/17217413/… & r-bloggers.com/simplifying-spatial-polygons-in-r
sk
1
Bukankah st_simplifyseharusnya melakukan itu? (belum menggunakannya)
lbusett
2
ooh, saya tidak menyadarinya st_simplify, terima kasih telah menunjukkannya. Saya lebih suka algoritma yang rmapshaper::ms_simplifydefaultnya melebihi semua yang lain yang saya coba sejauh ini, tapi saya akan bermain dengan opsi baru (pembaruan: whoa lanjutkan dengan hati-hati, preserveTopology = TRUEpasti belum bekerja dengan benar)
obrl_soil
1
Senang mendengarnya. Bagaimana dengan membuka laporan bug tentang ini?
lbusett
1
@obrl_soil Ini berfungsi untuk toleransi hingga sekitar 1000 pada poligon yang saya gunakan dalam pertanyaan ( regions) tetapi di luar itu tidak lagi mempertahankan topologi. Ketika itu pecah pada titik tertentu saya akan mengatakan itu bukan perilaku yang diinginkan
Phil

Jawaban:

16

Anda dapat melemparkan objek sf ke sp, untuk paket yang belum mendukung sf - Saya melakukan ini sedikit adil untuk interaksi raster / poligon. Jadi Anda bisa melakukan:

simplepolys <- rmapshaper::ms_simplify(input = as(sfobj, 'Spatial')) %>%
  st_as_sf()
obrl_soil
sumber
1
Teknik ini - casting sebagai objek spasial, menyederhanakan, kemudian casting ulang sebagai sfobjek - bekerja dengan sempurna, dan dapat digunakan dengan rmapshaper::ms_simplify()atau rgeos::gSimplify(). Terima kasih untuk sarannya!
Phil
Keren keren, perlu diketahui bahwa topologi poligon yang saling terkait hanya benar-benar dipertahankan dengan pendekatan rmapshaper. Jika semua data input Anda terisolasi, poligon yang tidak saling terkait, Anda dapat dengan aman menggunakan salah satu alg penyederhanaan yang tersedia.
obrl_soil
Saya menerima ini sebagai jawaban karena semakin kanonik sf::st_simplify()tidak kuat pada toleransi tinggi pada saat penulisan, meskipun jelas ini dapat berubah.
Phil
8
Saat ini saya sedang mengerjakan dukungan untuk sfobjek di rmapshaper . ms_simplifytersedia untuk sfobjek dalam versi pengembangan. Saya suka penguji awal - jika Anda ingin mencobanya, Anda dapat menginstal dengandevtools::install_github("ateucher/rmapshaper", ref = "sf")
andyteucher
6
Pada rmapshaperversi 0.3.0, panggilan ke as( , "Spatial")tidak lagi diperlukan.
Luke1018