R Language – Creating Minimum Bounding Geometry Using the Convex Hull Method

convex hullextentsr

I would like to create a small enveloppe around a set of polygons that encloses around them. I would like to avoid using the bounding box function (example below) because it would be too big. Rather, I would like to use a convex-hull like algorithm to create a polygon just around the desired polygons. At the very least, an oblique rectangle/diamond would be an improvement to cut out all the corners.

In QGIS, the function is Minimum bounding geometry with the geometry type Convex hull.

Sample code for image below

data(meuse)
coordinates(meuse) = ~x+y
meuse<-as(meuse, "sf")
meuse_poly<-st_buffer(meuse, dist=meuse$elev*15)
meuse_poly$ID<-c(1:nrow(meuse_poly))

plot(st_geometry(meuse_poly))
plot(st_geometry(meuse_poly[which(meuse_poly$landuse=="Bw"),]), add=T, col="red")
plot(st_geometry(st_as_sfc(st_bbox(meuse_poly[which(meuse_poly$landuse=="Bw"),]))), add=T, border="blue")

enter image description here

Best Answer

I have a hidden function for calculating the Alpha Convex Hull (Pateiro-Lopez & Rodriguez-Casal 2009) in the development version of spatialEco. The reason this function is not in the CRAN release is due to licensing issues in the alphahull package.

Please note that this statistic only works for [x,y] data. Polygons are tricky because the bounding geometry is based on the vertices of each polygons, functionally making it based on points ([x,y] vertices). Because of this, if you want an alpha hull, it takes some extra data prep to get points representing the polygon boundaries.

Please install alphahull and remotes packages from CRAN and then install the development version of spatialEco using remotes::install_github.

remotes::install_github("jeffreyevans/spatialEco")
library(sp)
library(sf)
library(spatialEco)
library(dplyr)

Here we add some example data and create your polygons

data(meuse)
  sp::coordinates(meuse) = ~x+y
  meuse <- as(meuse, "sf")
  meuse_poly <- sf::st_buffer(meuse, dist = meuse$elev*15)

Now, we can get [x,y] data from the polygons using the sf::st_segmentize function.

poly_points <- sf::st_segmentize(meuse_poly, dfMaxLength = 5) %>% 
  sf::st_coordinates() %>% 
  as.data.frame() %>% 
  dplyr::select(X, Y) %>% 
  sf::st_as_sf(coords = c("X", "Y"))  

We can then pass the points the the convexHull function

a <- spatialEco::convexHull(poly_points,alpha = 100000, sp=FALSE)
 plot(sf::st_geometry(a), cex=1.5, col="red") 
    plot(sf::st_geometry(meuse_poly), add=TRUE)

Let's test multiple alpha values to find an optima.

  par(mfcol=c(2,2))
    for (a in c(500, 1500, 5000, 100000)) {
    ch <- spatialEco::convexHull(poly_points, alpha = a, sp = FALSE)
      plot(sf::st_geometry(ch), cex=1.5, col="red") 
        plot(sf::st_geometry(meuse_poly), add=TRUE)
         title(paste0("alpha=", a))      
    }

References

Pateiro-Lopez & Rodriguez-Casal (2009) Generalizing the Convex Hull of a Sample: The R Package alphahull. Journal of Statistical Software 34(5):1-28 http://www.jstatsoft.org/v34/i05/paper