這篇文章將介紹計算幾何中一個基礎而重要的工具——叉積。
在這之前,我們先要解決一些基本問題。
點、線段的代碼表示
結合結構體或者類的知識,這里其實很好理解,但是在具體的編碼過程中怎么寫,這個根據個人有很大的靈活性。
比如對於點,就可以用如下的語句表達:
struct point
{
double x , y;
}
對於線段,可以用如下的語句表達:
struct line
{
point a , b ;
}
其實在這里無論是lrj的《訓練指南》還是具宗萬的《算法問題實戰策略》都會提到,在實際問題中我們用向量作為數據結構其實更加方便,這句話是一句總結性的話語,需要編程者隨着閱歷的增長才會有深刻的體會。
對於向量,有如下的表述語句:
struct vector
{
double x , y ;
}
叉積概念的引入
在平面中我們為了度量一條直線的傾斜狀態,為引入傾斜角這個概念。而通過在直角坐標系中建立tan α = k,我們實現了將幾何關系和代數關系的銜接,這其實也是用計算機解決幾何問題的一個核心,計算機做的是數值運算,因此你需要做的就是把幾何關系用代數關系表達出來。而在空間中,為了表示一個平面相對空間直角坐標系的傾斜程度,我們利用一個垂直該平面的法向量來度量(因為這轉化成了描述直線傾斜程度的問題)。
叉積的定義:
注意這里的θ是根據右手法則和叉乘的順序確定的,是具有一定的方向性,這種定義直接導致了叉乘在計算幾何問題上的廣泛應用。
通過這個定義式,我們馬上能夠很容易的得到如下的運算規律。

顯然這個定義式我們不怎么喜歡,因為它代數化程度還是太淺,主要就是由於角的正弦值我們不好找,但是這絲毫不影響這個定義式在應用當中的重要性,下面我們需要解決的問題就是,找到一個等價的代數化程度更高的定義式。
叉積的行列式公式(以二維為例):

其實在這里我們就能夠看到,如果說是用賦予方向性的線段(line)做向量進行叉乘,那么根據定義,我們編寫的cross函數中將會出現8個變量(感興趣的同學完全可以實現一下這個過程看看有多麻煩),這對編程者來說太過繁瑣,因此我們提倡將平面幾何中的線段用向量vector的形式表示出來。
之所以這么詳細的引出了叉乘的定義,是因為在后面它有着各類很重要的應用。
叉積的應用
一:求解三角形(平行四邊形)的面積.

那么在給出三角形三個點坐標的時候,我們就可以直接利用叉乘來計算三角形的面積,相對利用海倫公式求解,結果更加精確(減少了開根號的次數)。
我們基於這個結論可以推導出任意n邊形面積的計算公式。

這里需要充分理解上文給出的關於叉積定義的①式子,即嚴謹的來說,用叉乘算面積也是能夠算出負值的。在該圖中,我們這樣計算多邊形的面積:

二:點定位。
還是從上文給出的①式出發,我們通過代數式的勝負和夾角正弦值的對應關系來定性的描述向量之間的位置關系。

這種定性的描述,在之后計算幾何雜亂的算法中會頻繁出現,包括判斷線段是否相交、極角排序、凸包問題等等,因此這里一定要理解透徹。
