Упростить полигоны объекта sf

14

Как мне упростить sfмногоугольник без введения пробелов и осколков?

С шейп-файлом, например, я бы использовал 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

Я пробовал, sf::st_cast()который, из man-страниц, заявляет:

Приведите геометрию к другому типу: либо упростите, либо приведите явно

и:

для аргументации: характер; тип цели, если отсутствует, попытка упрощения; когда x имеет тип sfg (т. е. одиночную геометрию), то необходимо указать.

Когда я toпропал без вести, это не сработало, как ожидалось (я знал, что это слишком хорошо, чтобы быть правдой!):

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

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

В настоящее время я открываю файл rgdal::readOGR(), упрощаю его, сохраняю и загружаю снова sf.

Есть ли способ лучше?


rgeos::gSimplify()

Предложение @sk rgeos::gSimplify()может делать топологически упрощенные упрощения (то есть упрощает без создания осколков), если указано со следующими аргументами:

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

gSimplify@dataоднако, не сохраняет фрейм, поэтому мы должны создать его заново:

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

И это действительно приводит к меньшему размеру файла (можно настроить tolаргумент, чтобы уменьшить его), и я подтвердил, что это не создало проскальзываний, изучив его в QGIS.

object_size(regions_gSimplify)
# ~8MB

Так что, хотя это верная альтернатива, у rmapshaper::ms_simplify()меня все еще есть та же проблема, а именно, что она не работает с 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"

Ответ @obrl_soil также может быть применен gSimplify(), просто используйте его вместо ms_simplify().

Фил
источник
1
Есть ли у вас доступ к алгоритму Дугласа – Пекера? Это широко известно для упрощения функций в мире ГИС. stackoverflow.com/questions/17217413/… & r-bloggers.com/simplifying-spatial-polygons-in-r
sk
1
Разве не st_simplifyдолжен этого делать? (пока не использовал)
lbusett
2
о, я не заметил st_simplify, спасибо, что указал на это. Я предпочитаю алгоритм, который по rmapshaper::ms_simplifyумолчанию превосходит все остальные, которые я пробовал до сих пор, но я поиграю с новой опцией (обновление: но будьте осторожны, preserveTopology = TRUEопределенно пока не работает должным образом)
obrl_soil
1
Хорошо знать. Как насчет открытия сообщения об ошибке по этому вопросу?
lbusett
1
@obrl_soil Он работает для допусков примерно до 1000 для многоугольников, которые я использовал в вопросе ( regions), но кроме этого он больше не сохраняет топологию. Так как в какой-то момент он ломается, я бы сказал, что это не намеренное поведение
Фил,

Ответы:

16

Вы можете привести объект sf к sp для пакетов, которые еще не поддерживают sf - я делаю это справедливо для взаимодействий растров / полигонов. Так что вы могли бы сделать:

simplepolys <- rmapshaper::ms_simplify(input = as(sfobj, 'Spatial')) %>%
  st_as_sf()
obrl_soil
источник
1
Эта техника - приведение в качестве пространственного объекта, упрощение, а затем повторное приведение в качестве sfобъекта - отлично работала и может использоваться с rmapshaper::ms_simplify()или rgeos::gSimplify(). Спасибо за предложение!
Фил
Круто круто, просто имейте в виду, что топология взаимосвязанных полигонов действительно сохраняется только с помощью подхода rmapshaper. Если все ваши входные данные являются изолированными, не блокирующими многоугольниками, вы можете безопасно использовать любой из доступных упрощающих алгоритмов.
obrl_soil
Я принимаю это как ответ, потому что более канонический sf::st_simplify()не устойчив при высоких допусках во время написания, хотя, очевидно, это может измениться.
Фил
8
В настоящее время я работаю над поддержкой sfобъектов в rmapshaper . ms_simplifyдоступно для sfобъектов в разрабатываемой версии. Мне бы очень понравились ранние тестеры - если вы хотите попробовать это, вы можете установить сdevtools::install_github("ateucher/rmapshaper", ref = "sf")
andyteucher
6
Начиная с rmapshaperверсии 0.3.0, вызов as( , "Spatial")больше не требуется.
Luke1018