如何在两组点集间创建LineString/MultiLineString几何线条
问题需求
我拥有两组点(实际有数百对点集,此处为示例),想要创建一条LineString或MultiLineString,效果位于两组点集的中间位置。
数据加载代码
onecons <- st_read("https://raw.githubusercontent.com/deanm0000/SOexamples/e5591130b1d0e9c5c5fa8b6b5fc05b3958d13099/example.geojson") mapdeck(style=mapdeck_style("light")) %>% add_scatterplot(onecons, radius_min_pixels=5, tooltip='nodename', fill_colour = "pos", layer_id = 'nodes')
尝试过的方法
polys <- onecons %>% group_by(pos) %>% summarise() %>% st_convex_hull() mapdeck(style=mapdeck_style("light")) %>% add_polygon(st_as_sf(st_difference(st_geometry(polys[1,]), st_geometry(polys[2,]))), fill_opacity=.5) %>% add_scatterplot(onecons, radius_min_pixels=5, tooltip='nodeest', fill_colour = "pos", layer_id = 'nodes')
遇到的问题
- 交换
st_difference的参数后结果不符合预期 - 希望生成的线条位于点集中间而非点上
- 无法提取多边形的中间边界作为目标线条(使用
st_boundary只能获取完整边界)
解决方案
方法一:Voronoi图提取分组边界(适配不规则点分布)
这种方法能精准生成分隔两组点的中间边界线,适合点分布不规则的场景:
library(sf) library(mapdeck) library(dplyr) # 加载数据 onecons <- st_read("https://raw.githubusercontent.com/deanm0000/SOexamples/e5591130b1d0e9c5c5fa8b6b5fc05b3958d13099/example.geojson") # 生成所有点的Voronoi图并转为多边形 voronoi_polys <- st_voronoi(st_union(onecons)) %>% st_cast("POLYGON") %>% st_sf() # 给每个Voronoi多边形匹配对应的pos分组 voronoi_polys <- voronoi_polys %>% st_join(onecons, join = st_contains) %>% group_by(geometry) %>% summarise(pos = first(pos)) # 筛选出分隔不同pos分组的公共边界 adjacent_pairs <- st_intersects(voronoi_polys, voronoi_polys) boundary_list <- list() for (i in 1:nrow(voronoi_polys)) { # 只处理i之后的邻居,避免重复计算 neighbors <- adjacent_pairs[[i]][adjacent_pairs[[i]] > i] for (j in neighbors) { if (voronoi_polys$pos[i] != voronoi_polys$pos[j]) { common_edge <- st_intersection(st_boundary(voronoi_polys$geometry[i]), st_boundary(voronoi_polys$geometry[j])) if (!st_is_empty(common_edge)) boundary_list <- c(boundary_list, list(common_edge)) } } } # 合并为MultiLineString final_boundary <- st_sf(geometry = st_combine(do.call(c, boundary_list))) %>% st_cast("MULTILINESTRING") # 可视化 mapdeck(style=mapdeck_style("light")) %>% add_scatterplot(onecons, radius_min_pixels=5, tooltip='nodename', fill_colour = "pos", layer_id = 'nodes') %>% add_path(final_boundary, stroke_width = 3, stroke_colour = "#000000", layer_id = 'group_boundary')
方法二:凸包中线法(适配规整点分布)
如果两组点分布集中、凸包形状规整,用这种方法计算更快:
library(sf) library(mapdeck) library(dplyr) onecons <- st_read("https://raw.githubusercontent.com/deanm0000/SOexamples/e5591130b1d0e9c5c5fa8b6b5fc05b3958d13099/example.geojson") # 分组生成凸包 group_hulls <- onecons %>% group_by(pos) %>% summarise() %>% st_convex_hull() # 计算两个凸包的中间距离,生成缓冲区 hull_dist <- st_distance(group_hulls$geometry[1], group_hulls$geometry[2]) / 2 hull_buf1 <- st_buffer(group_hulls$geometry[1], hull_dist) hull_buf2 <- st_buffer(group_hulls$geometry[2], hull_dist) # 提取两个缓冲区交集的边界作为中间线 middle_line <- st_intersection(hull_buf1, hull_buf2) %>% st_boundary() %>% st_sf() # 可视化 mapdeck(style=mapdeck_style("light")) %>% add_scatterplot(onecons, radius_min_pixels=5, tooltip='nodename', fill_colour = "pos", layer_id = 'nodes') %>% add_path(middle_line, stroke_width = 3, stroke_colour = "#000000", layer_id = 'middle_line')
方法对比
- Voronoi图法:精准贴合点集分布,能处理不规则点群,但计算量稍大
- 凸包中线法:计算高效,适合点群集中规整的场景,但边界精度略低
内容的提问来源于stack exchange,提问作者Dean MacGregor
相关产品推荐
相关产品推荐

