如何用CGAL创建规则球体网格并以SurfaceMesh存储?
用CGAL生成规则球体网格并存储为SurfaceMesh
要生成你需要的规则球体网格(结构规整、面大小均匀),不能用原示例里的自适应隐式函数网格生成器(它会根据曲率自动调整网格密度,导致极点附近网格更密、整体形状不规则)。以下是两种可靠实现方式:
方法1:手动构造经纬网格(完全可控)
直接通过计算经纬坐标生成顶点,再按规则拼接成面,这种方式能精准控制网格的规整性:
#include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> #include <vector> typedef CGAL::Simple_cartesian<double> Kernel; typedef Kernel::Point_3 Point; typedef CGAL::Surface_mesh<Point> Mesh; int main() { Mesh mesh; const int num_latitudes = 20; // 纬度分段数(环数) const int num_longitudes = 40; // 经度分段数 // 存储顶点索引 std::vector<std::vector<Mesh::Vertex_index>> vertices(num_latitudes + 1); // 添加极点顶点 vertices[0].push_back(mesh.add_vertex(Point(0, 0, 1))); vertices[num_latitudes].push_back(mesh.add_vertex(Point(0, 0, -1))); // 计算中间层顶点 for (int i = 1; i < num_latitudes; ++i) { double theta = M_PI * i / num_latitudes; // 极角(从顶部极点往下) double z = cos(theta); double r = sin(theta); for (int j = 0; j < num_longitudes; ++j) { double phi = 2 * M_PI * j / num_longitudes; // 方位角 double x = r * cos(phi); double y = r * sin(phi); vertices[i].push_back(mesh.add_vertex(Point(x, y, z))); } } // 构建顶部极点周围的三角形面 for (int j = 0; j < num_longitudes; ++j) { int next_j = (j + 1) % num_longitudes; mesh.add_face(vertices[0][0], vertices[1][j], vertices[1][next_j]); } // 构建中间层的四边形面 for (int i = 1; i < num_latitudes - 1; ++i) { for (int j = 0; j < num_longitudes; ++j) { int next_j = (j + 1) % num_longitudes; mesh.add_face(vertices[i][j], vertices[i][next_j], vertices[i+1][next_j], vertices[i+1][j]); } } // 构建底部极点周围的三角形面 for (int j = 0; j < num_longitudes; ++j) { int next_j = (j + 1) % num_longitudes; mesh.add_face(vertices[num_latitudes][0], vertices[num_latitudes-1][next_j], vertices[num_latitudes-1][j]); } // 可以将网格保存为PLY等格式验证 CGAL::IO::write_ply("regular_sphere.ply", mesh); return 0; }
调整num_latitudes和num_longitudes可以控制网格的精细度,生成的网格完全符合你要的规整结构。
方法2:细分正多面体生成近似规则球体
先构造一个正多面体(比如正八面体),再用CGAL的细分算法迭代细分,得到趋近于球体的规整网格:
#include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> #include <CGAL/Subdivision_method_3.h> typedef CGAL::Simple_cartesian<double> Kernel; typedef Kernel::Point_3 Point; typedef CGAL::Surface_mesh<Point> Mesh; // 构造正八面体初始网格 Mesh create_octahedron() { Mesh mesh; // 正八面体的6个顶点 auto v0 = mesh.add_vertex(Point(1, 0, 0)); auto v1 = mesh.add_vertex(Point(-1, 0, 0)); auto v2 = mesh.add_vertex(Point(0, 1, 0)); auto v3 = mesh.add_vertex(Point(0, -1, 0)); auto v4 = mesh.add_vertex(Point(0, 0, 1)); auto v5 = mesh.add_vertex(Point(0, 0, -1)); // 构建8个三角形面 mesh.add_face(v4, v0, v2); mesh.add_face(v4, v2, v1); mesh.add_face(v4, v1, v3); mesh.add_face(v4, v3, v0); mesh.add_face(v5, v0, v3); mesh.add_face(v5, v3, v1); mesh.add_face(v5, v1, v2); mesh.add_face(v5, v2, v0); return mesh; } int main() { Mesh mesh = create_octahedron(); // 执行3次Catmull-Clark细分(次数越多,网格越接近球体,也越精细) CGAL::Subdivision_method_3::CatmullClark(mesh, 3); // 保存网格 CGAL::IO::write_ply("subdivided_sphere.ply", mesh); return 0; }
细分后的网格结构规整,面大小均匀,多次细分后会非常接近完美球体。
为什么原示例生成不规则网格?
你用的Surface_mesher是自适应隐式曲面网格生成器,它会根据隐式函数的曲率自动调整网格密度:球体极点附近曲率变化大,所以会生成更多小三角形,导致整体形状看起来不规则。这种工具适合复杂隐式曲面的网格生成,但不适合需要规整结构的球体场景。
内容的提问来源于stack exchange,提问作者Zimao
相关产品推荐
相关产品推荐

