You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在两组点集间创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:45:33