幾何與代數演算法

方向測試(orientation / CCW test)

站在 A 點,走到 B 點,然後問:要走到第三個點 C,我該左轉、右轉,還是直走?這個「往哪轉」的簡單問題,正是計算幾何(computational geometry)的主力工具。幾乎每個幾何演算法——判斷兩線段是否相交、建立凸包、把點繞著中心排序——最後都歸結為反覆問這個轉向問題。方向測試只用一條極小的算術公式就能回答,而且關鍵在於不用除法、不用開平方根,因此能在整數座標上精確計算,毫無捨入誤差。

這條公式就是叉積(cross product)。給定 A = (ax, ay)、B = (bx, by)、C = (cx, cy),計算帶符號量 d = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)。若 d > 0,三點構成逆時針(左轉);若 d < 0,構成順時針(右轉);若 d = 0,三點共線(落在同一條直線上)。為什麼成立?因為 d 恰好是三角形 ABC 帶符號面積的兩倍。帶符號面積為正,表示 C 落在從 A 通過 B 的有向直線左側;為負落在右側;為零則三角形是扁的,也就是三點共線。於是同一個「相減再相乘」的模式,一次就告訴你面積、轉向,以及一個點落在某直線的哪一側。

這個測試之所以重要,是因為它是更大演算法反覆呼叫數千次的原子操作,而且用不到除法就能保持精確。輸入為整數時,每個中間值都是整數,因此 d = 0 能可靠地偵測真正的共線,而不是浮點捨入造成的「差一點點」——後者正是幾何程式中惡名昭彰的錯誤來源。一個誠實的提醒:乘積可能很大(大約是座標量級的平方),所以在定寬整數上務必小心溢位,並選用夠寬的整數型別。

A = (0,0)、B = (4,0)、C = (2,3)。d = (4-0)*(3-0) - (0-0)*(2-0) = 12 - 0 = 12 > 0,故 A、B、C 逆時針(C 在直線 AB 上方)。把 C 移到 (2,-3):d = (4)*(-3) - 0 = -12 < 0,順時針。把 C 放到線上 (2,0):d = (4)*(0) - 0 = 0,三點共線。

一個叉積就給出轉向(以及兩倍帶符號三角形面積),完全不用除法。

你通常要的是叉積的正負號而非大小;但其大小可能讓定寬整數溢位,所以整數型別要能容納座標的平方。

又称
CCW testcross-product testleft-turn test叉積測試左轉測試逆時針測試