【发布时间】:2020-10-23 10:11:17
【问题描述】:
我想计算每个多边形的长度。 - 在每个多边形周围我创建了点(st_sample), - 从点的组合我创建了所有可能的折线, - 对于多边形内的折线,我计算了长度, - 最长的折线是我的结果(多边形的最大长度)。
我编写的代码让我得到了结果,但它真的很慢。你有一些改进我的代码的解决方案吗?我知道有两个循环我不能指望速度上的奇迹,但我不知道如何以另一种方式获得结果。
如果没有别的,我至少有一些替代解决方案可以在没有循环的情况下一步一步从一个多边形的点组合创建所有折线? :)
谢谢
library(sf)
library(data.table)
poly=st_read(system.file("shape/nc.shp", package="sf"))
poly=poly[1:10,]
poly=st_cast(poly,"POLYGON")
poly$max_length=0
##Combination of 10 points, withot repetiton
aa=CJ(1:10,1:10)
aa=aa[!duplicated(t(apply(aa[,.(V1, V2)], 1, sort))),][V1!=V2]
##for each polygon create sample of coordinates along line, from them I create polyline and calculated length for linestring which are inside polygon
for (ii in 1:nrow(poly)){
ncl=st_cast(poly[ii,],"LINESTRING")
##sample of point along line
ncp=st_cast(st_sample(ncl,10, type="regular", exact=T),"POINT")
##create empty sf
aaa=st_sf(st_sfc())
st_crs(aaa)="NAD27"
##for each combination of points create linestring and calculate length only for polylines which are inside polygon
for (i in 1:nrow(aa)){
aaa=rbind(aaa,st_sf(geometry=st_cast(st_union(ncp[t(aa[i])]),"LINESTRING")))
}
poly$max_length[ii]=as.numeric(max(st_length(aaa[unlist(st_contains(poly[ii,],aaa)),])))
}
第二次尝试在 data.table 中运行函数。少一个循环,但问题可能是第二个循环。
poly=st_read(system.file("shape/nc.shp", package="sf"))
poly=poly[1:10,]
poly=st_cast(poly,"POLYGON")
poly$max_length=0
##Combination of 10 points, withot repetiton
aa=CJ(1:10,1:10)
aa=aa[!duplicated(t(apply(aa[,.(V1, V2)], 1, sort))),][V1!=V2]
overFun <- function(x){
ncl=st_cast(x[,geometry],"LINESTRING")
##sample of point along line
ncp=st_cast(st_sample(ncl,40, type="regular", exact=T),"POINT")
##create empty sf
aaa=st_sf(st_sfc())
st_crs(aaa)="NAD27"
##for each combination pof points create linestring and calculate length
for (i in 1:nrow(aa)){
aaa=rbind(aaa,st_sf(geometry=st_cast(st_union(ncp[t(aa[i])]),"LINESTRING")))
}
as.numeric(max(st_length(aaa[unlist(st_contains(x[,geometry],aaa)),])))}
setDT(poly)
##run function inside data.table
poly[,max_length:=overFun(poly), by=seq(nrow(poly))]
编辑:我为我的问题找到了一些足够快的解决方案来满足我的需求。 在 data.table 中使用并行库,其功能也适用于 data.table。仍然存在问题,为什么使用函数 st_contains 排除了某些折线(见上图)。也许精度有问题?
library(sf)
library(data.table)
poly=st_read(system.file("shape/nc.shp", package="sf"))
poly=st_cast(poly,"POLYGON")
setDT(poly)
##Combination of 10 points, withot repetiton
aa=CJ(1:10,1:10)
aa=aa[!duplicated(t(apply(aa[,.(V1, V2)], 1, sort))),][V1!=V2]
overFun <- function(x){
ncl=st_cast(poly[1,geometry],"LINESTRING")
##sample of point along line
ncp=st_cast(st_sample(ncl,10, type="regular", exact=T),"POINT")
df=data.table(ncp[aa[,V1]],ncp[aa[,V2]] )
df[,v3:=st_cast(st_union(st_as_sf(V1),st_as_sf(V2)),"LINESTRING"), by=seq(nrow(df))]
as.numeric(max(st_length(df[unlist(st_contains(poly[1,geometry], df$v3)),]$v3)))}
library(parallel)
cl <- makeCluster(detectCores() - 1)
clusterExport(cl, list("overFun","data.table","st_cast","CJ","poly","st_sample","st_sf","st_sfc","aa","st_length","st_union",
"st_as_sf","st_contains"))
system.time(poly[,c("max_length"):=.(clusterMap(cl, overFun, poly$geometry)),])
stopCluster(cl)
【问题讨论】:
-
“多边形的最大长度”是什么意思?
-
我想计算每个多边形的长度。 -在每个多边形周围我创建了点(st_sample),-从点的组合我创建了所有可能的折线,-对于多边形内部的折线,我计算了长度,-最长的折线是我的结果(多边形的最大长度)。对不起我的英语。
-
我还没有运行你的代码,但看起来你把事情复杂化了。为什么
sf::st_length不能满足您的需求?似乎应该处理必须沿边界对点进行任何类型的采样 -
嗯,我发现了这一点,如果我理解正确,则无法将 st_length 与多边形一起使用:st_length 使用坐标参考系返回 LINESTRING 或 MULTILINESTRING 几何的长度。 POINT、MULTIPOINT、POLYGON 或 MULTIPOLYGON 几何图形返回零。
-
当你第一次阅读 shapefile 时,你得到了一个多面体对象。
st_length(poly)获取长度以米为单位的向量。st_length(poly)将其转换为多边形对象后也是如此。我正在使用sfv0.9-6,但我不明白为什么其他版本也不会出现这种情况。您是否还有其他我想解决的问题?
标签: r data.table sf