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

如何高效查找Vector2数组中的最外侧点以绘制点集外轮廓

你需要的是平面点集的凸包提取算法,以下是常用的高效实现方案:

核心算法推荐

你要找的最外侧点构成的封闭图形叫做凸包,下面两种是工业界最常用的高效实现,时间复杂度均为O(n log n),完全满足普通图形渲染、游戏开发场景的性能需求:

1. Graham扫描法(中小点集首选,实现简单)

执行步骤:

  • 首先从所有点中筛选出y坐标最小的点,若存在多个y相同的点则取x最小的点,该点必然属于凸包,记为基准点P0
  • 把剩余所有点按照和P0的极角从小到大排序,极角相同时距离P0更近的点排在前面
  • 初始化一个栈结构,依次将P0、排序后的前两个点压入栈中
  • 从排序后的第三个点开始遍历,每次判断栈顶两个点与当前遍历点形成的路径拐向:如果是顺时针拐(叉乘计算结果小于0),就弹出栈顶点,重复判断直到拐向为逆时针或栈内只剩2个点,再将当前点压入栈
  • 遍历完所有点后,栈中留存的点就是所有外侧凸包点

2. Andrew单调链算法(大点集首选,性能更稳定)

执行步骤:

  • 将所有点按照x坐标排序,x相同的点按y坐标排序
  • 构建下凸包:从左到右遍历排序后的点,每次判断当前点与栈末尾两个点的拐向,如果是顺时针拐就弹出栈顶点,否则将当前点加入栈
  • 构建上凸包:从右到左遍历排序后的点,遵循同样的拐向判断规则弹出不符合的点,再将当前点加入栈
  • 最终栈中会重复包含首尾两个点,去重后剩余的点即为凸包点

关键工具函数

判断拐向的核心逻辑依赖叉乘计算,以C#的Vector2为例,实现代码如下:

// 计算三点p0→p1→p2的叉乘
// 返回值>0:路径为逆时针拐;返回值<0:路径为顺时针拐;返回值=0:三点共线
float Cross(Vector2 p0, Vector2 p1, Vector2 p2)
{
    return (p1.X - p0.X) * (p2.Y - p0.Y) - (p1.Y - p0.Y) * (p2.X - p0.X);
}

注意事项

如果需要保留凸包边上的所有共线外侧点,把拐向判断的小于0条件改为小于等于0即可;如果只需要保留凸包的顶点,使用原小于0的判断即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:48:04