Extreme Points
策略 Strategy
- 问题的转化
- 如果一个多边形是凸包,那么当且仅当他的所有顶点( v e r t e x vertex vertex)都是极点;
- 问题就转化为甄别极点,那么如何甄别极点呢?
In-Trangle Test
,如果成立,则不是极点!
In-Triangle Test
- 无罪推论
- 首先假设所有的点都是极点;
- 然后暴力枚举出所有可能的三角形:
- 逐一判断除这三个点以外的所有极点,如果通过了
In-Triangle Test
,则标注为非极点。
- 逐一判断除这三个点以外的所有极点,如果通过了
To-Left Test
-
实现
In-Triangle Test
将
In-Triangle Test
转化为三次To-Left Test
:- 对于一个点,如果位于三角形内,那么对于三条边的的
To-Left Test
都会统一的返回True
或者False
!
- 对于一个点,如果位于三角形内,那么对于三条边的的
-
7 7 7 与 8 8 8 的问题
使用三刀最多切出 7 7 7 块蛋糕,但是对于三条直线,每一条直线的
To-Left Test
的结果都存在True
和False
两种情况,那么就会有 2 3 = 8 2^3 = 8 23=8 种情况,少的去哪里了?- 实际上对于三条边来说,当三者的
To-Left Test
的结果都是False
时,他们划分出的区域没有交集,如下图紫色标记区域:
- 实际上对于三条边来说,当三者的
使用行列式计算有向面积
-
实现
To-Left Test
-
在已知三角形边长时可以利用海伦公式计算三角形面积:
S = ( p ( p − a ) ( p − b ) ( p − c ) ) S = \sqrt{(p(p-a)(p-b)(p-c))} S=(p(p−a)(p−b)(p−c)) -
而已知三个点的二维坐标时,可以利用行列式计算三角形的有向面积,而根据有向面积的符号可以判断出是在左还是在右;
-
实际上这种方法的好处是,避免了三角函数和除法,而这两种计算会引入浮点数,降低计算的精度。
-
-
另外一种做法
-
实际上使用向量的叉乘也能实现
To-Left Test
,当
a ⃗ × b ⃗ > 0 , ( a ⃗ = p q ⃗ , b ⃗ = p s ⃗ ) \vec{a} \times \vec{b} > 0 , \ (\vec{a} = \vec{pq}, \vec{b} = \vec{ps}) a×b>0, (a=pq,b=ps)
时,结果为True
! -
三维向量叉乘的公式:
-
对于二维的向量,则更加直观:
a ⃗ × b ⃗ = ∣ a ⃗ ∣ ∣ b ⃗ ∣ s i n θ = x 1 y 2 − y 1 x 2 \vec{a} \times \vec{b} = |\vec{a}||\vec{b}|sin\theta =x_1y_2 - y_1x_2 a×b=∣a∣∣b∣sinθ=x1y2−y1x2-
此时没有第三维
z
,计算结果的正负即可表明 a ⃗ \vec{a} a 与 b ⃗ \vec{b} b 是否满足夹角 θ \theta θ 小于 π \pi π,即s
是否在pq
左边; -
而且实质上,两种方法是等效的,因为二维向量的叉乘等于所构成的平行四边形的有向面积,即三角形的有向面积的两倍:
带入化简,得到的形式与行列式的做法是一致的:
-
-
-
总结
To-Left-Test
可以有两种实现方法,当已知向量时可以直接使用叉乘,而如果只给出了点的坐标,则可使用行列式。
Reference
计算几何 - 邓俊辉