【问题标题】:Difference between sf::st_buffer and terra::buffer on R: diameter and radiusR 上 sf::st_buffer 和 terra::buffer 之间的区别:直径和半径
【发布时间】:2022-01-05 19:49:30
【问题描述】:

我对 R 上 sf 包中的 st_bufferterra 包中的 buffer 的用法感到困惑。

我正在围绕点创建缓冲区,当使用sf::st_buffer 我知道我需要在参数dist 中使用缓冲区的半径 但是在使用terra::buffer 时我需要指定参数width中缓冲区的直径

这是正确的吗?

我在这里检查了sf::st_buffer,参数disthttps://rdrr.io/r/stats/dist.html

这里是terra::buffer,参数widthhttps://rdrr.io/cran/terra/man/width.html

【问题讨论】:

    标签: r buffer sf terra


    【解决方案1】:

    缓冲区是与对象的距离。在一般意义上,它既不是半径也不是直径。

    当你围绕一个点创建缓冲区时,缓冲区是一个圆,缓冲区距离(宽度)等于那个圆的半径。

    这不适用于线、多边形或栅格单元周围的缓冲区。

    一些带有terra的说明性代码

    library(terra)
    v <- vect(cbind(0,0), crs="+proj=utm +zone=1")
    b <- buffer(v, 1)
    ext(b)
    #SpatExtent : -1, 1, -1, 1 (xmin, xmax, ymin, ymax)
    
    v <- vect(cbind(0,0), crs="+proj=longlat")
    # 1 degree at equator is ~ 111 km
    b <- buffer(v, 111000)
    round(ext(b), 2)
    #SpatExtent : -1, 1, -1, 1 (xmin, xmax, ymin, ymax)
    

    下面显示了不同纬度的经度/纬度点的缓冲区。这些缓冲区个圆,所有的半径都相同,尽管地球变平造成的扭曲很难看到。

    v <- vect(cbind(0, seq(0, 80, 15)), crs="+proj=longlat")
    b <- buffer(v, 1100000)
    plot(b, asp=1, border=rainbow(8), lwd=2)
    points(v)
    

    【讨论】:

      【解决方案2】:

      我相信在理论上,正确的答案是@robert-hijmans 的答案(点周围的圆形缓冲区只是通用缓冲区对象的一个​​特例)。

      我想指出另一个实际的区别:对于未投影的坐标{sf} 使用 Google 的 S2 库。 S2 库的快捷方式和假设与 GEOS 有所不同,并产生了不同的缓冲区。

      考虑这个例子,并注意红色缓冲区有多么不同(有点像像素化)。

      library(nominatimlite)
      library(sf)
      library(terra)
      
      a_point <- geo_lite_sf("Royal Observatory, Greenwich")
      
      st_crs(a_point) # WGS84
      # Coordinate Reference System:
      #   User input: WGS 84 
      #   wkt:
      # GEOGCRS["WGS 84",
      #     DATUM["World Geodetic System 1984",
      #         ELLIPSOID["WGS 84",6378137,298.257223563,
      #             LENGTHUNIT["metre",1]]],
      #     PRIMEM["Greenwich",0,
      #         ANGLEUNIT["degree",0.0174532925199433]],
      #     CS[ellipsoidal,2],
      #         AXIS["geodetic latitude (Lat)",north,
      #             ORDER[1],
      #             ANGLEUNIT["degree",0.0174532925199433]],
      #         AXIS["geodetic longitude (Lon)",east,
      #             ORDER[2],
      #             ANGLEUNIT["degree",0.0174532925199433]],
      #     ID["EPSG",4326]]
      
      st_is_longlat(a_point) # this is important! S2 will be used.
      # [1] TRUE
      
      
      sf_buffer <- a_point |>
        st_buffer(dist = 500) |>
        st_geometry()
      
      terra_buffer <- a_point |>
        vect() |>
        buffer(width = 500)
      
      plot(sf_buffer, border = "red")
      plot(terra_buffer, border = "blue", add = T)
      

      【讨论】:

        【解决方案3】:

        我不是terra 的专家(或多或少从未使用过它),但我认为这两个函数都需要缓冲区的半径:

        # packages
        library(sf)
        #> Linking to GEOS 3.9.1, GDAL 3.2.1, PROJ 7.2.1
        library(terra)
        #> terra version 1.4.11
        
        # data
        point_sf <- st_as_sfc("POINT (0 0)", crs="+proj=merc")
        point_terra <- vect("POINT (0 0)", crs="+proj=merc")
        
        # buffer
        buffer_sf <- st_buffer(point_sf, dist = 5)
        buffer_terra <- buffer(point_terra, width = 5)
        
        # plot
        plot(buffer_sf, axes = TRUE, lwd = 10)
        plot(buffer_terra, border = "red", add = TRUE, lwd = 3.5)
        

        reprex package (v2.0.1) 于 2021 年 11 月 28 日创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-25
          • 2018-06-17
          • 2015-12-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多