Holmestorm
Holmestorm

Reputation: 103

Returning the boundary of a set of points in R as a polygon?

Im trying to return the boundary of a set of points (as below). I've tried three approaches using the {sf} package.

Create test data

t <- 
  crossing(x=1:5, y=1:5) %>% 
  filter(!(x > 3 & y > 3)) %>% 
  st_as_sf(coords=c("x", "y"))

What I want

ggplot()+
  geom_sf(data=t)+
  geom_segment(aes(x = c(1, 1, 3, 3, 5, 5),
                   xend = c(1, 3, 3, 5, 5, 1),
                   y = c(1, 5, 5, 3, 3, 1),
                   yend = c(5, 5, 3, 3, 1, 1),
                   col = "What I want"))

enter image description here

What I've tried

ggplot()+
  geom_sf(data=t)+
  geom_sf(data = t %>% st_union() %>% st_convex_hull(), aes(col="st_convex_hull"), fill=NA)+
  geom_sf(data = t %>% st_union() %>% st_cast("POLYGON") %>% st_boundary(), aes(col = "st_boundary"))+
  geom_sf(data = 
            t %>% 
            st_union() %>% .
            st_buffer(0.5, endCapStyle = "SQUARE") %>% 
            st_buffer(-0.5, endCapStyle = "SQUARE"), 
          aes(col="st_buffer twice"), fill=NA)

enter image description here

I thought I might be on to something with using st_buffer() twice, but it still gives a curved outline. Also, putting the issue of the curved line aside, it runs very slowly on my real data (which contains hundreds of thousands of points).

Upvotes: 1

Views: 1110

Answers (1)

Jindra Lacko
Jindra Lacko

Reputation: 8749

I suggest you consider the {concaveman} package; in the specific case of your toy example it seems to work nicely. You may need to tune the value of the concavity parameter a bit.

I am not in position to comment on how good (or fast) it will perform on your actual data, but it should give you a start.

library(tidyverse)

t <- 
  crossing(x=1:5, y=1:5) %>% 
  filter(!(x > 3 & y > 3)) %>% 
  sf::st_as_sf(coords=c("x", "y"))

asdf <- t %>% 
  summarise() %>% 
  concaveman::concaveman(concavity = 1)

plot(asdf)

enter image description here

Upvotes: 8

Related Questions