向空Polygon_Set_2插入Polygon_2时触发CGAL前置条件违反错误
解决CGAL Polygon_set_2插入多边形时的预条件违反错误
问题分析
触发CGAL::Precondition_exception的核心原因是浮点数精度误差破坏了Arr_segment_traits_2内部的几何断言。你使用的Simple_cartesian<double>内核依赖普通浮点数运算,当多边形顶点坐标为近似值(例如代码中的-2.7071是√2的近似)时,舍入误差会导致CGAL无法正确判定点与线段的位置关系,进而触发预条件检查失败。
解决方案
1. 使用精确构造内核替换浮点数内核
将Simple_cartesian<double>替换为CGAL::Exact_predicates_exact_constructions_kernel,这个内核采用精确的有理数运算,完全避免浮点数精度问题。修改后的类型定义如下:
// 替换原有的内核定义 typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef typename K::Point_2 Point_2; typedef typename CGAL::Polygon_2<K> Polygon_2; typedef typename CGAL::Polygon_set_2<K> Polygon_set_2;
2. 确保多边形严格简单且顶点顺序正确
虽然你验证过多边形有效,但浮点数下的"简单性"可能存在隐性问题:
- 检查顶点是否按顺时针或逆时针顺序排列(避免数值误差导致的微小自交叉)
- 可调用
polygon.is_simple()再次确认(Debug模式下会触发更严格的检查)
3. 使用精确坐标值(可选)
如果坐标来自数学公式推导(比如√2),直接用CGAL的精确构造方式生成点,避免手动输入近似值:
// 示例:用精确构造生成√2相关的点 K::FT sqrt2 = CGAL::sqrt(K::FT(2)); std::vector<Point_2> vertices2 = { Point_2(-(2 - sqrt2), -(sqrt2 - 1)), Point_2(-sqrt2, -(2 - sqrt2)), Point_2(-(sqrt2 - 1), -sqrt2), Point_2(-(2 - sqrt2), -(sqrt2 - 1)) };
修改后的完整代码
#include <CGAL/Exact_predicates_exact_constructions_kernel.h> #include<CGAL/Polygon_2.h> #include<CGAL/Polygon_set_2.h> #include<CGAL/draw_polygon_2.h> #include<CGAL/draw_polygon_set_2.h> typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef typename K::Point_2 Point_2; typedef typename CGAL::Polygon_2<K> Polygon_2; typedef typename CGAL::Polygon_set_2<K> Polygon_set_2; int main(){ Polygon_set_2 S; std::vector<Point_2> vertices2 = { Point_2(-1.99618, -1.2929), Point_2(-2.7071, -1.99618), Point_2(-2.00382, -2.7071), Point_2(-1.2929, -2.00382) }; Polygon_2 polygon(vertices2.begin(), vertices2.end()); CGAL::draw(polygon); S.insert(polygon); CGAL::draw(S); return 0; }
补充说明
- 若不需要完全精确的构造,也可尝试
Exact_predicates_inexact_constructions_kernel,它的谓词是精确的,构造用浮点数,部分场景下也能解决问题,但对于近似坐标,精确内核的可靠性更高。 - Debug模式下CGAL的预条件检查更严格,Release模式可能跳过部分检查,但这只是掩盖问题,建议在Debug模式下解决根源问题。
内容的提问来源于stack exchange,提问作者Duo Zhang
相关产品推荐
相关产品推荐

