如何使用R sf从多边形中去除“几乎洞”?

gcuhipw9  于 2023-02-20  发布在  其他
关注(0)|答案(1)|浏览(176)

我有一个多边形,它有一些洞和一些“几乎洞”,这些洞是多边形的细长入口。(多边形文件HERE

field <- sf::read_sf("example_field.kml")
ggplot() +
  geom_sf(data = field) +
  theme_void()

我可以使用以下命令从多边形中删除一个“真正的”孔:

field_no_holes <- nngeo::st_remove_holes(field)
ggplot() +
  geom_sf(data = field_no_holes) +
  theme_void()

然而,这仍然留下了几个又长又细的“几乎是洞”。关于如何有效地去除这些洞,有什么想法吗?作为参考,这里是我的最终目标(我通过手动删除顶点创建了这个)。

field_fixed <- sf::read_sf("example_field_fixed.kml") %>%
  nngeo::st_remove_holes()
ggplot() +
  geom_sf(data = field_fixed) +
  theme_void()

gxwragnw

gxwragnw1#

下面有几种方法可以做到这一点。你必须弄清楚如何摆弄一些东西来弄清楚如何定义“瘦”。
第一种基于@dieghernan注解,添加了取消缓冲的步骤,以将形状返回到与其开始时大致相同的大小:

libarary(tidyverse)
library(sf)

x <- read_sf('example_field.kml')

x %>% 
 st_transform(3857) %>%      # crs 3857 allows buffering in meters
  st_buffer(dist = 20) %>%   # make the polygon 20m bigger to get rid of 'skinny' holes
  st_buffer(dist = -20) %>%  # shrink it back down to approximately the right size
  ggplot() +                 # plotting
   geom_sf(fill = 'black') + 
   geom_sf(data = x, fill = NA, col = 'red') +
   theme_void()

原始多边形轮廓为红色,新多边形填充为黑色:

这可能会遇到一些问题,凹点不是很正确的那种'瘦'。看到右下角的凹痕。
另一个更费力的解决方案可能不会被洞的“皮肤”卡住。取多边形的规则样本作为点,然后移除那些离缓冲和未缓冲多边形太远的点。将剩余的点变成多边形。

# regular sample of 1000 points of the polygon
points <- x %>% 
  st_cast('LINESTRING') %>%
  st_sample(size = 1000, type = 'regular') %>%
  st_zm() %>%  # remove z
  st_cast('POINT')

# similar to solution 1, buffer & un-buffer original polygon
buffered <- x %>% 
    st_transform(3857) %>% 
    st_buffer(20) %>% 
    st_buffer(-20) %>%
    st_transform(st_crs(points)) %>%
    st_cast('LINESTRING')

# select sampled points that are very near the buffer,
#  then cast them to a polygon
poly_from_points <- points[st_is_within_distance(points, buffered, dist = 5, sparse = F)] %>% 
st_combine() %>% 
st_cast('LINESTRING') %>% 
st_cast('POLYGON')

对于给定的示例文件,此方法可能不是必需的。在一些边缘情况下,此方法不太可能失败。
下图放大了右下角(东南)的凹口,以显示两种方法的差异沿着原始面。红色表示缓冲和取消缓冲(方法1),蓝色表示仅原始面中的点(方法2),近似黑色表示原始面。

相关问题