r-根据相邻性排列sf对象特征

  • 本文关键字:排列 sf 对象 特征 r r-sf
  • 更新时间 :
  • 英文 :


假设我有一个名为m_lineMULTILINESTRING,由几个MULTILINESTRINGs组成。

l1 = st_multilinestring(list(rbind(c(0,1),c(1,10))))
l2 = st_multilinestring(list(rbind(c(1,10),c(40,25))))
l3 = st_multilinestring(list(rbind(c(40,25),c(50,40))))
l4 = st_multilinestring(list(rbind(c(50,40),c(21,63))))

l1 = st_sf(geometry=st_sfc(l1, crs=3857))
l2 = st_sf(geometry=st_sfc(l2, crs=3857))
l3 = st_sf(geometry=st_sfc(l3, crs=3857))
l4 = st_sf(geometry=st_sfc(l4, crs=3857))
m_line = rbind(l4,l2,l1,l3)

有没有办法排列特征,使第一个特征是线的任一端,然后第二个特征是与第一个特征相邻的线,依此类推?就像让它重新排列成l1、l2、l3、l4或l4、l3,l2、l1一样。

提前感谢您,祝您度过美好的一天!

我相信,在几个假设下;细线";形成单个";"长线";,在没有间断和分叉的情况下,你可以根据邻接矩阵计算出一个对细线串排序的向量。其可以通过sf::st_touches()调用来计算。

# adjacency matrix of line with itself
adjacency <- st_touches(m_line, m_line)
# first element that has only a 1 neighbor - a good place to start
wrk_item <- min(which(sapply(adjacency, length) == 1)) 
# init  of resultset
order <- rep(NA, length(adjacency))

# iterate over adjacency matrix, constructing the final version of order vector
for (i in seq_along(adjacency)) {

# update resultset
order[i] <- wrk_item

# next item yet unprocessed (= not yet in resultset)
wrk_item <- setdiff(adjacency[[i]], order)

}
order
# [1] 1 4 3 2

当我尝试处理比示例更多的功能时,遇到了一个错误。

基于金德拉的解决方案,我对其进行了一些调整。我还开始寻找只在一端连接的功能。然后,我循环浏览所有特征,以找到与所识别的上一个特征相邻的下一个特征。

这是我的解决方案。

library(sf)
l1 = st_multilinestring(list(rbind(c(0,1),c(1,10))))
l2 = st_multilinestring(list(rbind(c(1,10),c(40,25))))
l3 = st_multilinestring(list(rbind(c(40,25),c(50,40))))
l4 = st_multilinestring(list(rbind(c(50,40),c(21,63))))
l5 = st_multilinestring(list(rbind(c(21,63),c(33,75))))
l6 = st_multilinestring(list(rbind(c(33,75),c(75,85))))
l7 = st_multilinestring(list(rbind(c(75,85),c(75,90))))
l8 = st_multilinestring(list(rbind(c(75,90),c(82,100))))

l1 = st_sf(geometry=st_sfc(l1, crs=3857))
l2 = st_sf(geometry=st_sfc(l2, crs=3857))
l3 = st_sf(geometry=st_sfc(l3, crs=3857))
l4 = st_sf(geometry=st_sfc(l4, crs=3857))
l5 = st_sf(geometry=st_sfc(l5, crs=3857))
l6 = st_sf(geometry=st_sfc(l6, crs=3857))
l7 = st_sf(geometry=st_sfc(l7, crs=3857))
l8 = st_sf(geometry=st_sfc(l8, crs=3857))
m_line = rbind(l4,l2,l5,l7,l1,l3,l8,l6)
adjacency <- st_touches(m_line)
# Sparse geometry binary predicate list of length 8, where the predicate was `touches'
#  1: 3, 6
#  2: 5, 6
#  3: 1, 8
#  4: 7, 8
#  5: 2
#  6: 1, 2
#  7: 4
#  8: 3, 4
# get the feature connected to only one end
wrk_item <- min(which(sapply(adjacency, length) == 1)) 
# init  of resultset
order <- rep(NA, length(adjacency)) 
for (i in seq_along(adjacency)) {
order[i] = wrk_item

#locate the feature that is connected to the current `wrk_item` identified
adjacency = st_touches(m_line,m_line[wrk_item,])

#if the adjacency returns more than one value then select the one that is not in the resultset
wrk_item = setdiff(which(sapply(adjacency, is.na) == FALSE),order)

}
order
# [1] 5 2 6 1 3 8 4 7
#rearrange the features based on adjacency
m_line2 = m_line[order,]
st_coordinates(m_line2)
#       X   Y L1 L2
# [1,]  0   1  1  1
# [2,]  1  10  1  1
# [3,]  1  10  1  2
# [4,] 40  25  1  2
# [5,] 40  25  1  3
# [6,] 50  40  1  3
# [7,] 50  40  1  4
# [8,] 21  63  1  4
# [9,] 21  63  1  5
# [10,] 33  75  1  5
# [11,] 33  75  1  6
# [12,] 75  85  1  6
# [13,] 75  85  1  7
# [14,] 75  90  1  7
# [15,] 75  90  1  8
# [16,] 82 100  1  8
st_coordinates(m_line)
#       X   Y L1 L2
# [1,] 50  40  1  1
# [2,] 21  63  1  1
# [3,]  1  10  1  2
# [4,] 40  25  1  2
# [5,] 21  63  1  3
# [6,] 33  75  1  3
# [7,] 75  85  1  4
# [8,] 75  90  1  4
# [9,]  0   1  1  5
# [10,]  1  10  1  5
# [11,] 40  25  1  6
# [12,] 50  40  1  6
# [13,] 75  90  1  7
# [14,] 82 100  1  7
# [15,] 33  75  1  8
# [16,] 75  85  1  8

最新更新