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

如何使用CGAL对3D闭合2流形点集生成三角形网格(非四面体)

解决CGAL生成曲面三角形网格的问题

首先明确:Triangulation_3是三维空间的四面体三角化工具,生成的是三维网格,自然会得到四面体。要生成嵌入R³的闭合2流形的三角形网格,应该用CGAL针对曲面的工具,以下是两种适配你场景的方案:

方案一:利用Delaunay三角化提取凸包表面(适配球面这类凸曲面)

因为你生成的是球面点,球面的凸包就是其本身,凸包的面都是三角形。步骤如下:

  1. 构建三维Delaunay三角化
  2. 遍历三角化的凸包面,提取每个面的三个顶点,组成三角形网格

示例代码:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <vector>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_3<K> Delaunay;
typedef K::Point_3 Point;

int main() {
    std::vector<Point> points;
    int num_theta = 30;
    int num_phi = 15;
    // 改进球面点生成:双层循环生成均匀分布的点
    for (int i = 0; i < num_phi; ++i) {
        double phi = CGAL_PI * i / (num_phi - 1);
        for (int j = 0; j < num_theta; ++j) {
            double theta = 2 * CGAL_PI * j / num_theta;
            double x = std::sin(phi) * std::cos(theta);
            double y = std::sin(phi) * std::sin(theta);
            double z = std::cos(phi);
            points.emplace_back(x, y, z);
        }
    }

    Delaunay dt(points.begin(), points.end());

    // 遍历凸包面,输出三角形
    for (auto f = dt.finite_faces_begin(); f != dt.finite_faces_end(); ++f) {
        if (dt.is_on_convex_hull(f)) {
            // 获取面的三个顶点
            Point p0 = f->vertex(0)->point();
            Point p1 = f->vertex(1)->point();
            Point p2 = f->vertex(2)->point();
            // 这里可以将三个点存入你的三角形网格结构,比如Surface_mesh
            std::cout << p0 << ", " << p1 << ", " << p2 << std::endl;
        }
    }

    return 0;
}

方案二:Poisson曲面重建(适配一般闭合2流形)

如果你的点集来自非凸的闭合2流形,Poisson曲面重建可以从散点生成闭合的三角形网格,步骤如下:

  1. 为点集计算法向量(如果没有的话)
  2. 调用Poisson重建函数生成曲面网格

示例代码:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Poisson_surface_reconstruction.h>
#include <CGAL/Surface_mesh.h>
#include <vector>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_3 Point;
typedef K::Vector_3 Vector;
typedef CGAL::Surface_mesh<Point> Mesh;

int main() {
    std::vector<std::pair<Point, Vector>> points_with_normals;
    // 先生成球面点并计算法向量(球面点的法向量就是点本身的单位向量)
    int num_theta = 30;
    int num_phi = 15;
    for (int i = 0; i < num_phi; ++i) {
        double phi = CGAL_PI * i / (num_phi - 1);
        for (int j = 0; j < num_theta; ++j) {
            double theta = 2 * CGAL_PI * j / num_theta;
            double x = std::sin(phi) * std::cos(theta);
            double y = std::sin(phi) * std::sin(theta);
            double z = std::cos(phi);
            Point p(x, y, z);
            Vector n(x, y, z); // 球面法向量等于点坐标
            points_with_normals.emplace_back(p, n);
        }
    }

    Mesh mesh;
    // 执行Poisson重建
    CGAL::poisson_surface_reconstruction_delaunay(
        points_with_normals.begin(), points_with_normals.end(),
        mesh,
        CGAL::parameters::relative_weight(2.0) // 可调整参数优化结果
    );

    // 输出网格信息或保存到文件
    std::cout << "Mesh has " << mesh.number_of_vertices() << " vertices and " << mesh.number_of_faces() << " faces." << std::endl;

    return 0;
}

额外说明

你原来的球面点生成代码存在问题:用同一个i生成theta和phi,导致点集中在一条螺旋线上,分布极不均匀,会影响后续三角化效果。上面的示例代码改用双层循环生成theta和phi,能得到更均匀的球面点。

内容的提问来源于stack exchange,提问作者Cedric Martens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:45:28