【问题标题】:Filling gaps in multipart polygons without creating overlapping polygons填充多部分多边形中的间隙而不创建重叠多边形
【发布时间】:2022-11-07 06:41:48
【问题描述】:

我想填补多部分多边形的空白,为每个要素创建一个范围多边形。

我试图在多部分功能上做一个 250m 的缓冲区,然后做一个 250m 的负缓冲区。这几乎可行,但会创建与相邻要素重叠的多边形。

是否有一种方法可以执行类似于我下面的代码但确保多边形不重叠的方法?

library(sf)
library(dplyr)

download.file("https://drive.google.com/uc?export=download&id=1Iyk7XhPHY5rs4OLI56b3GHibZIPdDnpo" , destfile="Areas.zip")
unzip("Areas.zip")
Areas <- st_read("Areas.gpkg") 

Area_1 <- Areas %>%
    filter(name == "Area 1") %>% 
    st_buffer(., 250) %>% 
    st_buffer(., -250) 
    
New_Areas <- bind_rows(Area_1, Areas %>% filter(name != "Area 1"))

【问题讨论】:

    标签: r geospatial polygon sf


    【解决方案1】:

    编辑:concaveman 方法

    作为替代方法,您可以在对象周围创建一个外壳,并使用该坐标创建一个多边形。 concaveman 包对于这项任务非常有用,另请参见 https://gis.stackexchange.com/questions/354276/using-r-and-sf-create-an-concave-envelope-polygon-around-multilinestring

    library(sf)
    library(dplyr)
    library(ggplot2)
    
    download.file("https://drive.google.com/uc?export=download&id=1Iyk7XhPHY5rs4OLI56b3GHibZIPdDnpo",
      destfile = "Areas.zip",
      mode = "wb"
    )
    unzip("Areas.zip", exdir = ".")
    
    Areas <- st_read("Areas.gpkg")
    #> Simple feature collection with 6 features and 1 field
    #> Geometry type: MULTIPOLYGON
    #> Dimension:     XY
    #> Bounding box:  xmin: 272036.8 ymin: 432143.8 xmax: 288261.8 ymax: 446143.8
    #> Projected CRS: OSGB 1936 / British National Grid
    
    Area_1 <- Areas %>%
      filter(name == "Area 1")
    
    # Use concaveman
    library(concaveman)
    geom_convex <- concaveman(st_coordinates(Area_1)[, 1:2]) %>%
      list() %>%
      st_polygon() %>%
      st_sfc()
    
    Area_convex <- st_sf(st_drop_geometry(Area_1),
      geom = geom_convex,
      crs = st_crs(Areas)
    )
    
    plot(st_geometry(Area_convex), col = "red")
    plot(st_geometry(Area_1), add = TRUE, border = "blue")
    

    New_Areas <- bind_rows(Area_convex, Areas %>% filter(name != "Area 1"))
    
    ggplot() +
      geom_sf(data = New_Areas, fill = "red")
    

    reprex package (v2.0.1) 于 2022 年 6 月 16 日创建

    旧答案:坚持缓冲方法

    您可以在重新合并之前使用st_difference() 删除重叠部分:

    library(sf)
    library(dplyr)
    library(ggplot2)
    
    download.file("https://drive.google.com/uc?export=download&id=1Iyk7XhPHY5rs4OLI56b3GHibZIPdDnpo",
      destfile = "Areas.zip",
      mode = "wb"
    )
    unzip("Areas.zip", exdir = ".")
    
    Areas <- st_read("Areas.gpkg")
    #> Reading layer `Areas' from data source 
    #>   `/tmp/Rtmpw1wNtg/reprex-2125ac8065c-loyal-rat/Areas.gpkg' using driver `GPKG'
    #> Simple feature collection with 6 features and 1 field
    #> Geometry type: MULTIPOLYGON
    #> Dimension:     XY
    #> Bounding box:  xmin: 272036.8 ymin: 432143.8 xmax: 288261.8 ymax: 446143.8
    #> Projected CRS: OSGB 1936 / British National Grid
    
    ggplot(Areas) +
      geom_sf()
    

    Area_1 <- Areas %>%
      filter(name == "Area 1") %>%
      st_buffer(250) %>%
      st_buffer(-250)
    
    NoArea_1 <- Areas %>% filter(name != "Area 1")
    
    Area_1_end <- st_difference(Area_1, st_union(st_geometry(NoArea_1)))
    #> Warning: attribute variables are assumed to be spatially constant throughout all
    #> geometries
    
    st_overlaps(Area_1, NoArea_1, sparse = FALSE)
    #>      [,1]  [,2]  [,3] [,4] [,5]
    #> [1,] TRUE FALSE FALSE TRUE TRUE
    
    st_overlaps(Area_1_end, NoArea_1, sparse = FALSE)
    #>       [,1]  [,2]  [,3]  [,4]  [,5]
    #> [1,] FALSE FALSE FALSE FALSE FALSE
    
    ggplot(Area_1) +
      geom_sf() +
      geom_sf(data = Area_1_end, fill = NA, color = "red")
    

    ggplot(Area_1_end) +
      geom_sf(fill = "red") +
      geom_sf(data = NoArea_1, fill = "blue", alpha = 0.1)
    

    New_Areas <- bind_rows(Area_1_end, Areas %>% filter(name != "Area 1"))
    
    New_Areas
    #> Simple feature collection with 6 features and 1 field
    #> Geometry type: GEOMETRY
    #> Dimension:     XY
    #> Bounding box:  xmin: 272036.8 ymin: 432143.8 xmax: 288261.8 ymax: 446143.8
    #> Projected CRS: OSGB 1936 / British National Grid
    #>     name                           geom
    #> 1 Area 1 POLYGON ((272911.8 441747.1...
    #> 2 Area 2 MULTIPOLYGON (((280486.8 43...
    #> 3 Area 3 MULTIPOLYGON (((272061.8 44...
    #> 4 Area 4 MULTIPOLYGON (((286586.8 43...
    #> 5 Area 5 MULTIPOLYGON (((282261.8 44...
    #> 6 Area 6 MULTIPOLYGON (((285261.8 43...
    

    reprex package (v2.0.1) 于 2022 年 6 月 15 日创建

    【讨论】:

      【解决方案2】:

      请注意,concaveman 方法确实不是生成不重叠的多边形。

      library(sf)
      #> Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
      library(dplyr)
      #> 
      #> Attaching package: 'dplyr'
      #> The following objects are masked from 'package:stats':
      #> 
      #>     filter, lag
      #> The following objects are masked from 'package:base':
      #> 
      #>     intersect, setdiff, setequal, union
      library(ggplot2)
      
      download.file("https://drive.google.com/uc?export=download&id=1Iyk7XhPHY5rs4OLI56b3GHibZIPdDnpo",
        destfile = "Areas.zip",
        mode = "wb"
      )
      unzip("Areas.zip", exdir = ".")
      
      Areas <- st_read("Areas.gpkg")
      #> Reading layer `Areas' from data source 
      #>   `TempRtmpoRVQgr
      eprex-1a645c5d56e-goofy-coneyAreas.gpkg' 
      #>   using driver `GPKG'
      #> Simple feature collection with 6 features and 1 field
      #> Geometry type: MULTIPOLYGON
      #> Dimension:     XY
      #> Bounding box:  xmin: 272036.8 ymin: 432143.8 xmax: 288261.8 ymax: 446143.8
      #> Projected CRS: OSGB 1936 / British National Grid
      Area_1 <- Areas %>%
        filter(name == "Area 1")
      
      NoArea_1 <- filter(Areas, name != "Area 1")
      
      # Original areas don´t overlap
      st_overlaps(Area_1, NoArea_1, sparse = FALSE)
      #>       [,1]  [,2]  [,3]  [,4]  [,5]
      #> [1,] FALSE FALSE FALSE FALSE FALSE
      
      # Use concaveman
      library(concaveman)
      geom_convex <- concaveman(st_coordinates(Area_1)[, 1:2]) %>%
        list() %>%
        st_polygon() %>%
        st_sfc()
      
      Area_convex <- st_sf(st_drop_geometry(Area_1),
        geom = geom_convex,
        crs = st_crs(Areas)
      )
      
      # New areas do overlap
      st_overlaps(Area_convex, NoArea_1, sparse = FALSE)
      #>      [,1]  [,2]  [,3] [,4] [,5]
      #> [1,] TRUE FALSE FALSE TRUE TRUE
      

      创建于 2022-11-06,reprex v2.0.2

      因此,如果您想使用concaveman 解决方案,您需要使用st_difference,就像在缓冲区方法中一样。

      # Need to use st_difference
      Area_convex_end <- st_difference(Area_convex, st_union(st_geometry(NoArea_1)))
      #> Warning: attribute variables are assumed to be spatially constant throughout all
      #> geometries
      
      st_overlaps(Area_convex_end, NoArea_1, sparse = FALSE)
      #>       [,1]  [,2]  [,3]  [,4]  [,5]
      #> [1,] FALSE FALSE FALSE FALSE FALSE
      

      创建于 2022-11-06,reprex v2.0.2

      选择一种或另一种解决方案的原因应该基于挤压多边形的形状。

      【讨论】: