CGAL中使用copy_face_graph复制曲面网格不一致的解决咨询
你遇到的问题其实是copy_face_graph的设计特性导致的:这个函数的核心是复制拓扑结构(面、边、顶点的连接关系),但默认情况下不会保证副本的顶点顺序、坐标存储顺序和原网格完全一致——它可能会在内部重新排列顶点(比如去重、或者按照遍历顺序创建新顶点),所以才会出现顶点/面数相同但坐标顺序不对的情况。
下面给你两种解决方案,按需选择:
方案一:直接使用Surface_mesh的拷贝构造(最简单)
如果你只是想要一个和原网格完全一致的副本(包括顶点顺序、坐标、所有内置/自定义属性),根本不需要用copy_face_graph,直接用Surface_mesh的拷贝构造函数或者赋值运算符即可,它会自动完成深拷贝:
// 替换原来的copy_face_graph调用 Mesh mesh_copy = mesh_orig; // 或者 Mesh mesh_copy(mesh_orig);
这样得到的mesh_copy会和mesh_orig完全一致,包括顶点的顺序、每个顶点的坐标,以及所有附加在顶点/面/边上的属性。
方案二:用copy_face_graph并指定顶点映射(需要精细控制时)
如果因为某些原因必须使用copy_face_graph,可以通过指定**顶点映射(vertex map)**来强制保留原顶点的顺序和对应关系。具体做法是创建一个映射容器,记录原网格顶点到副本顶点的对应关系,然后传递给copy_face_graph的命名参数:
修改后的完整代码如下:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Surface_mesh.h> #include <iostream> #include <fstream> #include <CGAL/boost/graph/copy_face_graph.h> #include <map> typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh; typedef Mesh::Vertex_index Vertex_index; int main(int argc, char* argv[]) { const char* filename1 = (argc > 1)? argv[1] : "data/blobby.off"; std::cout << ".off loaded" << std::endl; std::ifstream input(filename1); Mesh mesh_orig; if (!input || !(input >> mesh_orig)) { std::cerr << "First mesh is not a valid off file." << std::endl; return 1; } input.close(); Mesh mesh_copy; // 创建顶点映射:记录原顶点到副本顶点的对应关系 std::map<Vertex_index, Vertex_index> vertex_map; // 使用命名参数传递顶点映射,确保顶点顺序和坐标一致 CGAL::copy_face_graph( mesh_orig, mesh_copy, CGAL::parameters::vertex_map(vertex_map) ); std::ofstream mesh_cpy("CPY_ANYLYZE/mesh_copy.off"); mesh_cpy << mesh_copy; mesh_cpy.close(); // 可选:验证顶点是否完全匹配 bool is_exact_copy = true; for (Vertex_index v : mesh_orig.vertices()) { if (mesh_orig.point(v) != mesh_copy.point(vertex_map[v])) { is_exact_copy = false; break; } } std::cout << (is_exact_copy ? "Exact copy created successfully!" : "Copy mismatch detected!") << std::endl; return 0; }
为什么这个方法有效?
通过传递vertex_map,copy_face_graph会严格按照原网格的顶点遍历顺序来创建副本的顶点,并将每个原顶点映射到副本中对应的位置,从而保证顶点的坐标和顺序与原网格完全一致。如果你的网格有自定义的顶点/面属性,还可以配合CGAL::copy_property_map来同步这些属性。
总结一下:如果只是要完整复制网格,优先用方案一;如果需要对复制过程做精细控制(比如只复制部分拓扑、自定义顶点映射),再用方案二。
内容的提问来源于stack exchange,提问作者gummiBear

