如何将CGAL::Polyhedron_3的半边子集插入CGAL::AABB_tree?
问题背景
已成功将CGAL::Polyhedron_3的所有边插入CGAL::AABB_tree,但插入半边子集时,使用存储Polyhedron::Halfedge_handle的vector编译失败(MacOS clang 13.0.1,测试CGAL 4.13.2/4.14.3/5.6);存储Polyhedron::Halfedge_const_iterator的vector可正常编译,但需求是使用Halfedge_handle而非迭代器。
编译错误核心是AABB_halfedge_graph_segment_primitive.h中的make_id函数无法匹配Halfedge_handle类型——该Primitive期望的输入是迭代器类型,而非句柄指针,导致类型转换失败。
解决方案
方法1:利用CGAL内置函数转换句柄为迭代器
如果需要保留Halfedge_handle的存储,可以在插入AABB树时,通过Polyhedron的iterator_from_handle成员函数将句柄转换为对应迭代器,再构造插入范围:
修改测试代码中的插入逻辑如下:
#elif INSERT_MODE==2 std::cout << "\nInserting subset of edges using Halfedge_handle" << std::endl; // 存储Halfedge_handle的vector(可正常编译) std::vector<Polyhedron::Halfedge_const_handle> half_edges; Polyhedron::Halfedge_const_iterator edge_pos = graph.halfedges_begin(); // 存入句柄 half_edges.push_back(edge_pos); ++edge_pos; half_edges.push_back(edge_pos); // 转换句柄为迭代器并插入AABB树 std::vector<Polyhedron::Halfedge_const_iterator> iterators; for (auto h : half_edges) { iterators.push_back(graph.iterator_from_handle(h)); } tree.insert(iterators.begin(), iterators.end(), graph); #endif
方法2:自定义适配Primitive支持Halfedge_handle
如果不想额外转换迭代器,可以自定义一个适配的Primitive类型,让它直接支持Halfedge_handle作为输入:
// 自定义支持Halfedge_handle的Primitive template <typename HalfedgeGraph> struct AABB_halfedge_handle_segment_primitive : public CGAL::AABB_halfedge_graph_segment_primitive<HalfedgeGraph> { typedef typename CGAL::AABB_halfedge_graph_segment_primitive<HalfedgeGraph> Base; typedef typename HalfedgeGraph::Halfedge_const_handle Halfedge_handle; AABB_halfedge_handle_segment_primitive() = default; AABB_halfedge_handle_segment_primitive(Halfedge_handle h, const HalfedgeGraph& g) : Base(g.iterator_from_handle(h), g) {} }; // 重新定义Primitive和Tree类型 typedef AABB_halfedge_handle_segment_primitive<Polyhedron> Primitive; typedef CGAL::AABB_traits<K, Primitive> Traits; typedef CGAL::AABB_tree<Traits> Tree;
之后即可直接用存储Halfedge_handle的vector插入:
tree.insert(half_edges.begin(), half_edges.end(), graph);
错误原因解析
从编译错误信息可见,make_id函数的候选参数期望的是ED类型(即HDS_edge迭代器),但传入的是Halfedge_handle对应的指针类型,两者无隐式转换,导致模板参数推导失败。而Halfedge_const_iterator本身就是符合要求的迭代器类型,因此可以正常匹配make_id的参数。
内容的提问来源于stack exchange,提问作者Duarte

