使用std::pair<Point_3,unsigned>生成TIN时CGAL类混合报错求解
问题:使用带索引的3D点生成TIN并转换为Surface_mesh
我希望用std::pair<Point_3, unsigned>替代Point_3来生成TIN,想知道如何正确组合Surface_mesh、Projection_traits_xy_3、Triangulation_vertex_base_with_info_2和Delaunay_triangulation_2。我写的代码如下:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Projection_traits_xy_3.h> #include <CGAL/Delaunay_triangulation_2.h> #include <CGAL/boost/graph/copy_face_graph.h> #include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> #include <CGAL/Delaunay_triangulation_2.h> #include <CGAL/point_generators_2.h> #include <CGAL/Triangulation_vertex_base_with_info_2.h> #include <map> typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Projection_traits_xy_3<K> PrjTrts; typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned, PrjTrts> Vb2; typedef K::Point_3 Point3; typedef CGAL::Surface_mesh<Point3> Mesh; typedef CGAL::Triangulation_data_structure_2<Vb2> T2ds; typedef CGAL::Delaunay_triangulation_2<PrjTrts, T2ds> TIN; int main () { std::map<Point3, unsigned> cgalPts; insertSomePtsIn(cgalPts); TIN dsm(cgalPts.begin(),cgalPts.end()); Mesh sm; CGAL::copy_face_graph(dsm, sm); return 0; }
运行时出现如下编译错误:
In file included from /home/Necktwi/workspace/displaz/src/render/PointArray.cpp:28: /usr/include/CGAL/boost/graph/copy_face_graph.h:342:46: error: no matching function for call to 'get' 342 | get(vertex_point, sm)), | ^~~ /home/Necktwi/workspace/displaz/src/render/PointArray.cpp:1035:13: note: in instantiation of function template specialization 'CGAL::copy_face_graph<CGAL::Delaunay_triangulation_2<CGAL::Projection_traits_xy_3<CGAL::Epick>, CGAL::Triangulation_data_structure_2<CGAL::Triangulation_vertex_base_with_info_2<unsigned int, CGAL::Projection_traits_xy_3<CGAL::Epick>>>>, CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>>, CGAL::Named_function_parameters<bool, CGAL::internal_np::all_default_t>, CGAL::Named_function_parameters<bool, CGAL::internal_np::all_default_t>>' requested here 1035 | CGAL::copy_face_graph(dsm, sm); | ^ /usr/include/boost/property_map/property_map.hpp:129:19: note: candidate template ignored: could not match 'const T *' against 'boost::vertex_point_t' 129 | inline const T& get(const T* pa, std::ptrdiff_t k) { return pa[k]; } | ^ /usr/include/boost/property_map/property_map.hpp:165:3: note: candidate template ignored: could not match 'readable_property_map_archetype<K, V>' against 'boost::vertex_point_t' 165 | get(const readable_property_map_archetype<K,V>&, | ^ /usr/include/boost/property_map/property_map.hpp:302:3: note: candidate template ignored: could not match 'put_get_helper<Reference, PropertyMap>' against 'boost::vertex_point_t' 302 | get(const put_get_helper<Reference, PropertyMap>& pa, const K& k) | ^ /usr/include/CGAL/Dynamic_property_map.h:232:1: note: candidate template ignored: could not match 'CGAL::dynamic_vertex_property_t<T>' against 'boost::vertex_point_t' 232 | get(const CGAL::dynamic_vertex_property_t<T>&, const G&) | ^ /usr/include/CGAL/Dynamic_property_map.h:240:1: note: candidate template ignored: could not match 'CGAL::dynamic_halfedge_property_t<T>' against 'boost::vertex_point_t' 240 | get(const CGAL::dynamic_halfedge_property_t<T>&, const G&) | ^ /usr/include/CGAL/Dynamic_property_map.h:248:1: note: candidate template ignored: could not match 'CGAL::dynamic_edge_property_t<T>' against 'boost::vertex_point_t' 248 | get(const CGAL::dynamic_edge_property_t<T>&, const G&) | ^ /usr/include/CGAL/Dynamic_property_map.h:256:1: note: candidate template ignored: could not match 'CGAL::dynamic_face_property_t<T>' against 'boost::vertex_point_t' 256 | get(const CGAL::dynamic_face_property_t<T>&, const G&)
问题分析与解决方案
错误核心是带信息的三角剖分顶点与Surface_mesh的顶点属性映射不兼容:copy_face_graph默认尝试直接读取TIN的顶点属性,但你的TIN顶点存储的是「投影2D点+unsigned索引」,而非Surface_mesh需要的原始3D点,导致属性映射失败。
修正后的完整代码
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Projection_traits_xy_3.h> #include <CGAL/Delaunay_triangulation_2.h> #include <CGAL/Surface_mesh.h> #include <CGAL/Triangulation_vertex_base_with_info_2.h> #include <vector> #include <map> #include <iostream> typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Projection_traits_xy_3<K> PrjTrts; // 顶点存储:unsigned索引 + 投影后的2D点 typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned, PrjTrts> Vb2; typedef CGAL::Triangulation_data_structure_2<Vb2> T2ds; typedef CGAL::Delaunay_triangulation_2<PrjTrts, T2ds> TIN; typedef K::Point_3 Point3; typedef CGAL::Surface_mesh<Point3> Mesh; // 模拟插入3D点的函数 void insertSomePtsIn(std::vector<std::pair<PrjTrts::Point_2, unsigned>>& indexed_pts, std::vector<Point3>& original_pts) { original_pts.emplace_back(0, 0, 1); pts.emplace_back(PrjTrts::Point_2(0, 0), 0); original_pts.emplace_back(1, 0, 2); pts.emplace_back(PrjTrts::Point_2(1, 0), 1); original_pts.emplace_back(0, 1, 3); pts.emplace_back(PrjTrts::Point_2(0, 1), 2); original_pts.emplace_back(1, 1, 0.5); pts.emplace_back(PrjTrts::Point_2(1, 1), 3); } int main () { std::vector<Point3> original_pts; // 存储原始3D点 std::vector<std::pair<PrjTrts::Point_2, unsigned>> indexed_pts; // 投影2D点+原始点索引 insertSomePtsIn(indexed_pts, original_pts); // 构建带索引的Delaunay三角剖分 TIN dsm(indexed_pts.begin(), indexed_pts.end()); Mesh sm; std::map<TIN::Vertex_handle, Mesh::Vertex_index> vmap; // TIN顶点到Surface_mesh顶点的映射 // 手动拷贝顶点:通过索引获取原始3D点 for (auto vh : dsm.finite_vertex_handles()) { unsigned idx = vh->info(); vmap[vh] = sm.add_vertex(original_pts[idx]); } // 手动拷贝面:根据顶点映射构建Surface_mesh的面 for (auto fh : dsm.finite_face_handles()) { Mesh::Vertex_index v0 = vmap[fh->vertex(0)]; Mesh::Vertex_index v1 = vmap[fh->vertex(1)]; Mesh::Vertex_index v2 = vmap[fh->vertex(2)]; sm.add_face(v0, v1, v2); } // 验证结果 std::cout << "Surface_mesh 顶点数:" << num_vertices(sm) << ",面数:" << num_faces(sm) << std::endl; return 0; }
关键修正点
- 输入数据结构调整:用
std::vector<std::pair<PrjTrts::Point_2, unsigned>>替代std::map<Point3, unsigned>,直接传递投影后的2D点和原始3D点的索引,避免重复投影和map的性能损耗。 - 放弃自动拷贝:不再使用
copy_face_graph,改为手动遍历TIN的顶点和面,通过顶点存储的索引从原始3D点集合中获取坐标,完全控制顶点属性的传递,解决属性映射不兼容问题。 - 明确顶点信息的作用:
Triangulation_vertex_base_with_info_2存储的unsigned值是原始3D点在向量中的索引,确保Surface_mesh最终存储的是未投影的原始3D坐标。
内容的提问来源于stack exchange,提问作者Necktwi
相关产品推荐
相关产品推荐

