提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
1 介绍
对于非凸多面体的许多应用,有一个有效的解决方案,首先将多面体分解为凸块。例如,两个多面体的闵可夫斯基和可以通过将两个多面体分解为凸块,计算凸块的成对闵可夫斯基和,并合并成对和来计算。
虽然我们希望分解为最少数量的片段,但这个问题已知是NP-hard[1]。我们的实现将一个Nef多面体N分解为O(r2)个凸块,其中r是具有两个相邻切面的边的数量,这些相邻切面与多面体内部的夹角大于180度。这些边也被称为反射边。O(r2)个凸块的界为最差情况最优[1]。
基于垂直切面插入的垂直分解(从顶部查看)。左:非凸多面体。中:非垂直反射边缘已被解决。右图:垂直反射边缘已经被解决了。子体是凸的。
我们的分解分为两步。在第一步中,每个非垂直反射边e通过插入垂直facet e来解决。在第二步中,我们对垂直反射边做同样的处理。图中说明了这两个步骤。目前实现仅限于有界多面体的分解。
2 接口使用
Nef_polyhedron_3实例表示将三维空间细分为顶点、边、面和体。其中一些项形成多面体(已选),而另一些项表示多面体内的外部体积或孔(未选)。例如,单位立方体是点集[0,1]3。表示单位立方体的最小细分有8个顶点、12条边、6个面和2个体。由顶点、边和面包围的体积是立方体的内部,因此被选中。多维数据集外的卷不属于它,因此未被选择。顶点、边和面(也表示为边界项)用于分隔两个卷,但对于表示拓扑属性也很有用。对于(封闭的)单位立方体,边界项是多面体的一部分,因此被选中,但对于开放的单位立方体[0,1)3,它们不被选中。每个项目都有自己的选择标记,这允许正确表示Nef多面体,这些多面体在布尔和拓扑操作下关闭。
通常,Nef_polyhedron_3实例不包含任何冗余项。然而,函数convex_decomposition_3()将给定Nef_polyhedron_3的选定体细分为选定的facet。因此,这些额外的facet是多余的,也就是说,它们的插入改变了多面体的表示,而不是多面体本身。
当convex_decomposition_3()解析所有反射边时,所选的子体已成为凸体。它们中的每一个都由一个单独的体表示,因此可以分别遍历,如分解shell部分所述。访问凸块的另一种可能性是将它们转换为单独的Nef多面体,如下面的示例代码所示。
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>
#include <CGAL/convex_decomposition_3.h>
#include <list>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3;
typedef CGAL::Nef_polyhedron_3<Kernel, CGAL::SNC_indexed_items> Nef_polyhedron_3;
typedef Nef_polyhedron_3::Volume_const_iterator Volume_const_iterator;
int main() {
Nef_polyhedron_3 N;
std::cin >> N;
CGAL::convex_decomposition_3(N);
std::list<Polyhedron_3> convex_parts;
// the first volume is the outer volume, which is
// ignored in the decomposition
Volume_const_iterator ci = ++N.volumes_begin();
for( ; ci != N.volumes_end(); ++ci) {
if(ci->mark()) {
Polyhedron_3 P;
N.convert_inner_shell_to_polyhedron(ci->shells_begin(), P);
convex_parts.push_back(P);
}
}
std::cout << "decomposition into " << convex_parts.size() << " convex parts " << std::endl;
}