有没有更有效的方法来测量
<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
根据 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