根据 libigl 教程:
Libigl 在内部使用精确算术来稳健地构造中间布尔结果。如果将该结果“四舍五入”为浮点数(甚至是双精度),如果重新注入到进一步的布尔运算中会导致问题。为了方便 CSG 树操作并鼓励调用者不要显式多次调用 igl::copyleft::cgal::mesh_boolean,libigl 实现了一个类 igl::copyleft::cgal::CSGTree。
简单来说 - 您可以使用 mesh_boolean 函数构造 CSG 网格,但在这种情况下,您必须明确注意中间计算的稳健性。 CSGTree 类会自动为您执行此操作,因为它使用 CGAL 精确算法进行所有带有坐标的中间计算。 CSGTree 类的另一个好处 - 只需一行代码即可构建多级 CSG 树。下面的示例展示了如何从两个网格构造一个最简单的 CSG 树并将其可视化:
#include <Eigen/Dense>
#include <igl/copyleft/cgal/CSGTree.h>
#include <igl/opengl/glfw/Viewer.h>
#include <igl/read_triangle_mesh.h>
int main()
{
// ------ load mesh #1
Eigen::MatrixXd V1;
Eigen::MatrixXi F1;
igl::read_triangle_mesh("data/sphere.obj", V1, F1);
// ------ load mesh #2
Eigen::MatrixXd V2;
Eigen::MatrixXi F2;
igl::read_triangle_mesh("data/xcylinder.obj", V2, F2);
// ------ combine meshes #1 and #2
const igl::copyleft::cgal::CSGTree t{{V1, F1}, {V2, F2}, "union"};
// ------ plot the combined mesh
const auto V = t.cast_V<Eigen::MatrixXd>();
const auto F = t.F();
igl::opengl::glfw::Viewer viewer;
viewer.data().set_mesh(V, F);
viewer.launch();
}
这样的单行构造是可能的,因为CSGTree 具有以下构造函数(除其他外):
CSGTree(const CSGTree & A, const CSGTree & B, const MeshBooleanType & type)
正如您在上面看到的 - 如果有必要 - 例如,为了可视化,可以通过 cast_V 模板函数将生成的坐标数组转换为双精度数组。这个可视化的结果如下: