【问题标题】:Subtracting multiple polyhedra continuously from a polyhedron从多面体中连续减去多个多面体
【发布时间】:2021-08-20 09:40:49
【问题描述】:

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

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

我用 CGAL 库解决这个问题的方法: 实际上,只有 A 是 2 流形,Bi 都是有边界的 3 维曲面。为了使用 CGAL 库的“Nef Polyhedron 上的 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 文件。下载链接:blank.off and sv.off

程序运行时出现的问题

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

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

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

【问题讨论】:

  • 我使用提供的文件尝试了您的代码,但没有重现上述两个错误中的任何一个。您是否尝试过调试或发布模式?您使用的是什么版本的 CGAL?关于您关于三角测量点集的问题,答案是肯定的。您应该查看文档中的形状重建包:doc.cgal.org/latest/Manual/packages.html
  • 感谢您的回复。程序在Release模式下运行,我没有在Debug模式下尝试。我使用的 CGAL 版本是 5.2.2-I-900。

标签: cgal boolean-operations


【解决方案1】:

在对您的输入进行了一些尝试之后,我可以说导致您所有问题的最合理的原因是您的输入不是很干净。如果您设法从 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) 从您的点集中获取网格,它们应该足够干净。 (我试过第一个,效果很好)。

【讨论】:

  • 询问后不久,我找到了Polygon Mesh Processing 包,并意识到使用Surface_mesh 进行布尔运算实际上是一个更好的选择。我的网格不干净,因为我写的三角测量程序有一些漏洞。我寻找三角测量包但找不到它。我会试试你建议的包。非常感谢您回答我的问题。
  • 我注意到随着计算的进行,网格变得更加复杂,这会减慢以后的布尔运算。是否有简化网格的功能?
  • 你可以看看doc.cgal.org/latest/Surface_mesh_simplification/index.html 但我不确定简化网格是否会比不简化的corefining快得多。
猜你喜欢
  • 2019-09-05
  • 1970-01-01
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2014-03-10
相关资源
最近更新 更多