最可靠方案是使用 boost::geometry::intersects(),需确保多边形类型为 boost::geometry::model::polygon<Point>、顶点闭合、正确处理孔与浮点容差。

用 boost::geometry 判断两个多边形是否相交最可靠
标准 C++ 库不提供几何运算能力,手写射线法或分离轴(SAT)容易漏掉凹多边形、自相交、退化边等边界情况。直接用 boost::geometry 是目前最省心且工业级可用的方案。
它支持任意环序(顺/逆时针)、带孔多边形、浮点容差控制,并自动处理拓扑异常(如共线点、零长边)。关键函数是 boost::geometry::intersects() 和 boost::geometry::overlaps() ——前者检测“有公共内点或边界点”,后者严格要求“内部有重叠但不完全包含”。
- 确保多边形类型定义为
boost::geometry::model::polygon<point_type>,其中point_type推荐用boost::geometry::model::d2::point_xy<double> - 输入顶点必须闭合(首尾点相同),否则
intersects()可能返回false即使视觉上相交 - 若多边形含孔,需用
boost::geometry::model::polygon<...>::inner_ring_type显式添加,否则孔会被忽略 - 编译需链接
-lboost_system,头文件只需#include <boost/geometry.hpp>和#include <boost/geometry/geometries/polygon.hpp>
自己实现时优先用分离轴定理(SAT)而非射线法
射线法(如奇偶规则)只适合单个点在多边形内的判断,无法直接用于两多边形相交;而 SAT 能自然扩展到凸/凹多边形对——只要把凹多边形三角剖分后对每对三角形做 SAT,就可覆盖全部情况。
SAT 的核心是:两个凸多边形不相交 ⇔ 存在某条轴(取自任一多边形的边法向量),使得它们在该轴上的投影不重叠。实现时要注意:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 对凹多边形,必须先调用
earcut或poly2tri做三角剖分,再逐对三角形调用 SAT,否则会漏判“凹口咬合”情形 - 浮点比较必须用容差(如
1e-9),避免因dot计算精度导致投影区间误判为无重叠 - 轴方向要单位化,否则投影长度失真;法向量生成需统一按边向量逆时针旋转 90° 得到
- 若需区分“相交”和“包含”,不能只依赖 SAT 结果——SAT 只回答“是否分离”,包含关系得额外用
point_in_polygon检查一个形心是否在另一多边形内
CGAL 适合高精度或带约束的场景,但编译和依赖重
当多边形顶点坐标来自 CAD 数据、需要精确布尔运算(如求交集区域),或含大量共线/退化结构时,CGAL 比 boost::geometry 更稳。它的 do_intersect() 基于精确几何谓词,不会因浮点误差返回假阴性。
但代价明显:头文件编译极慢,需启用 -DCGAL_HEADER_ONLY=ON 或预编译;依赖 GMP 和 MPFR;且 API 更底层——比如多边形要封装成 CGAL::Polygon_2<K>,K 需显式选 Exact_predicates_exact_constructions_kernel 才保精度。
- 若只是运行时判断布尔结果(不要求构造交集),
CGAL::do_intersect(p1, p2)足够,比intersection()快一个数量级 - 顶点顺序不影响结果,
CGAL内部自动归一化环向 - 不支持直接读取带孔多边形字符串;需手动拆分外环和内环,再用
CGAL::General_polygon_set_2组装 - Windows 下用 MSVC 编译需关掉
/permissive-,否则模板实例化报错
常见错误:用 std::vector<Point> 直接传给几何库却没闭合或多义
很多人把顶点存成 std::vector<Point>(如 {(0,0), (1,0), (1,1)}),然后直接塞给 boost::geometry::intersects(),结果始终返回 false。问题不在算法,而在数据格式不匹配。
所有主流几何库都要求多边形对象满足“环闭合”语义:即首点与末点坐标完全一致。否则库会认为这是开折线,不是封闭区域。
- Boost 示例:
poly.outer().push_back(poly.outer().front());补闭合点,不能靠“隐式理解” - CGAL 中若用
Polygon_2构造器传入未闭合 vector,会静默截断或触发断言失败 - 若顶点含重复点(如
(0,0), (0,0), (1,0)),部分库(如旧版 Boost)可能崩溃;预处理应调用boost::geometry::remove_spikes() - 坐标单位不一致(如一个用毫米、一个用米)会导致容差失效;务必在输入前统一度量尺度
真正麻烦的从来不是“怎么算”,而是“怎么让数据符合库的契约”。多边形相交判断本身很成熟,但数据毛刺、环向混乱、浮点噪声这些细节,才是线上出问题的主因。

















