关于使用CGAL库计算多边形直骨架时忽略指定边及权重约束的技术问询
嘿,我刚好之前折腾过CGAL的直骨架相关功能,碰到过和你几乎一样的问题!来给你捋捋这里的门道~
首先说为什么CGAL的加权直骨架函数要求权重严格正:
其实CGAL的加权直骨架实现是基于加权Voronoi图的变体,算法核心是每条边以对应权重的速度向多边形内部收缩。0权重相当于这条边完全不收缩,偏移线和原边完全重合——这会打破算法依赖的几何假设,比如拓扑一致性、交点计算的唯一性,很容易导致数值计算崩溃或者生成错误的拓扑结构。CGAL的开发团队为了保证算法的鲁棒性,就直接把权重约束设为严格正,从根源上避免这些退化问题。
接下来是你最关心的:怎么实现“丢弃某些边”的需求?这里给你三个经过测试的可行方案:
方案1:用极小正权重替代0权重(权宜但实用)
如果你只是想模拟“边不收缩”的效果,可以给要丢弃的边设置一个极小的正权重,比如用你使用的几何内核的最小可表示正数值,示例代码如下:#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <limits> typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::FT FT; // 取内核数值类型的极小正数值 FT tiny_weight = std::numeric_limits<FT>::epsilon();不过要注意,极小权重可能会带来数值精度问题,比如某些情况下会出现微小的拓扑误差,所以建议在使用后验证结果的正确性,或者根据你的场景调整这个极小值(比如用
1e-8代替epsilon,避免内核的极端极小值)。方案2:预处理多边形,重构边界(更彻底的解决方法)
如果你的场景不允许用极小权重的折中方案,那可以直接修改原多边形:将要丢弃的边的两个相邻顶点直接连接,形成一个新的简单多边形,这样这些边就完全不参与直骨架的计算了。举个例子:假设你有一个五边形顶点序列A-B-C-D-E-A,想丢弃B-C这条边,那可以把顶点序列改成A-B-D-E-A,生成一个新的四边形,再对这个新多边形计算直骨架。
不过这个方法只适用于那些边被移除后,新的多边形仍然是你需要的几何形状的场景——如果你只是想让某些边不收缩但保留原多边形的轮廓,那这个方法可能不适用。方案3:使用低级构建器接口(灵活但复杂)
如果你需要更精细的控制,可以跳过高层的create_interior_weighted_straight_skeleton_2函数,直接使用CGAL的Straight_skeleton_builder_2低级接口。这个类允许你手动添加每条边并设置参数,甚至可以通过自定义逻辑控制哪些边参与收缩流程。不过这个方法的学习曲线比较陡,需要你深入理解CGAL直骨架的构建拓扑和几何逻辑,适合对CGAL有一定使用经验的开发者。
内容来源于stack exchange

