计算几何--算法与应用 邓俊辉译(第三版) 第一章 凸包与导言
本文涉及知识点
预备知识
矢量 u ⃗ , v ⃗ \vec u,\vec v u,v,如果u逆时针旋转不超过180 ∘ ^\circ ∘能够和v重合,则称v在u的逆时针平面。俗称左侧(u是竖直向上的向量)。逆时针旋转也称左拐。下侧是不规范的说法,尽量不使用。
点P和线段 A B ⃗ \vec{AB} AB的位置关系
double cross=
A
B
⃗
×
A
P
⃗
\vec{AB}\times \vec{AP}
AB×AP
cross>0,P在AB左侧;cross=0,P在AB上;cross<0,P在AB右侧。

ABC排序
以横坐标升序为第一关键字,纵坐标降序为第二关键字对点ABC排序。
预备知识一:如果B的纵坐标小于AC,则BC在AB的逆时针半平面或共线。
情况一:A.x < B.x < C.x。红角锐角,蓝角锐角。,故AB逆时针旋转不到180
∘
^\circ
∘可以和BC重合。

情况二:A.x=B.x<C.x。红角直角,蓝角锐角。
情况三:A.x<B.x=C.x。红角锐角,蓝角直角。
情况三:A.x=B.x=C.y。共线。
预备知识二:B的纵坐标小于等于AC也符合上述性质。
预备知识三:平移所有所有点
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0)所有向量不变,令
A
(
x
1
,
y
1
)
,
B
(
x
2
,
y
2
)
,
移动前
A
B
⃗
=
(
x
2
−
x
1
,
y
2
−
y
1
)
A(x_1,y_1),B(x_2,y_2),移动前\vec{AB}=(x_2-x_1,y_2-y_1)
A(x1,y1),B(x2,y2),移动前AB=(x2−x1,y2−y1),移动后也是。
预备知识四:以原小为旋转为中心,旋转所有点
θ
\theta
θ,所有的向量也旋转
θ
\theta
θ。
旋转公式
{
x
′
=
x
cos
θ
−
y
sin
θ
y
′
=
x
sin
θ
+
y
cos
θ
旋转公式\begin{cases} x'=x\cos\theta-y\sin\theta \\ y'=x\sin\theta+y\cos\theta \\ \end{cases}
旋转公式{x′=xcosθ−ysinθy′=xsinθ+ycosθ
令
A
(
x
1
,
y
1
)
,
B
(
x
2
,
y
2
)
,移动后
A
B
⃗
A(x_1,y_1),B(x_2,y_2),移动后\vec{AB}
A(x1,y1),B(x2,y2),移动后AB,
{
Δ
x
′
=
x
2
′
−
x
1
′
=
(
x
2
−
x
1
)
cos
θ
−
(
y
2
−
y
1
)
sin
θ
=
Δ
y
cos
θ
−
Δ
x
sin
θ
Δ
y
′
=
y
2
′
−
y
1
′
=
(
x
2
−
x
1
)
sin
θ
+
(
y
2
−
y
1
)
cos
θ
=
Δ
y
cos
θ
+
Δ
y
cos
θ
\begin{cases} \Delta x'=x_2'-x_1'= (x_2-x_1)\cos\theta-(y_2-y1)\sin\theta=\Delta y\cos\theta-\Delta x\sin \theta \\ \Delta y'=y_2'-y_1'=(x_2-x_1)\sin\theta+(y_2-y_1)\cos\theta = \Delta y \cos\theta + \Delta y \cos\theta \end{cases}
{Δx′=x2′−x1′=(x2−x1)cosθ−(y2−y1)sinθ=Δycosθ−ΔxsinθΔy′=y2′−y1′=(x2−x1)sinθ+(y2−y1)cosθ=Δycosθ+Δycosθ
即将向量旋转
θ
\theta
θ
用线性代数证明,更简洁。令R是旋转矩阵,则:
BR-AR=(B-A)R
预备知识四:A,B,C是平面上的点,BC在AB的顺时针(逆时针)半平面,则AC在AB的顺时针(逆时针)半平面。
A
B
⃗
×
A
C
⃗
=
A
B
⃗
×
(
A
B
⃗
+
B
C
⃗
)
=
A
B
⃗
×
A
B
⃗
+
A
B
⃗
×
B
C
⃗
=
A
B
⃗
B
C
⃗
\vec{AB}\times\vec{AC}=\vec{AB}\times{(\vec{AB}+\vec{BC}})=\vec{AB}\times\vec{AB}+\vec{AB}\times\vec{BC}=\vec{AB}\vec{BC}
AB×AC=AB×(AB+BC)=AB×AB+AB×BC=ABBC即两者叉乘相等。
预备知识五:R是凸多边形P和Q的交集,则R是凸多边形。
∀
p
,
q
∈
R
,
r
∈
p
q
,
根据凸多边形的定义,
r
∈
P
,
r
∈
Q
→
r
∈
R
\forall p,q\in R,r \in pq,根据凸多边形的定义,r \in P,r \in Q \to r \in R
∀p,q∈R,r∈pq,根据凸多边形的定义,r∈P,r∈Q→r∈R
引言
某张地图,将校园划分成若干区域,同一个区域最近的电话机相同。就是的Voronoi图(Voronoi diagram,沃罗诺伊图)。
给定一组几何形状不同的障碍物,我们需要在不与任何障碍物发生碰撞的前提下,找出联结任意两点的最短路。这就是运动规划(motion planning),这在机器人学中至关重要的问题。
两张地图:一张描述各个建筑物,包括公用电话;另一张则画出校园内的道路。为了规划出通往公用电话的运动路径,我们需要将这两张地图叠合起来。
这一学科可定义为“针对处理几何对象的算法及数据结构的系统化研究”,其重点在于“渐进快速的精确算法”。
《计算几何》主要应用领域:机器人学、计算机图形学、CAD/CAM以及地理信息系统。
1 凸包的例子
凸多边形(convex polygon)凸包 Convex hull
对具有几何本质的算法问题,我的采用的解决方法大多需要具备两方面的要素:一是对该问题的几何特性的深刻理解,二是算法和数据结构的合理应用。
平面的一个子集S称为是“凸”的,当且仅当任意两点p,q
∈
S
\in S
∈S,线段
p
q
‾
\overline{pq}
pq都完全属于S。集合S的凸包CH(S)就是包含S的最小凸集–更确切地说,它是所有包含S的所有凸集的交。
给定平面点集
P
=
p
2
,
⋯
p
n
P={p_2,\cdots p_n}
P=p2,⋯pn,通过计算从P中选出若干点,它们沿顺时针方向依次对应与CH§的各顶点。
输入=平面上的一组点:
p
1
,
p
2
,
p
3
,
p
4
,
p
5
,
p
6
,
p
7
,
p
8
,
p
9
p_1,p_2,p_3,p_4,p_5,p_6,p_7,p_8,p_9
p1,p2,p3,p4,p5,p6,p7,p8,p9
输出=凸包的表示
p
4
,
p
5
,
p
8
,
p
2
,
p
9
p_4,p_5,p_8,p_2,p_9
p4,p5,p8,p2,p9
性质一:相对于CH§边界上任意一边所在直线,P中所有的点均居于同侧。 
性质二:
p
,
q
∈
P
,
p
≠
q
p,q \in P,p \neq q
p,q∈P,p=q。如果所有点都在
p
q
‾
\overline{pq}
pq同侧,则
p
q
‾
\overline{pq}
pq是凸包的边界。
不严格的证明:
p
q
‾
不是边界
→
存在
r
∈
p
q
‾
是凸包内一点,两个方向延长
p
q
,将凸包分成两个凸多边形
H
1
,
H
2
,
\overline{pq}不是边界 \to 存在r \in \overline{pq}是凸包内一点,两个方向延长pq,将凸包分成两个凸多边形H1,H2,
pq不是边界→存在r∈pq是凸包内一点,两个方向延长pq,将凸包分成两个凸多边形H1,H2,
r
沿
p
q
法线方向移动无尽小,得到的点是
s
;
r
沿
p
q
法线反方向移动无穷小,得到
t
。显然
s
,
t
分属于
H
1
,
H
2
r沿pq法线方向移动无尽小,得到的点是s;r沿pq法线反方向移动无穷小,得到t。显然s,t分属于H1,H2
r沿pq法线方向移动无尽小,得到的点是s;r沿pq法线反方向移动无穷小,得到t。显然s,t分属于H1,H2。
H
1
,
H
2
非空
→
除直线
p
q
外,两侧都有点
H1,H2非空 \to 除直线pq外,两侧都有点
H1,H2非空→除直线pq外,两侧都有点。
小结:
p
,
q
∈
P
,
p
≠
q
p,q \in P,p \neq q
p,q∈P,p=q。如果所有点都在
p
q
‾
\overline{pq}
pq同侧
⟺
\iff
⟺ pq是凸包的边界。
证明:
引理一:P凸包的顶点
∈
P
\in P
∈P。
如果所有的其它点都在pq左侧,则交换pq,这样所有的点都在新pq的右侧。根据凸多边形的定义,所有pq所在直线的半平面交际就是凸多边形。故所有点都在pq组成的凸多边形内。
凸包一定包括pq,否则q点在多边形外。pq所在直线将凸包分成H1,H2。根据引理一,H1,H2中的一个退化成直线,即pq就是边界。
暴力算法
时间O(n^3)的凸包算法,三层循环。第一层枚举p,第二层枚举q,第三层循环枚举其它点。合法的pq首尾相连就是凸包点的逆时针序。
处理三点共线:
r
∈
P
,
r
≠
p
,
r
≠
q
r \in P,r\neq p,r\neq q
r∈P,r=p,r=q都是以下情况之一则pq是凸包的边:
一,r在pq 右则。
二,r在线段pq上。
一般情况下都用浮点数实现,故有舍入误差。下图pqr几乎共线,其他点都距离此三点较远。在误差的作用下,以下两种情况都有可能发生。一,所有点都在pr、pq、rq的右则。即这些边都是凸包的边,这显然是错误的。

二,r在qp左侧,p在rq左侧,q在pr侧。即这三条边都不是凸包的边,这显然是错误的。

Andrew 算法 (Andrew’s algorithm)单调链算法 (Monotone Chain algorithm)
p
1
到
p
n
以
x
为第一关键字
,
y
为第二关键字排序
p_1到p_n以x为第一关键字,y为第二关键字排序
p1到pn以x为第一关键字,y为第二关键字排序,即字典序排序。
性质三:p1一定是凸包的顶点。
用反正法证明。令凸包的点集是
Q
=
q
1
,
q
2
⋯
q
k
,
p
1
∉
Q
Q={q_1,q_2\cdots q_k},p1 \notin Q
Q=q1,q2⋯qk,p1∈/Q。
则p1的凸组合为:
=
∑
i
=
1
k
λ
i
q
i
=
p
1
+
∑
i
=
1
k
λ
i
v
i
,
v
i
=
q
i
−
p
1
=\sum\limits_{i=1}^k\lambda_i q_i=p_1+\sum\limits_{i=1}^k\lambda_iv_i,v_i=q_i-p_1
=i=1∑kλiqi=p1+i=1∑kλivi,vi=qi−p1
由于p1的x最小,古
v
i
.
x
≥
0
v_i.x \ge 0
vi.x≥0 要想让左右式子的x相等,则
λ
i
或
v
i
.
x
\lambda_i或v_i.x
λi或vi.x必定一个为0。即
p
1
的任意凸组合,只包括横坐标和
p
1.
x
相同的点,而这些点的
y
>
p
1.
y
,故无法让左右式的
y
相等
p_1的任意凸组合,只包括横坐标和p1.x相同的点,而这些点的y>p1.y,故无法让左右式的y相等
p1的任意凸组合,只包括横坐标和p1.x相同的点,而这些点的y>p1.y,故无法让左右式的y相等。
同理
p
n
p_n
pn也一定是凸包的顶点。
求上凸包的过程
将p1加到L中。
将p2加到L中。
for( i =3 to n)
{
当 L的点数大于等于2 且
p
i
不在
L
最后两个元素的右侧
p_i不在L最后两个元素的右侧
pi不在L最后两个元素的右侧,则L.pop_back()。 当表示循环
p
n
p_n
pn加到L中。
}
L记录
p
1
到
p
n
p_1到p_n
p1到pn的上凸包。
线段
p
1
p
n
将凸包拆分上凸包和下凸包
线段p_1p_n将凸包拆分上凸包和下凸包
线段p1pn将凸包拆分上凸包和下凸包。
A
=
p
i
,
B
=
p
j
,
C
=
p
k
,
i
<
j
<
k
A=p_i,B=p_j,C=p_k,i < j < k
A=pi,B=pj,C=pk,i<j<k AC在上凸包,B在下凸包。
上凸包证明
令p的上凸包是q,共有m个点, q 1 = p 1 , q m = p n q_1=p_1,q_m=p_n q1=p1,qm=pn。上述代码处理完 p i p_i piL就是p的上凸包。
在
q
1
∼
q
m
q_1\sim q_m
q1∼qm中依次增加
A
(
q
m
.
x
,
负无穷大
)
,
B
(
q
1
.
x
,
负无穷大
)
A(q_m.x,负无穷大),B(q_1.x,负无穷大)
A(qm.x,负无穷大),B(q1.x,负无穷大)形成的凸多变形L’,已经处理的点都在L’中。
证明一:L’是凸多边形。
∠
q
1
B
A
=
∠
q
m
A
B
=
90
∘
。由于已经字典序排序,故以
q
1
为原点,
q
2
在第一四象限,故
q
1
的内角
<
180
∘
,同理
q
m
的内积也
<
180
∘
\angle q_1BA=\angle q_mAB=90^\circ。由于已经字典序排序,故以q_1为原点,q2在第一四象限,故q_1的内角<180^\circ,同理q_m的内积也<180^\circ
∠q1BA=∠qmAB=90∘。由于已经字典序排序,故以q1为原点,q2在第一四象限,故q1的内角<180∘,同理qm的内积也<180∘

证明二;
p
i
p_i
pi淘汰一个点后,所有点都在新L’内部。因为新L’增加一个三角形和一个梯形,没有减少区域。

证明三:不删除只增加 p i p_i pi,所有点都在新L’中。以为新L’只增加区域,没有减少区域。

总结:L’只会增加区域,不会减少区域,故包括所有点。
下凸包过程
在D中增加
p
n
p_n
pn
在D中增加
p
n
−
1
p_{n-1}
pn−1
for( i = n-2 to 1)
{
当 D中有两个元素,且
p
i
p_i
pi不在D最后两个元素的右则,D.pop_back()。
在D中增加p_i
}
D‘=D,在D’中增加
(
D
.
b
a
c
k
(
)
.
x
,
无穷大
)
,
(
D
1.
x
,
无穷大
)
(D.back().x,无穷大),(D1.x,无穷大)
(D.back().x,无穷大),(D1.x,无穷大)
类似上凸包,D’包括所有的点,所有点都在
D
i
D
i
+
1
D_iD_{i+1}
DiDi+1右则。
合并
H = L’和D’的交集,故H包括所有点,且是凸多边形。
H就是L和D的并集。H中的边都是凸包的边。
D去掉第一个元素和最后的元素,L+D 便是凸包节点的顺时针序。
特殊情况处理
上述算法已经考虑x相同。
三点共线不是右拐,也弹出(淘汰)。
三点构成右拐,但因为误差的原因变成左拐。计算结果比实际结果少一个顶点。
三点构成左拐,但因为误差的原因变成右拐,计算结果比结果多一个顶点,不在是凸多边形。解决方法:将靠近的顶点合并成一个顶点。
左拐(右拐)误判成右拐(左拐)往往是三个点比较接近,故误差不大。
退化及鲁棒性
一个几何算法的建立过程,往往经过三个阶段。
一,理解我们正在处理的几何概念。尽量忽略无关问题。
二,对算法进行调整,使之能正确处理退化情况。
三,具体实现。最典型问题“对实数进行精确运算”不现实,往往归结为鲁棒性问题。一,转成整数运算,支持精确运算的软件包。往往牺牲性能。二,调整算法,提前检测不一致的情况,仅仅避免程序不崩溃或无响应。无法保证结果正确。
主要应用领域
一,计算机图形学。
二,机器人学。
三,地理信息系统。
四,CAD/CAM。
扩展阅读
| 算法为骨,CAD为魂 |
|---|
| 亲士工具箱:支持中望CAD2024、AutoCad2013及以上,多年承接CAD项目的精华 |
| 工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
| 学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
| 活到老,学到老。明朝中后期,大约50%的进士能当上堂官(副部及更高);能当上堂官的举人只有十余人。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)