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

如何实现CGAL网格从lazy exact精确核到double类型非精确核转换

问题描述

我有一个使用三角形结构的CGAL网格,采用精确核(EK, EMesh3, EPoint3),需要将其转换为采用非精确核(K, Mesh3, Point3)的同拓扑网格。我目前的实现方案是遍历精确网格的所有顶点与面片,逐个添加到初始化的空非精确网格对象中,请问是否存在更简洁直接的转换方式?

当前手动实现的转换代码如下:

Mesh3 Convert(EMesh3 emesh) {
  const size_t nvertices = emesh.number_of_vertices();
  const size_t nedges    = emesh.number_of_edges();
  const size_t nfaces    = emesh.number_of_faces();
  Mesh3 mesh;
  mesh.reserve(nvertices, nedges, nfaces);
  for(EMesh3::Vertex_index vd : emesh.vertices()) {
    const EPoint3 vertex = emesh.point(vd);
    const double x = CGAL::to_double<EK::FT>(vertex.x());
    const double y = CGAL::to_double<EK::FT>(vertex.y());
    const double z = CGAL::to_double<EK::FT>(vertex.z());
    mesh.add_vertex(Point3(x, y ,z));
  }
  for(EMesh3::Face_index fd : emesh.faces()) {
    std::vector<int> face;
    for(EMesh3::Vertex_index vd : vertices_around_face(emesh.halfedge(fd), emesh)) {
      face.push_back(vd);
    }
    mesh.add_face(
      CGAL::SM_Vertex_index(face[0]), 
      CGAL::SM_Vertex_index(face[1]), 
      CGAL::SM_Vertex_index(face[2])
    );
  }
  return mesh;
}
最优解决方案

不需要手动遍历顶点、面片维护拓扑关系,直接使用CGAL内置的CGAL::copy_face_graph工具函数即可完成跨核的网格复制,只需要自定义顶点坐标的转换逻辑即可,代码可以大幅简化,同时鲁棒性更强。

最简实现代码(针对CGAL::Surface_mesh类型):

#include <CGAL/boost/graph/copy_face_graph.h>

Mesh3 Convert(const EMesh3& emesh) {
  Mesh3 mesh;
  CGAL::copy_face_graph(
    emesh, 
    mesh,
    CGAL::parameters::vertex_point_map(
      CGAL::make_transform_property_map(
        [](const EPoint3& p) {
          return Point3(
            CGAL::to_double(p.x()),
            CGAL::to_double(p.y()),
            CGAL::to_double(p.z())
          );
        },
        emesh.points()
      )
    )
  );
  return mesh;
}

这个方案相比手动遍历的优势:

  • 自动完整保留原网格的所有拓扑连接关系,不需要手动处理边、面的顶点索引对应
  • 内部自动完成内存预留,不需要手动计算顶点、边、面的数量调用reserve
  • 兼容所有符合CGAL FaceGraph概念的网格类型,Surface_mesh、Polyhedron_3等不同网格实现之间都可以用这个方法转换
  • 不会出现手动遍历容易遇到的顶点索引错位、面顶点环绕顺序错误的问题

注意:如果精确核使用的是支持开方运算的精确数类型,CGAL::to_double会做就近舍入,转换后的浮点坐标可能存在极小的数值误差,但网格拓扑结构会和原网格完全一致。

内容的提问来源于stack exchange,提问作者Stéphane Laurent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:57:15