R Spatial Analysis – Joining Polygons from Same Data Source into Smooth Polygon

polygonpolygonizersfspatial-join

I would like to create on single polygon from multiple small polygons (see the image below which represents what I want)

I need to connect the polygons and I found that purrr::st_connect might work but it seems we need two objects to connect but in my case all polygons are in the same object.
When I will have one object I will apply smoothr::smooth() function that smooth the border of a polygon.

Can someone please tell me how I could connect polygons which are within the same object?

library(dplyr)
library(sf)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
set.seed(2806)
nc_sample=dplyr::sample_n(nc,10)
ggplot() + geom_sf(data = nc_sample)

enter image description here

As suggested by Spacedman in the comment I could create buffers around my polygons, I connect them and i get the image below. But the thing is I would have to select a different distance for the buffer if I apply the code to states which are further away than those in this sample.

nc_buffer = st_buffer(nc_sample, 40000)
nc_poly=st_union(nc_buffer)

ggplot() + 
  geom_sf(data = nc_poly) +
  geom_sf(data = nc_sample) 

enter image description here

Best Answer

Here's another take, utilizing GEOS concave transformer.
If {sf} is built with GEOS >= 3.11.0 (not the case with current {sf} Windows binaries from CRAN), sf::st_concave_hull() should be enough. But those stuck with Windows binaries can also use {geos}, which currently comes with GEOS 3.11.1, provides geos_c_concave_hull() bindings and gets along with {sf} just fine.

The idea here is to first add points to straight line segments, this allows to use smaller ratio in geos_concave_hull(). Somehow st_segmentize() was outperformed by st_buffer(), results were also more suitable for next steps.

library(dplyr)
library(sf)
library(ggplot2)

sf::sf_extSoftVersion()["GEOS"]
#>    GEOS 
#> "3.9.3"
geos::geos_version()
#> [1] '3.11.1'

nc <- st_read(system.file("shape/nc.shp", package="sf"))
set.seed(2806)
nc_sample=dplyr::sample_n(nc,10)

# by first adding points to polygons, we can go lower with 
# ratio values of geos_concave_hull()
smooth_buffer <-
  st_geometry(nc_sample) %>% 
  st_buffer(1) %>%  
  st_union() %>%
  as_geos_geometry() %>% 
  geos_concave_hull(ratio = .01) %>% 
  st_as_sfc() %>% 
  st_buffer(5000) %>%
  smooth(method = "ksmooth", smoothness = 5) 

ggplot() +
  geom_sf(data = smooth_buffer, fill = NA, color = "#03abcc", linewidth = 1) +
  geom_sf(data = nc_sample, fill = "grey90") +
  theme_minimal()

Created on 2023-07-01 with reprex v2.0.2