使用 sf 或 terra 的 LINESTRING 的累积长度

问题描述 投票:0回答:1

有没有更有效的方法来测量

<LINESTRING>
<MULTILINESTRING>
的累积长度?换句话说,我需要测量从起点到终点的点之间的距离。目前,我只想出将
<LINESTRING>
分成单独的部分并测量每个部分的长度的想法。它确实有效,但由于采用迭代方法,因此需要花费大量时间。有没有内置的方法?

下面是我想出的一个表示。它以

spData
的塞纳河为例。尽管下面的示例使用
sf
geos
包,但我很高兴听到任何其他空间包,例如
terra
geos
,甚至
rsgeo

干杯!

library(sf)
#> Linking to GEOS 3.10.2, GDAL 3.4.1, PROJ 8.2.1; sf_use_s2() is TRUE
library(geos)
library(spData)
#> To access larger datasets in this package, install the spDataLarge
#> package with: `install.packages('spDataLarge',
#> repos='https://nowosad.github.io/drat/', type='source')`

# Example
lines <- seine[2, ]

# My foo
cumulative_length <- 
  function(input) {
    
    # Save CRS
    crs <- sf::st_crs(input)
    
    # Retrive coordinates
    lines_coo <- 
      sf::st_coordinates(input)
    
    # Count number of segments of linestring
    n <- nrow(lines_coo) - 1
    
    # Pre-allocate a list 
    lines_geos <- 
      vector(mode = "list", length = n)
    
    # Construct linestrings
    for (i in 1:n) {
      lines_geos[[i]] <- 
        geos::geos_make_linestring(lines_coo[i:(i+1),1], 
                                   lines_coo[i:(i+1),2], 
                                   crs = crs)
    }
    
    # Measure cumulative segment length
    lines_order <- 
      sapply(lines_geos, geos::geos_length) |> 
      append(0, 0) |> 
      cumsum()
    
    return(lines_order)
    
  }

bench::mark(cumulative_length(lines))
#> # A tibble: 1 × 6
#>   expression                    min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>               <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 cumulative_length(lines)     13ms   13.7ms      72.9     244KB     109.

创建于 2024-03-23,使用 reprex v2.0.2

r geospatial r-sf terra geos
1个回答
0
投票

根据 L Tyrone 的评论,我运行了一个基准测试。

sf
快了 10 毫秒,我不知道是否明显快了四种情况:

library(sf)
library(geos)
library(spData)

# Example
input <- seine[2, ]

# My foo
cumulative_length <- 
  function(input) {
    
    # Save CRS
    crs <- sf::st_crs(input)
    
    # Retrive coordinates
    lines_coo <- 
      sf::st_coordinates(input)
    
    # Count number of segments of linestring
    n <- nrow(lines_coo) - 1
    
    # Pre-allocate a list 
    lines_geos <- 
      vector(mode = "list", length = n)
    
    # Construct linestrings
    for (i in 1:n) {
      lines_geos[[i]] <- 
        geos::geos_make_linestring(lines_coo[i:(i+1),1], 
                                   lines_coo[i:(i+1),2], 
                                   crs = crs)
    }
    
    # Measure cumulative segment length
    lines_order <- 
      sapply(lines_geos, geos::geos_length) |> 
      append(0, 0) |> 
      cumsum()
    
    return(lines_order[n+1])
    
  }

microbenchmark::microbenchmark(
  cumulative_length(input),
  sf::st_length(input),
  times = 100
)
#> Unit: milliseconds
#>                      expr     min      lq     mean   median      uq     max
#>  cumulative_length(input) 34.8516 36.1055 44.63292 41.18370 48.8481 95.0899
#>      sf::st_length(input) 28.4086 29.9401 34.94634 32.77725 37.5570 77.9914
#>  neval
#>    100
#>    100

创建于 2024-03-23,使用 reprex v2.1.0

© www.soinside.com 2019 - 2024. All rights reserved.