凸多边形相交检测应优先使用SAT算法,时间复杂度O(n+m),通过n+m条分离轴(各边法向量)投影比较判定:任一轴无重叠即不相交,全部重叠则相交。

没有万能函数,必须按形状类型分层处理——凸多边形用 SAT,凹多边形必须做边-边检测,别指望一个 intersects() 调用就搞定。
凸多边形优先用 SAT,别手写射线法判点
SAT 是唯一适合凸多边形的高效方案,时间复杂度 O(n+m),结果确定:只要所有分离轴上投影重叠,就一定相交;任一轴不重叠,立刻返回 false。
- 分离轴来源:取 A 和 B 所有边的法向量(二维即边向量
(dx, dy)旋转 90° 得(-dy, dx)),共n + m条,无需归一化 - 投影比较:对每条轴,分别算 A 和 B 的 min/max 投影值;若
max_A + 1e-6f ,该轴分离,直接返回 <code>false - 常见坑:漏枚举某条边的法向量 → 漏掉分离轴 → 误报相交;浮点比较不加容差 → 共线或紧贴时因精度丢失误判
凹多边形必须遍历边-边相交,仅判点会漏判
“所有顶点都在对方内部” ≠ “多边形相交”。典型反例:U 形凹多边形三个顶点在矩形内,但底边穿出——此时顶点全在内,却完全不相交。
- 必要条件:遍历 A 的每条边与 B 的每条边,调用线段相交检测;推荐用
ccw()判断规范相交(排除端点重合、共线等歧义) - 充分条件:只要发现一对边有**内部交点**(非仅端点重合),立即返回
true - 退化情况:若无边相交,再检查是否存在一个顶点在另一多边形**严格内部**(用 winding number + 容差),此时是包含关系,不是相交
- 性能提醒:
O(n×m)复杂度,顶点数超 50 时明显卡顿;务必先用aabb_intersect()粗筛,!aabb_intersect(a, b)就直接跳过
用 boost::polygon::intersects() 前先确认数据合规性
boost::polygon::intersects() 看似省事,但崩溃或返回 false negative 很常见,问题几乎都出在输入质量上。
立即学习“C++免费学习笔记(深入)”;
- 顶点顺序:必须全部为逆时针(或全部顺时针),否则结果错误;可用
boost::polygon::area()检查符号,负值说明顺序反了 - 闭合性:顶点数组首尾**不必重复**,Boost 内部会自动闭合;若手动重复首顶点,会导致非法多边形构造失败
- 自交检测:Boost 不拒绝自交多边形,但
intersects()在这种输入下行为未定义;必须前置做is_simple()或边-边自交检测
三角形这类特殊凸形,分离轴要精简去重
两个三角形只需检测 11 条有效分离轴:A 的面法向量(1 条)、B 的面法向量(1 条)、A 的 3 条边 × B 的 3 条边 → 9 个叉积方向,但其中可能重复或为零向量。
- 别硬编码循环 15 次;插入每条轴前用
glm::all(glm::epsilonEqual(a, b, 1e-6f))去重,且用glm::length()过滤掉模长的零向量 - 投影区间必须对全部 3 个顶点计算
glm::dot(vertex, axis),取 min/max;别用std::minmax_element—— vector 小于 3 时行为易错 - 退化三角形(三点几乎共线)必须提前拦截:用
0.5f * glm::length(glm::cross(v1 - v0, v2 - v0))算面积,若,降级为线段相交检测 + 端点包含判断
最常被忽略的是:凹多边形不能靠顶点包含“蒙混过关”,而凸多边形一旦退化(比如建模误差导致三点共线),SAT 就会崩——这两类情况必须在主逻辑外单独设防,不是加个 try-catch 就能解决的。


















