我目前正在研究一个项目,我有一个点特征 - 点特征包括142个点 - 和多个多边形(大约10个)。我想计算R中每个单点和最近的面要素之间的距离。
我目前的做法很繁琐,有点长。我目前正计划计算每个单点和每个多边形之间的距离。例如,我将计算142点和多边形A之间的距离,142点和多边形B之间的距离,142点和多边形C之间的距离等。以下是这些距离计算之一的示例代码:< / p>
dist_cen_polya <- dist2Line(centroids_coor, polygonA_shp)
在进行这些计算之后,我会编写一个代码来选择每个单点和最近的多边形之间的最小/最近距离。问题是这个程序很乏味。
有没有人知道最小化计算工作量/计算时间的包/代码?我真的想使用一个比较单个的包来指向最近的面要素或计算一个点和所有感兴趣的多边形之间的距离吗?
谢谢。
答案 0 :(得分:14)
这里我使用的是rgeos拓扑库中的gDistance函数。我正在使用蛮力双循环,但速度惊人的快。 142点和10个多边形需要不到2秒。我确信有一种更优雅的方式来执行循环。
require(rgeos)
# CREATE SOME DATA USING meuse DATASET
data(meuse)
coordinates(meuse) <- ~x+y
pts <- meuse[sample(1:dim(meuse)[1],142),]
data(meuse.grid)
coordinates(meuse.grid) = c("x", "y")
gridded(meuse.grid) <- TRUE
meuse.grid[["idist"]] = 1 - meuse.grid[["dist"]]
polys <- as(meuse.grid, "SpatialPolygonsDataFrame")
polys <- polys[sample(1:dim(polys)[1],10),]
plot(polys)
plot(pts,pch=19,cex=1.25,add=TRUE)
# LOOP USING gDistance, DISTANCES STORED IN LIST OBJECT
Fdist <- list()
for(i in 1:dim(pts)[1]) {
pDist <- vector()
for(j in 1:dim(polys)[1]) {
pDist <- append(pDist, gDistance(pts[i,],polys[j,]))
}
Fdist[[i]] <- pDist
}
# RETURN POLYGON (NUMBER) WITH THE SMALLEST DISTANCE FOR EACH POINT
( min.dist <- unlist(lapply(Fdist, FUN=function(x) which(x == min(x))[1])) )
# RETURN DISTANCE TO NEAREST POLYGON
( PolyDist <- unlist(lapply(Fdist, FUN=function(x) min(x)[1])) )
# CREATE POLYGON-ID AND MINIMUM DISTANCE COLUMNS IN POINT FEATURE CLASS
pts@data <- data.frame(pts@data, PolyID=min.dist, PDist=PolyDist)
# PLOT RESULTS
require(classInt)
( cuts <- classIntervals(pts@data$PDist, 10, style="quantile") )
plotclr <- colorRampPalette(c("cyan", "yellow", "red"))( 20 )
colcode <- findColours(cuts, plotclr)
plot(polys,col="black")
plot(pts, col=colcode, pch=19, add=TRUE)
min.dist向量表示多边形的行号。例如,您可以使用此向量对最近的多边形进行子集化。
near.polys <- polys[unique(min.dist),]
PolyDist向量包含要素投影单元中的实际笛卡尔最小距离。
答案 1 :(得分:1)
在多边形中,你有很多行。如果点位于多边形内或位于边缘上,则多边形之间的距离为零。
所以实际上你正在寻找两种情况:
所以这是一个简单的算法,如果我们考虑每个多边形有10个边,则所有点都需要O(10 * 10)* 142。这使得100 * 142 = 14200次操作。 =&GT; O(m * deltaE)* n(m是多边形的数量,deltaE是每个多边形的平均边数,n是点数)。
现在我们检查一下是否可以加快速度。首先想到的是我们可以为每个多边形使用边界框检查或边界圆。
另一个想法是为一组角度准备每个多边形的最近边。例如,如果您有8个角度(每45°),您可以移除列表中被另一个边缘取代的所有边缘(因此,移除边缘的任何点总是会产生比其他边缘的任何点更大的距离)多边形。
这种方式通常可以大幅降低复杂性。如果你想到一个矩形,你只有一个或两个边而不是4.如果你想到一个普通的8边多边形,你可能最终会得到一个或两个,每个多边最多3个边。
如果您将法线向量添加到每条边,您可以计算该点是否在内部,并且您必须执行扫描线或任何检查(或者您知道它的konvex)以确定。
也有可能的映射索引,例如在等距的mannor中用x和y分隔二维空间。这样你只需要测试位于9个扇区的多边形。
下一个版本可能正在使用R树,每个节点的每个边界框(圆圈)都必须检查最小预期距离和最大预期距离。因此,不需要检查节点的多边形,导致最小距离远远大于另一个节点的最大距离。
另一件事是,如果你有一个像地图数据一样的给定树。在街道地图中,你总是拥有世界 - &gt;地区 - &gt;国家 - &gt;县 - &gt;城市 - &gt;城市部门 - &gt; ...
此时,您可以在合理的时间内搜索包含数百万个多边形的整个世界地图中最近的位置,大部分时间<10毫秒。
可以说你在这里有很多选择。并预处理多边形列表并通过使用多边形的二进制空间分区树或使用角度方法或甚至更精细的东西来提取相关边。由你决定。我希望你最终会在对数范围内做一些事情,如O(log(n)* log(deltaE))变为O(log(n))作为平均复杂度。