Reputation: 103
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"))
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"))
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)
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
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)
Upvotes: 8