叉積 線段相交判斷 凸包

2022-05-30 04:03:13 字數 2471 閱讀 1530

一、叉積

叉積的計算是線段方法的核心。對於向量p1和p2,叉積是由點(0,0)、p1、p2和p1+p2構成的平行四邊形的有向面積。另一種與之等價但更有效的的叉積定義方式是將其看做矩陣行列式:

p1×p2 = x1y2 - x2y1 = - p2×p1

若p1×p2為正,則相對於原點(0,0)來說,p1位於p2順時針方向;若p1×p2為負,p1位於p2逆時針方向;若為0則方向相同,或相反。

若是相對於點p0(x0,y0)而非原點,則p0p1p0p2的叉積為(p1-p0)×(p2-p0) = (x1-x0)(y2-y0)-(x2-x0)(y1-y0)。

確定連續線段是向左轉還是向右轉

對於線段p0p1和p1p2,採用叉積可以避免計算角度,只需簡單的計算一下p0p2是位於p0p1的順時針還是逆時針方向。計算叉積

(p2-p0)×(p1-p0) = (x2-x0)(y1-y0) - (x1-x0)(y2-y0)

若結果為負,p0p2p0p1的逆時針方向,在p1處左轉;結果為正則右轉;為0表示三點共線。

判斷兩條線段是否相交

要判斷兩條線段是否相交,則需要檢查每條線段是否跨越了另一條線段的直線。如果點p1位於某直線的一邊,而點p2位於該直線的另一邊,則稱p1p2跨越了這條直線。兩條線段相交,當且僅當下面兩個條件至少成立乙個:

每條線段都跨越了包含另一條線段的直線

一條線段的乙個端點落在另一條線段上

二、確定任意一對線段是否相交

給定乙個線段的集合,僅僅判斷是否有兩個線段相交,不必輸出所有相交的線段對。此處我們假設,線段均不垂直。

我們使用「掃除」演算法來解決這個問題。在掃除過程中,一條假想的掃除線穿過乙個給定的幾何物體集合,會與集合中的部分線段相交。下圖中掃除線r與線段a、c相交,且與a的交點的y座標值大於c的,則認為此處a>c。

在圖(a)中,在r處,a>c;在t處,a還是》c,那麼我們認為a和c沒有相交。而在圖(b)中,在v處,e>f,而在圖w處,f>e,故e和f相交。

上圖描述了乙個演算法,我們按照線段端點的x座標,從小到達,進行「掃除」。當在乙個線段的左端點掃除時,將所有相交的線段序列按序放入乙個「完全前序關係t」中。當掃到線段的右端點時,從t中去除該線段。但是,如果位於在該線段上方的線段集合,與位於該線段下方的線段集合有交集,則表明有線段相交。

關鍵在於,如果儲存t,如果求交集。可以用紅黑樹來儲存t。

演算法步驟

1. 初始化t為空集

2. 對線段的端點排序

3. 在端點p處,開始掃除,從最左邊的處開始

如果p是線段s的左端點

insert(t, s);

如果有線段在掃除線處相交

return true;

如果p是線段的右端點

如果above(t, s) 和 below(t, s)有交集,則

無交集則,delete(t, s);

4. return false

三、尋找凸包

點集q的凸包,是乙個最小的凸多邊形p,滿足q中的每個點都在p的邊界上,或者在p的內部。

graham掃瞄法: 複雜度o(nlogn)

選取y最小的點,多個y最小的話,選取其中x最小的點,作為p0

剩餘的點,按照p0和pi的極角的逆時針排序,編號為p1,p2,...,pm

如果m小於2,表示點數小於3,形不成多邊形

設定以空棧s,將p0、p1、p2壓入棧中。

for i=3 to m

得到棧頂的2個點pi-1和pi-2,如果t1t0t0pi轉的時候,不是左轉,就把頂點t0出棧;

如果出棧了t0,就繼續a,直到棧的頂點不再出棧位置

將pi入棧

return s

圖中,從a到f是一步一步選擇的過程。

jarvis步進法:複雜度o(nh),h是凸包頂點數

先找到最下邊結點裡最左邊的點p0,然後尋找使得p0p1極角最小的點,則p1也是凸包頂點;繼續尋找使得p1p2極角最小的點,直到達到最高點pk,上圖是p3,此時已經構造好了ch(q)的右鏈。為了構造左鏈,尋找pk+1使得pkpk+1極角最小,但此時x軸啊原x軸的負方向。

**自:

叉積,點積,線段相交

本身比較菜,就暫時只能參考別人的總結。這個知識點就是對大學裡高等數學中幾何知識的計算機應用。c 實現。1.1簡單的幾何問題。1.2 點積。1.3 叉積 以上部分問題的 實現不再多說,只需要回顧大學高等數學課本知識即可。上述知識參考 演算法競賽入門經典訓練指南 include include incl...

叉積判斷線段 直線相交 POJ3304

給你n個線段的兩端座標 問是否存在一條直線 所有線段在這條直線上的投影有共同點 存在一條直線 所有線段在這條直線上的投影有共同點 有一條線能穿過所有線段 這兩條直線剛好 暴力列舉所有端點 直線與線段相交 叉積 判斷一次就夠啦 線段與線段相交 twice include include include...

poj3304(叉積判斷直線和線段相交)

題意 求是否能找到一條直線,使得n條線段在該直線的投影有公共點。思路 如果存在這樣的直線,那麼在公共投影點作直線的垂線,顯然該垂線會經過所有直線,那麼原題轉換為求是否有經過所有線段的直線。如果存在這樣的直線,那麼該直線一定能通過平移和旋轉之後經過所有線段中的兩個端點,那麼我們列舉所有兩兩線段的端點作...