代码之家  ›  专栏  ›  技术社区  ›  user3357059

多边形内的r-sf包质心

  •  4
  • user3357059  · 技术社区  · 6 年前

    Calculate Centroid WITHIN / INSIDE a SpatialPolygon 但我用的是sf软件包。

    rm(list = ls(all = TRUE)) #start with empty workspace
    
    library(sf)
    library(tidyverse)
    library(ggrepel)
    
    pol <- st_polygon(list(rbind(c(144, 655),c(115, 666)
                             ,c(97, 660),c(86, 640)
                             ,c(83, 610),c(97, 583)
                             ,c(154, 578),c(140, 560)
                             ,c(72, 566),c(59, 600)
                             ,c(65, 634),c(86, 678)
                             ,c(145, 678),c(144, 655)))) %>%
      st_sfc()
    
    a = data.frame(NAME = "A")
    st_geometry(a) = pol
    
    a <- a  %>% 
      mutate(lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
         lat = map_dbl(geometry, ~st_centroid(.x)[[2]]))
    
    ggplot() +
      geom_sf(data = a, fill = "orange") +
      geom_label_repel(data = a, aes(x = lon, y = lat, label = NAME)) 
    

    结果如下

    enter image description here

    2 回复  |  直到 6 年前
        1
  •  8
  •   Mitch    6 年前

    简单的答案是替换 st_centroid 具有 st_point_on_surface . 如果质心位于多边形内部,则不会返回真正的质心。

    a2 <- a  %>% 
      mutate(lon = map_dbl(geometry, ~st_point_on_surface(.x)[[1]]),
             lat = map_dbl(geometry, ~st_point_on_surface(.x)[[2]]))
    
    ggplot() +
      ggplot2::geom_sf(data = a2, fill = "orange") +
      geom_label_repel(data = a2, aes(x = lon, y = lat, label = NAME))
    

    或者

    如果多边形有一个位于多边形内部的质心,请使用该质心,否则,请在多边形内查找一个点。

    st_centroid_within_poly <- function (poly) {
    
      # check if centroid is in polygon
      centroid <- poly %>% st_centroid() 
      in_poly <- st_within(centroid, poly, sparse = F)[[1]] 
    
      # if it is, return that centroid
      if (in_poly) return(centroid) 
    
      # if not, calculate a point on the surface and return that
      centroid_in_poly <- st_point_on_surface(poly) 
      return(centroid_in_poly)
    }
    
    a3 <- a  %>% 
      mutate(lon = map_dbl(geometry, ~st_centroid_within_poly(.x)[[1]]),
             lat = map_dbl(geometry, ~st_centroid_within_poly(.x)[[2]]))
    
    ggplot() +
      ggplot2::geom_sf(data = a3, fill = "orange") +
      geom_label_repel(data = a3, aes(x = lon, y = lat, label = NAME)) 
    

    上面的函数 st_centroid_within_polygon 改编自 question you reference 对于 sf 表面上的点 found here

        2
  •  2
  •   M.M. Middeldorp    5 年前

    扩大米奇的答案,因为 st_centroid_within_poly

    st_centroid_within_poly <- function (poly) {
    
      # check if centroid is in polygon
      ctrd <- st_centroid(poly, of_largest_polygon = TRUE)
      in_poly <- diag(st_within(ctrd, poly, sparse = F))
    
      # replace geometries that are not within polygon with st_point_on_surface()
      st_geometry(ctrd[!in_poly,]) <- st_geometry(st_point_on_surface(poly[!in_poly,]))
    
      ctrd
    }