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

如何在R中计算多边形向外偏移1单位的外包轮廓坐标

问题描述

注:我正在使用R进行开发,但本问题更多偏向逻辑思路,而非R专属问题。
我正在开发一款Shiny应用,用户可在20×20网格上绘制黑色形状,服务端中该形状以表格形式存储:表格每一行对应形状的一条边,记录边的起止点坐标,即(x, y)和(xend, yend)。
请问如何基于这张表计算得到完全包裹原形状、且和原形状保留1点间隙的外框形状的坐标表?(示例中黑色为原始形状,红色为目标外框形状)
你可以使用如下代码在本地复现上述边坐标表:

structure(list(sideNo = 1:8, 
               x = c(4L, 4L, 8L, 8L, 4L, 8L, 15L, 18L), 
               y = c(3L, 7L, 16L, 19L, 3L, 16L, 7L, 3L), 
               xend = c(18L, 15L, 15L, 18L, 4L, 8L, 15L, 18L), 
               yend = c(3L, 7L, 16L, 19L, 7L, 19L, 16L, 19L)), 
          row.names = c(NA, -8L), 
          class = c("tbl_df", "tbl", "data.frame"))
解决方案

你要实现的是轴对齐多边形的向外1单位偏移,属于几何处理里的缓冲区生成场景,因为你给出的示例所有边都是水平/垂直的轴对齐边,不需要处理复杂的斜线偏移,有三种成熟的实现路径:

方法1:通用几何库实现(最省事,R原生可用)

直接用空间几何库的内置缓冲区函数处理,不用自己写逻辑:

  1. 把边表转换成闭合多边形对象:先提取所有边的顶点,按顺序去重后组成闭合多边形
  2. 调用缓冲区函数向外偏移1单位,注意设置参数避免生成圆角
  3. 从偏移后的多边形提取边坐标,整理成和原格式一致的边表
    R语言实现示例:
library(sf)
library(dplyr)

# 读取原始边表
edge_df <- structure(list(sideNo = 1:8, 
                          x = c(4L, 4L, 8L, 8L, 4L, 8L, 15L, 18L), 
                          y = c(3L, 7L, 16L, 19L, 3L, 16L, 7L, 3L), 
                          xend = c(18L, 15L, 15L, 18L, 4L, 8L, 15L, 18L), 
                          yend = c(3L, 7L, 16L, 19L, 7L, 19L, 16L, 19L)), 
                     row.names = c(NA, -8L), 
                     class = c("tbl_df", "tbl", "data.frame"))

# 提取顶点并生成sf多边形对象
points <- rbind(
  edge_df %>% select(x, y) %>% rename(x = x, y = y),
  edge_df %>% select(xend, yend) %>% rename(x = xend, y = yend)
) %>% distinct()
poly <- st_polygon(list(as.matrix(rbind(points, points[1,])))) %>% st_sfc(crs = NA)

# 向外偏移1单位,设置斜接样式避免圆角
offset_poly <- st_buffer(poly, dist = 1, joinStyle = "MITRE", mitreLimit = 2)

# 提取偏移后的边表
offset_coords <- st_coordinates(offset_poly)[,1:2]
n <- nrow(offset_coords)
offset_edge_df <- tibble(
  sideNo = 1:(n-1),
  x = offset_coords[-n, 1],
  y = offset_coords[-n, 2],
  xend = offset_coords[-1, 1],
  yend = offset_coords[-1, 2]
)

方法2:手动实现逻辑(不需要依赖第三方库)

如果不想引入空间计算库,按下面的步骤手动处理即可:

  1. 区分边的类型和方向:遍历所有边,先判断是水平边(y==yend)还是垂直边(x==xend)
  2. 边的向外平移:
    • 水平边:如果这条边是多边形的下界(边上方是形状内部),则整条边的y坐标减1;如果是上界(边下方是形状内部),则y坐标加1,同时边的x起止各向两端延伸1单位
    • 垂直边:如果这条边是多边形的左界(边右方是形状内部),则整条边的x坐标减1;如果是右界(边左方是形状内部),则x坐标加1,同时边的y起止各向两端延伸1单位
  3. 求交拼接:相邻的平移后的边的交点就是新形状的顶点,按顺序连接所有交点,去重后就得到新的边表

方法3:网格形态学处理(适合小网格场景)

因为你的场景是20x20的小网格,用栅格处理逻辑更简单:

  1. 生成一个20x20的全0矩阵,把原始形状覆盖的所有网格点标记为1
  2. 对矩阵做一次3x3全1核的形态学膨胀操作,所有和原始形状相邻的点都会被标记为1
  3. 提取膨胀后区域的外轮廓,就是你要的外框形状

内容的提问来源于stack exchange,提问作者Abdallah Atef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:18:02