从表面减去封闭网格(CGAL?)

Substract closed mesh from surface (CGAL?)

我有以下问题,最好用下图描述。

我有一个 3D 表面,因此它可以有垂直重叠并且是一个非闭合网格。我有一个要从中减去的对象。绿色+黄色区域是原始表面,红线勾勒出一个球体(作为三角网格,不是图元)。黄色区域是与需要从原始表面移除的球体相交的表面部分。绿色区域是减法的结果:需要的表面。

我已经在使用 CGAL 库,但仍然是新手,因此使用 CGAL 的解决方案将是首选。但是,如果有人有没有 CGAL 的解决方案,那也将受到欢迎。

我能看到的最好方法是给表面一个轻微的厚度(保持当前表面为底部)。然后用 Nef_polyhedron_3 减去另一个对象,然后转换为 Polyhedron_3 只保留底面。但这似乎有点 hack。


编辑: 使用建议的解决方案我非常接近,但我无法使用建议的反向法线裁剪到正确的一侧,使用以下代码。 我也试过看人脸顶点顺序(顺时针/逆时针)有没有效果,但是好像没有。

typedef CGAL::Simple_cartesian<double>                  SC;
typedef CGAL::Surface_mesh<SC::Point_3>                 SurfaceMesh;
typedef SurfaceMesh::Property_map<SM_fid, SC::Vector_3> SM_fnormals;
typedef SurfaceMesh::Vertex_index                       SM_vid;
typedef SurfaceMesh::Face_index                         SM_fid;

namespace PMP = CGAL::Polygon_mesh_processing;
namespace params = PMP::parameters;

void clip(SurfaceMesh P&, SurfaceMesh& Q) {        
    SM_fnormals fnormals = CGALobstacle->add_property_map<SM_fid, SC::Vector_3>
        ("f:normals", CGAL::NULL_VECTOR).first;

    PMP::compute_face_normals(Q, fnormals);

    PMP::clip(P, Q, false, params::all_default(), params::face_normal_map(fnormals));
}

Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/clip.h 中有一个从 CGAL 4.10 开始的未记录的函数。函数签名是:

/// requires face_index_map, vertex_index_map for np_tm
/// requires face_index_map for np_c
/// if edge_is_constrained_map is not provided in np_tm a default one is
/// provided using boost::unordered_set<edge_descriptor>
template <class TriangleMesh,
          class NamedParameters1,
          class NamedParameters2>
bool
clip(      TriangleMesh& tm,
 /*const*/ TriangleMesh& clipper,
           bool close,
     const NamedParameters1& np_tm,
     const NamedParameters2& np_c)

第二个参数是你的球体,第一个是你的表面。第三个表示您是否希望关闭输出表面(在您的情况下如此错误)。请注意,该函数正在裁剪,因此如果您想要球体的外部,则需要反转球体的方向(向内法线)。

有一个用法示例here

我建议使用 Surface_mesh 而不是 Polyhedron_3

请注意,该功能未记录在案,header 可能会在即将发布的版本中消失(如果确实存在,则意味着它已正式记录在案)。

EDIT:自 CGAL 4.13 以来官方记录的函数是 here