一个多面体连续减去多个多面体

Subtracting multiple polyhedra continuously from a polyhedron

我想得到一个多面体减去多个(可能是几百个)多面体的结果。我发现 CGAL 库的“3D Boolean Operations on Nef Polyhedra”包支持多面体之间的布尔运算。我想用这个包来解决我的问题,但是我 运行 陷入了很多麻烦。虽然我知道 CGAL 库是一个强大的库,但我对它完全陌生,不知道如何最有效地使用它来解决我的问题。 我的目标是使用 CGAL 库实现一个多面体减去多个多面体,我将更详细地介绍这个问题以及我的方法和程序产生的错误。如果你能告诉我为什么程序会产生这些错误以及我如何有效地使用 CGAL 库来实现一个多面体减去多个多面体,我将不胜感激。

我想用CGAL解决的问题: 我用 MATLAB 得到了一些多面体:A,B1,B2,...,Bi,..., Bn(n 可能有几百个)。我想得到 A-B1-B2-...-Bn.

的结果

我用CGAL库解决这个问题的方法: 事实上,只有A是2-流形,而Bi都是有边界的3维曲面。为了使用 CGAL 库的“Nef 多面体上的 3D 布尔运算”包,我将这些表面变成了闭合多面体。我将 A 保存为名为“blank.off”的“.off”格式文件。 Bi 被转换为“.off”格式,所有 Bi 都保存在一个名为“sv.off”的文件中。每个 Bi 由换行符分隔。我使用 CGAL::OFF_to_nef_3() 将文件“blank.off”读入 Nef_polyhedron 对象 nef1。然后我写了一个循环语句,其中我使用 CGAL::OFF_to_nef_3() 将文件“sv.off”读入 Nef_polyhedron 对象 nef2 并执行 nef1-=nef2.

代码如下:

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>

#include <CGAL/Polyhedron_3.h>

#include <CGAL/Nef_polyhedron_3.h>

#include <CGAL/IO/Polyhedron_iostream.h>

#include <CGAL/draw_nef_3.h>

#include <CGAL/OFF_to_nef_3.h>
    
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; 

typedef CGAL::Polyhedron_3<Kernel>  Polyhedron;

typedef CGAL::Nef_polyhedron_3<Kernel> Nef_polyhedron;

#include<fstream>
#include<ctime>

int main() {

    Polyhedron p1, p2, res;
    int n = 0;

    std::ifstream fin1("blank.off");
    std::ifstream fin2("sv.off");
    std::cout << "how many polyhedra in sv.off\n";
    std::cin >> n;

    //load nef2 and do bool operations
    Nef_polyhedron nef1(p1);
    Nef_polyhedron nef2(p2);
    CGAL::OFF_to_nef_3(fin1, nef1);
    fin1.close();
    for (int i = 0; i < n;i++) {

        nef2.clear();
        CGAL::OFF_to_nef_3(fin2, nef2);
        fin2.get();

        nef1 -= nef2;
        std::cout << "A-B" << i+1 << " have been calculated" << std::endl;

    }

    //convert nef2 to res.off
    nef1.convert_to_polyhedron(res);
    std::ofstream fout("res.off");
    fout << res;

    //draw
    //CGAL::draw(nef1);
    fin2.close();

    return 0;
}

您可以从 Github 下载 blank.off 和 sv.off 文件。下载link:blank.off and sv.off

程序运行时出现的问题运行

  1. 在程序的第五次迭代 (i==4) 中,有时 IDE 会停止 运行 或崩溃而不会抛出任何异常。为什么会出现这个问题?是不是内存占用太高了?
  2. 12 次循环后(i==11),我想将nef1 转换为.off 文件以保存当前结果。但是当程序执行到"nef1.convert_to_polyhedron(res)"since nef1.is_simple() returns false这句时就失败了。我查看了手册,意识到这意味着 nef1 不再是 2-流形。但是是什么导致 nef1 不再是 2-流形? CGAL 中是否有函数可以修改 nef1 使其再次成为 2-流形?
  3. 这不是错误,而是计算速度太慢了。还有其他方法可以更快吗?

其他问题: 事实上,我最初使用 MATLAB 得到的是无边界的多面体 A 和有边界的曲面 B 的 点集 。为了对A和B进行布尔运算,我用MATLAB编写了一些程序来对A和B进行三角剖分,并将B转换为闭合多面体。我知道程序生成的三角网格质量不高,这可能是出现这么多错误的主要原因。这些是否完全可以用 CGAL 库来完成?怎么做? 最重要的问题是CGAL库是否适合对三维几何进行数百次连续的布尔运算?

非常感谢您阅读这个问题,如果您能帮助我,我将不胜感激。

在对您的输入进行了一些研究之后,我可以说您所有问题的最合理原因是您的输入不是很干净。如果您设法从 sv.off 的 OFF 中移除退化的面孔,一切都应该 运行 没问题。现在,有一种方法可以使一切变得更快:corefine_and_compute_difference。 如果我调整你的代码来使用它,它看起来像:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/draw_surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic;

typedef CGAL::Surface_mesh<Epic::Point_3>  Surface_mesh;
int main() {
    std::cout << "how many polyhedra in sv.off\n";
    std::cin >> n;
    std::ifstream fin1("data/blank.off");
    std::ifstream fin2("data/sv.off");

    //load nef2 and do bool operations
    Surface_mesh s1, s2, out;
    CGAL::IO::read_OFF(fin1, s1);
    fin1.close();
    for (int i = 0; i < n;i++) {

        s2.clear();
        CGAL::IO::read_OFF(fin2, s2);
        fin2.get();

        std::ofstream fout("s2.off");
        fout << s2;
        fout.close();
        CGAL::Polygon_mesh_processing::corefine_and_compute_difference(s1, s2, s1);
        std::cout << "A-B" << i+1 << " have been calculated" << std::endl;

    }

    //convert nef2 to res.off
    std::ofstream fout("res.off");
    fout << s1;
    fout.close();
    //draw
    CGAL::draw(s1);
    fin2.close();

    return 0;
}

但是您必须确保您的 sv 网格是“干净的”,例如它们不能有退化的面。 从第一个 sv 网格的形状来看,我想说你可以使用 CGAL 的 Advancing Front Surface Reconstruction (example here) 从你的点集中获取你的网格,它们应该足够干净。 (我试过第一个,效果很好)。