结论:没有万能函数,必须按形状类型分层处理多边形相交;凸多边形应优先使用sat算法,其时间复杂度为o(n+m),通过检查n+m条分离轴(两多边形各边法向量)上投影是否重叠来确定相交。

直接结论:没有万能函数,必须按形状类型分层处理
两个多边形是否相交,不能靠一个 is_intersect() 调用就解决。C++ 标准库不提供此功能,Boost 的 boost::polygon 虽有 overlap() 和 intersects(),但默认只处理简单多边形且要求顶点顺序一致、无自交;实际项目中,你大概率得自己组合算法。
凸多边形优先用 SAT,别手写射线法判点
SAT(Separating Axis Theorem)是唯一适合凸多边形的高效方案,O(n+m) 时间复杂度,且结果确定——只要所有分离轴上投影重叠,就一定相交;发现任一轴不重叠,立刻返回 false。
-
分离轴来源:取 A 和 B 所有边的法向量(二维即旋转 90°),共 n+m 条,无需归一化,用dot()投影即可 -
投影比较:对每条轴,分别算 A 和 B 的 min/max 投影值;若max_A ,该轴分离,直接返回 false -
常见坑:忘记检查 A 的边法向量和 B 的边法向量要**各自独立枚举**;漏掉某条边 → 漏判分离轴 → 误报相交 -
浮点安全:投影比较必须加容差,如max_A ,否则共线或紧贴时因精度丢失误判
凹多边形必须做边-边相交检测,仅判点会漏判
“所有顶点都在对方内部” ≠ “多边形相交”,这是 99% 新手栽跟头的地方。典型反例:U 形凹多边形三个顶点在矩形内,但底边穿出——此时顶点全在内,却完全不相交。
-
必要条件:遍历 A 的每条边与 B 的每条边,调用线段相交检测(推荐用ccw()判断规范相交,避免除零和端点歧义) -
充分条件:只要发现一对边有**内部交点**(非仅端点重合),立即返回 true -
退化情况:若无边相交,再检查是否存在一个顶点在另一多边形**严格内部**(用 winding number + 容差),此时才可能为包含关系而非相交 -
性能提醒:O(n×m) 复杂度,顶点数超 50 时明显卡顿;务必先用 AABB 粗筛,!aabb_intersect(a, b)就直接跳过
用 Boost::polygon 前先确认数据合规性
Boost 的 boost::polygon::intersects() 看似省事,但实际运行时崩溃或返回 false negative 很常见,问题几乎都出在输入质量上。
-
顶点顺序:必须全部为逆时针(或全部顺时针),否则intersects()可能返回错误结果;用boost::polygon::area()检查符号,负值说明顺序反了 -
闭合性:顶点数组首尾不必重复,但 Boost 内部会自动闭合;若手动重复首顶点,会导致非法多边形构造失败 -
自交检测:Boost 不拒绝自交多边形,但intersects()行为未定义;上线前务必用boost::polygon::is_valid()验证 -
坐标类型:强烈建议用int或long long,浮点型易触发内部断言失败;若必须用 float/double,请配合boost::polygon::set_coordinate_type显式配置
真正难的不是写对一个 case,而是让同一套逻辑在凸/凹/退化/浮点扰动/顶点乱序下都不崩——边界和容差处理,永远比主干逻辑更耗时间。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











