Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting (alpha) hulls to spatial polygon

In R, I wish to convert the alpha shape polygon surrounding a bunch of points into one single spatial polygon object.

library(sf)
library(alphahull)

To start out, I create the point random points distribution

dat <- matrix(c(1,2,3,4,5, 3,3,5,6,9), ncol = 2)

I find the alpha shape covering the points (i.e. a polygon encompassing all points). I am particularly interested in this function as it has the feature to find a more or less tight polygon shape according to the given alpha

dat.ashape<- ashape(dat, alpha= 7) 

I take the coordinates of the extreme

coords<- dat.ashape$x[dat.ashape$alpha.extreme,]

I make the last point same as the first (to have a closed shape)

coords<- rbind(coords, coords[1,]) 

To make things to work I need to order the point in sequence

coords<- cbind(coords, NA) 
coords[,3]<- c(1, 5, 3, 2, 4, 6) 
coords<- coords[order(coords[,3]),]

I create the simple spatial point feature from the coordinate matrix

dat.sf <- st_multipoint(coords, dim = "XYZ")

... and create the polygon

tst<- dat.sf %>% # 
  st_cast('POLYGON')

Finally, comparing the point and shape distribution and the polygon, I was able to build the polygon correctly, but this is rather easy with six points! (Because I made myself manually the right order)

plot(dat.ashape) 
plot(tst, add=T, col=adjustcolor('red', alpha.f=.3), border=2)

In a more sophisticated example with say 100 points, I get stuck in the part where I should get the sequence of points right, before st_cast into polygon.

set.seed(1)
dat <- matrix(stats::rnorm(100), ncol = 2)
dat.ashape<- ashape(dat, alpha=7)
coords<- dat.ashape$x[dat.ashape$alpha.extreme,] 
coords<- rbind(coords, coords[1,]) 

dat.sf <- st_multipoint(coords, dim = "XY")

tst <- dat.sf %>%
  st_cast('POLYGON')

plot(dat.ashape)
plot(tst, add=T, col=adjustcolor('red', alpha.f=.3), col.line='red', border=2)

.... and I obviously do not get trick done.

I am grateful for any help!

like image 771
Dario Fiorentino Avatar asked Nov 18 '25 13:11

Dario Fiorentino


1 Answers

Based on the answer just above (thanks!). For me this worked using sf only:

library(sf)
library(dplyr)
library(alphahull)

# get your ashape object
aoi <- ashape(pts, alpha = 2000)

# converted to sf polygons
a <- data.frame(aoi$edges)[,c( 'x1', 'y1', 'x2', 'y2')]
l <- st_linestring(matrix(as.numeric(a[1,]), ncol=2, byrow = T))
for(i in 2:nrow(a)){
  l <- c(l, st_linestring(matrix(as.numeric(a[i,]), ncol=2, byrow = T)))
}
alphapoly <- st_sf(geom = st_sfc(l), crs = 2056) %>% st_polygonize() %>% st_collection_extract()
like image 85
Dominique Weber Avatar answered Nov 21 '25 01:11

Dominique Weber



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!