You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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;
}

关键修正点

  1. 输入数据结构调整:用std::vector<std::pair<PrjTrts::Point_2, unsigned>>替代std::map<Point3, unsigned>,直接传递投影后的2D点和原始3D点的索引,避免重复投影和map的性能损耗。
  2. 放弃自动拷贝:不再使用copy_face_graph,改为手动遍历TIN的顶点和面,通过顶点存储的索引从原始3D点集合中获取坐标,完全控制顶点属性的传递,解决属性映射不兼容问题。
  3. 明确顶点信息的作用:Triangulation_vertex_base_with_info_2存储的unsigned值是原始3D点在向量中的索引,确保Surface_mesh最终存储的是未投影的原始3D坐标。

内容的提问来源于stack exchange,提问作者Necktwi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:32:19