本文涉及知识点
预备知识
所谓凸多面体是指这样一类多面体------将其任意一个面扩展成平面,其他所有面都在该平面的同一侧。
泼德猜想指出,每个凸多面体都允许自无重叠展开 (Shephard 1975)
混合与凸组合
我们只关心产品的两类成分--不妨称之为A和B。假设混合物 ξ 1 , ξ 2 , ξ 3 \xi_1,\xi_2,\xi_3 ξ1,ξ2,ξ3。 ξ 1 \xi_1 ξ1中含有10%的A,35%的B; ξ 2 \xi_2 ξ2含有16%的A,20%的B; ξ 3 \xi_3 ξ3,含有7%的A、15%的B分成。将 ξ 1 , ξ 2 , ξ 3 \xi_1,\xi_2,\xi_3 ξ1,ξ2,ξ3按1:3:1比例混合,可得13%A,22%B成分的混合物。能否配置x%的A,y%的B呢?
我们把(0.1,0.35),(0.16,0.2),(0.07,0.15)看成平面上的点,本问题就变成二维凸组和。
混合物包含d种成分时,可"勾兑"出混合物对应于一个d维凸多胞胎。
碰撞检测
在计算机领域,凸包可以用来加速碰撞检测。任意给定两个物体 P 1 和 P 2 P_1和P_2 P1和P2,我们希望检测他们是否相交。如果大多数问题下是否定的,那们下面的方法很合算。将这两个物体分别近似为 P 1 ^ , P 2 ^ \hat{P_1},\hat{P_2} P1^,P2^,这两个物体包含了原来的物体,如果 P 1 ^ , P 2 ^ \hat{P_1},\hat{P_2} P1^,P2^不相交,则 P 1 , P 2 P_1,P_2 P1,P2一定不相交。如果 P 1 ^ , P 2 ^ \hat{P_1},\hat{P_2} P1^,P2^相交,则检测 P 1 , P 2 P_1,P_2 P1,P2。
P 1 ^ , P 2 ^ \hat{P_1},\hat{P_2} P1^,P2^的体积要尽快地小,判断相交要仅可能地简单。如:凸包,球。
三维凸包的复杂度
三维空间中,任意n个点组成的集合P,其凸包都是以个凸多胞体,而且改多胞体的顶点全部来自于P。
定理11.1 :设P为包含n个顶点的任一凸多胞体,则P中所含的边不会超过3n-6条,所含的小平面不会超过2n-4张。
任何凸多面体,都可以以某种方式展开成不平行的平面图。在与P对应的图中,每张面都至少三条弧围成;而且一张弧与两个面相关。也就 2 n e ≥ 3 n f 2n_e \ge 3n_f 2ne≥3nf带入欧拉公式:
n + n f − 2 ≥ 2 n f / 2 → n f ≤ 2 n − 4 n+n_f-2\ge 2n_f/2 \to n_f \le 2n-4 n+nf−2≥2nf/2→nf≤2n−4
根据欧拉公式替换 n f n_f nf
2 n e ≥ 3 ( n e + 2 − n ) → 0 ≥ n e + 6 − 3 n → n e ≤ 3 n − 6 2n_e \ge 3(n_e+2-n)\to 0 \ge n_e+6-3n \to n_e \le 3n-6 2ne≥3(ne+2−n)→0≥ne+6−3n→ne≤3n−6
所有的小平面都是三角形,即所谓单纯多胞体。在这种情况下,因为 2 n e = 3 n f 2n_e = 3n_f 2ne=3nf,所以上述关于边及小平面数目的上界都将成为确界。
构造三维凸包
递增式构造凸包的第一步:在P中选出不共面的四个点--这样,它们的凸包必是一个四面体。任取P中的两点 p 1 , p 2 p_1,p_2 p1,p2。然后,依次将集合P中的各点,与直线 p 1 p 2 p_1p_2 p1p2进行比较,直到出现一个落在该直线上的点 p 3 p_3 p3。接下来,继续将P中的各点,与 p 1 p 2 p 3 p_1p_2p_3 p1p2p3确定的平面进行比较,直到出现一个不落在该平面的 p 4 p_4 p4。如果找不到,说明共面,用平面凸包算法。
接下来,还要将其余各点的次序随机打乱,将他们排成 p 5 ⋯ , p n p_5\cdots ,p_n p5⋯,pn。我们将按这一随机的次序,逐一处理各点:在此过程中,还将动态地维护凸包。对于任何一个整数 r ≥ 1 r \ge 1 r≥1,令P_r: := {p_i,\cdots p_r}。该算法反复循环,没循环一次,都要将点 p r p_r pr加入到 P r − 1 的凸包中去 P_{r-1}的凸包中去 Pr−1的凸包中去。
可能出现在以下两种情况:一, p r 在 P r − 1 凸包中 p_r在P_{r-1}凸包中 pr在Pr−1凸包中。二,在凸包外。下面讨论凸包外。
站在点 p r p_r pr的位置,朝CH(P_{r-1})看去。能够看到 C H ( P r − 1 ) CH(P_{r-1}) CH(Pr−1)的某些小平面--这些小平面都在正面;另外一些小平面无法看到,它们都在背面。哪些可见的小平面组成了一个连通区域,称为 p r 在 C H ( P r − 1 ) p_r在CH(P_{r-1}) pr在CH(Pr−1)上的可见区域。这个区域是由 C H ( P r − 1 CH(P_{r-1} CH(Pr−1的某些边组成的一条封闭的折线围成,我们称这条折线为 p r 在 C H ( P r − 1 ) p_r在CH(P_{r-1}) pr在CH(Pr−1)上的地平线。正如可以从图11-6中看到的那样,如果以 p r p_r pr为中心将地平线投影到某平面上,得到的影像恰好是CH(P_{r-1})到同一平面的投影的边界。

可见是什么?考察 C H ( P r − 1 ) 上任一小平面 f 所在的那张平面 h f 。这张平面定义了两个闭的半空间 − − 根据 C H ( P r − 1 ) 的凸性,它必然完全包含于其中的某个闭半空间之中;如果一个点来自于 h f 另一侧的那个开空间,它就会与面 f 可见 CH(P_{r-1})上任一小平面f所在的那张平面h_f。这张平面定义了两个闭的半空间--根据CH(P_{r-1})的凸性,它必然完全包含于其中的某个闭半空间之中;如果一个点来自于h_f另一侧的那个开空间,它就会与面f可见 CH(Pr−1)上任一小平面f所在的那张平面hf。这张平面定义了两个闭的半空间−−根据CH(Pr−1)的凸性,它必然完全包含于其中的某个闭半空间之中;如果一个点来自于hf另一侧的那个开空间,它就会与面f可见

在将CH(P_{r-1})转化到CH( P r P_r Pr)的过程中, p r p_r pr的地平线扮演了一个重要的角色。需要保留的是不可见的面,不需要保留的是可见的面。
我们可以用双向链接边表(double connected edge list)来存储凸包。唯一不同之处在于,这里的顶点都是三维的点。这里仍将遵守原先的习惯--若从多胞体的外部看去,沿着每一张面的边界,所有的半边都构成一个逆时针的环路。
性质一 : r 1 < r 2 则 C H ( P r 1 ⊂ C H ( P r 2 ) r_1<r_2则CH(P_{r_1} \sub CH(P_{r_2}) r1<r2则CH(Pr1⊂CH(Pr2)。
性质二 :如果小面f 同时是 C H ( P r 1 ⊂ C H ( P r 2 ) CH(P_{r_1} \sub CH(P_{r_2}) CH(Pr1⊂CH(Pr2)的面,则方向不变,指向CH(P_{r_1} 任意一点。
性质三 :如果一个对地平行线所有的面都不可见(红色多面体),则对新增加的的面对不可见(绿色多面体)。


分析
性质四::算法总共生成的三角面数目的期望值不超过6n-20。

扩展阅读
| 算法为骨,CAD为魂 |
|---|
| 请通过博文下载学院导航 |
| 经典文章推荐:C++BFS算法 |
| 活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。
