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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:37:39