John J.
John J.

Reputation: 1716

How to compute the greatest distance between a centroid and the edge of the polygon using the SF package?

I have a bunch of variously shaped and sized polygons with centroids. I want to calculate distance from each centroid to the furthest point of its respective polygon.

This question has been resolved here using the package::sp and package::rgeos.

According to its vignette, the sf package "aims at succeeding sp in the long term." Looking through the documentation I was unable to find a solution, but I'm no expert on simple features. Is there a good way to complete this operation using the sf package, or should I stick with sf and rgeos for now?

Upvotes: 4

Views: 2419

Answers (2)

Gilles San Martin
Gilles San Martin

Reputation: 4370

I'm not certain to understand what you want exactly : the distance to the furthest point (this what you ask) or the coordinates of the furthest point (this is what is provided by the answer you point to).

Here is a solution to calculate the distance (and that can easily be changed to extract the coordinates)

# This is an example for one polygon.
# NB the polygon is the same as in the answer pointed to in the question

library(sf)
sfPol <- st_sf(st_sfc(st_polygon(list(cbind(c(5,4,2,5),c(2,3,2,2))))))

center <- st_centroid(sfPol)
vertices <-  st_coordinates(sfPol)[,1:2]
vertices <-  st_as_sf(as.data.frame(vertices), coords = c("X", "Y"))
furthest <- max(st_distance(center, vertices))
furthest

## [1] 1.699673



# You can adapt this code into a function that will work 
# for multiple polygons

furthest <- function(poly) {
    # tmpfun find the furthest point from the centroid of one unique polygon
    tmpfun <- function(x) {
        center <- st_centroid(x)
        vertices <-  st_coordinates(x)[,1:2]
        vertices <-  st_as_sf(as.data.frame(vertices), coords = c("X", "Y"))
        furthest <- max(st_distance(center, vertices))
        return(furthest)
    }

    # We apply tmpfun on each polygon
    return(lapply(st_geometry(poly), tmpfun))
}


poly1 <- cbind(c(5,4,2,5),c(2,3,2,2))
poly2 <- cbind(c(15,10,8,15),c(5,4,12,5))

sfPol <- st_sf(st_sfc(list(st_polygon(list(poly1)), 
                           st_polygon(list(poly2)))))

furthest(sfPol)

## [[1]]
## [1] 1.699673
## 
## [[2]]
## [1] 5.830952

Upvotes: 1

lbusett
lbusett

Reputation: 5932

Casting the polygon to POINT (thus getting the vertexes) and then computing distances wrt the centroid should work. Something like:

library(sf)

# build a test poly
geometry <- st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(1,3),  c(0,0))))) 
pol <- st_sf(r = 5, geometry)

# compute distances 
distances <- pol %>% 
  st_cast("POINT") %>% 
  st_distance(st_centroid(pol))

distances
#>          [,1]
#> [1,] 1.201850
#> [2,] 1.054093
#> [3,] 2.027588
#> [4,] 1.201850

# maximum dist:
max_dist <- max(distances)
max_dist
#> [1] 2.027588

# plot to see if is this correct: seems so.
plot(st_geometry(pol))
plot(st_centroid(pol), add = T)
plot(st_cast(pol, "POINT")[which.max(distances),],
     cex =3, add = T, col = "red")

You get the same distance twice, since the first and last vertex are the same, but since you are interested in the maximum it should not matter.

HTH

Upvotes: 6

Related Questions