如何实现两个sfc_LINESTRING网格对象的最近邻连接以构建sfnetworks网络
连接两个独立sf网格并构建统一网络的解决方案
问题背景
我有两个相邻区域,各自拥有一个sfc_LINESTRING类型的连通网格——一个区域较大、网格较粗,另一个区域较小、网格较细。想要实现连接操作,让大网格中的至少一个点与小网格中的至少一个点相连,最终目标是用sfnetworks构建包含两个采样区域所有节点的网络。尝试用st_join和merge未能成功,相关代码如下:
library(sf) library(nngeo) nc = st_read(system.file("shape/nc.shp", package="sf")) nc_utm = st_transform(nc, crs="+proj=utm +zone=18 +datum=NAD83 +unit=m") # 使用UTM坐标系 # 裁剪出两个小区域用于采样网格 area_1 <- st_crop(nc_utm, xmin = 0, xmax = 20000, ymin = 3950000, ymax = 4000000) area_2 <- st_crop(nc_utm, xmin = 20100, xmax = 25000, ymin = 3960000, ymax = 3980000) # 采样网格并内部连接 grid_1 <- sf::st_sample( area_1, size = 25, type = 'regular') %>% sf::st_as_sf() %>% nngeo::st_connect(.,.,k = 9) grid_2 <- sf::st_sample( area_2, size = 25, type = 'regular') %>% sf::st_as_sf() %>% nngeo::st_connect(.,.,k = 9) # 可视化 ggplot() + geom_sf(data = nc_utm) + geom_sf(data = area_1, fill = 'blue', alpha = 0.3) + geom_sf(data = area_2, fill = "red", alpha = 0.3) + geom_sf(data = grid_1, colour = "blue") + geom_sf(data = grid_2, colour = "red") + coord_sf(datum = "+proj=utm +zone=18 +datum=NAD83 +unit=m", xlim = c(-10000, 30000), ylim = c(3940000, 4001000))
解决方案
st_join和merge仅适用于属性表关联,无法生成空间连接线。正确思路是:提取两个网格的原始节点,找到节点间的最近对,生成连接线,再合并所有线要素构建统一网络。
1. 保存网格的原始节点
修改采样代码,单独保存节点要素(后续用于找连接点):
library(dplyr) # 采样area_1并保存节点 nodes_1 <- sf::st_sample(area_1, size = 25, type = 'regular') %>% sf::st_as_sf() %>% mutate(node_id = paste0("g1_", row_number())) # 给节点加唯一ID grid_1 <- nngeo::st_connect(nodes_1, nodes_1, k = 9) # 采样area_2并保存节点 nodes_2 <- sf::st_sample(area_2, size = 25, type = 'regular') %>% sf::st_as_sf() %>% mutate(node_id = paste0("g2_", row_number())) grid_2 <- nngeo::st_connect(nodes_2, nodes_2, k = 9)
2. 找到两个网格的最近节点对
通过空间计算找出距离最近的节点对,作为连接点:
# 计算nodes_1中每个节点对应的nodes_2最近节点索引 nearest_idx <- st_nearest_feature(nodes_1, nodes_2) # 计算每对节点的距离 nodes_1$nearest_dist <- st_distance(nodes_1, nodes_2[nearest_idx, ], by_element = TRUE) # 筛选出距离最小的节点对 min_dist_row <- which.min(nodes_1$nearest_dist) connect_node_1 <- nodes_1[min_dist_row, ] connect_node_2 <- nodes_2[nearest_idx[min_dist_row], ]
3. 生成两个网格的连接线
基于选中的节点对生成空间连接线:
# 生成连接线要素 connect_line <- st_union(connect_node_1, connect_node_2) %>% st_cast("LINESTRING") %>% st_as_sf() %>% mutate(from = connect_node_1$node_id, to = connect_node_2$node_id) # 记录连接关系
4. 合并网格并构建sfnetwork
将原始网格线和连接线合并,转换为sfnetwork对象:
library(sfnetworks) # 合并所有线要素 all_lines <- bind_rows(grid_1, grid_2, connect_line) # 构建无向sfnetwork combined_network <- as_sfnetwork(all_lines, directed = FALSE)
5. 可视化验证
添加连接线的可视化代码,确认连接效果:
ggplot() + geom_sf(data = nc_utm) + geom_sf(data = area_1, fill = 'blue', alpha = 0.3) + geom_sf(data = area_2, fill = "red", alpha = 0.3) + geom_sf(data = grid_1, colour = "blue") + geom_sf(data = grid_2, colour = "red") + geom_sf(data = connect_line, colour = "green", size = 1.2) # 高亮连接线
内容的提问来源于stack exchange,提问作者colebrookson
相关产品推荐
相关产品推荐

