假设我有一个名为m_line
的MULTILINESTRING
,由几个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