1

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

4
  • Is your desired output really something like the blue line above? That looks like you could get something like it by buffering the polygons until you get a single ring. Would that work?
    – Spacedman
    Commented Jun 28, 2023 at 14:49
  • Yes I could but I don't find the method very elegant, you see I have to try multiple buffer distance to find which one will make the buffer touching each other. You see in this post (stackoverflow.com/questions/66936153/…) the islands are connected by a thin line. By doing this I would be able to make a general code without have to try different buffer distance. Commented Jun 29, 2023 at 8:11
  • So ideally you want to preserve your polygons and connect them with the thinnest bridges possible? Seems an odd thing to do though... Would it matter if there were multiple thin "bridges" between polygons, or sub-optimal? Because finding the optimal might be harder than finding a solution.
    – Spacedman
    Commented Jun 29, 2023 at 12:32
  • the answer was given to me there : stackoverflow.com/questions/76579854/… I'll delete this post in a bit:) Thanks for your time Commented Jun 29, 2023 at 13:31

1 Answer 1

0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.