OpenCASCADE网格和CGAL网格互转
在做一些网格相关的算法时(如曲线包覆算法),可以直接从OCC的TopoDS_Face得到对应的网格模型(获取TopoDS_Face网格)。OCC的中网格是Poly_Triangulation相关的类,用来显示等简单任务是很方便的,但做一些复杂的算法就比较累了。CGAL是一个很强大的网格算法库,开源但不友好,有很完备的数据结构,里面很多算法是很不错的,非常值得借鉴学习,CGAL是只有头文件的,使用起来很方便,只是大量使用模板,使用和理解起来有些费劲。
从occ切换到CGAL,最基本的是OCC的网格数据与CGAL的网格间的转换。代码如下:
1.Poly_Triangulation <=> Surface_mesh
typedef CGAL::Simple_cartesian<double> clKernel;
typedef CGAL::Point_3<clKernel> clPoint; //点
typedef CGAL::Surface_mesh<clPoint> clMesh;//网格
void MMesh_MeshFuns_Cgal::occMeshToClMesh(const Handle(Poly_Triangulation)& T, clMesh& sm) { sm.clear();//清空 if (T.IsNull()) return; try { //顶点数量、边的数量(不知)、面的数量 Standard_Integer nbNodes = T->NbNodes(); Standard_Integer nbTriangles = T->NbTriangles(); if (nbNodes == 0 || nbTriangles == 0) return; const TColgp_Array1OfPnt& nodes = T->Nodes(); const Poly_Array1OfTriangle& triangles = T->Triangles(); sm.reserve(nbNodes, 0, nbTriangles); //顶点 std::vector<cgalVertex_index> vertexmap(nbNodes); for (int i = 1; i <= nodes.Length(); i++) { const gp_Pnt& pnt = nodes.Value(i); cgalVertex_index vi = sm.add_vertex(clPoint(pnt.X(), pnt.Y(), pnt.Z())); vertexmap[i - 1] = vi; } //三角面 int n1, n2, n3; for (int i = 1; i <= triangles.Length(); i++) { const Poly_Triangle& tri = triangles.Value(i); tri.Get(n1, n2, n3); cgalFace_index fi = sm.add_face(std::vector<cgalVertex_index>{vertexmap[n1 - 1], vertexmap[n2 - 1], vertexmap[n3 - 1]}); } } catch (...) { } }
2.Surface_mesh <=> Poly_Triangulation
Handle(Poly_Triangulation) MMesh_MeshFuns_Cgal::clMeshToOccMesh(const clMesh& sm) { Handle_Poly_Triangulation T; if (sm.is_empty()) return T; try { Standard_Integer nbNodes = sm.number_of_vertices(); Standard_Integer nbTriangles = sm.number_of_faces(); if (nbNodes == 0 || nbTriangles == 0) return T; TColgp_Array1OfPnt nodes(1, nbNodes); Poly_Array1OfTriangle triangles(1, nbTriangles); //顶点 for (clMesh::Vertex_index vd : vertices(sm)) { const clPoint& p = sm.point(vd); nodes(vd.idx() + 1).SetCoord(p.x(), p.y(), p.z()); } //三角面 int vi = 1; for (clMesh::Face_index fd : sm.faces()) { vi = 1; for (clMesh::Vertex_index vd : vertices_around_face(sm.halfedge(fd), sm)) { triangles(fd.idx() + 1).Set(vi, vd.idx() + 1); if (vi == 3) break; vi++; } } //occ三角网格 T = new Poly_Triangulation(nodes, triangles); } catch (...) { } return T; }
更多精彩请关注公众号