計算幾何常用演算法介紹
1. 向量減法
設二維向量 p = (x1,y1) ,q = (x2,y2)
則向量減法定義為: p - q = ( x1 - x2 , y1 - y2 )
顯然有性質 p - q = - ( q - p )
如不加說明,下面所有的點都看作向量,兩點的減法就是向量相減;
2.向量叉積
設向量p = (x1,y1) ,q = (x2,y2)
則向量叉積定義為: p × q = x1*y2 - x2*y1 得到的是乙個標量顯然有性質 p × q = - ( q × p ) p × ( - q ) = - ( p × q )
如不加說明,下面所有的點都看作向量,點的乘法看作向量叉積;
叉乘的重要性質:
> 若 p × q > 0 , 則p 在q的順時針方向
> 若 p × q < 0 , 則p 在q的逆時針方向
> 若 p × q = 0 , 則p 與q共線,但可能同向也可能反向
設點為q,線段為p1p2 ,判斷點q在該線段上的依據是:( q - p1 ) × ( p2 - p1 ) = 0 且 q 在以 p1,p2為對角頂點的矩形內
4.判斷兩線段是否相交
我們分兩步確定兩條線段是否相交:
(1). 快速排斥試驗
設以線段 p1p2 為對角線的矩形為r, 設以線段 q1q2 為對角線的矩形為t,如果r和t不相交,顯然兩線段不會相交;
(2). 跨立試驗
所以判斷p1p2跨立q1q2的依據是:
( p1 - q1 ) × ( q2 - q1 ) * ( q2 - q1 ) × ( p2 - q1 ) ≥ 0
同理判斷q1q2跨立p1p2的依據是:
( q1 - p1 ) × ( p2 - p1 ) * ( p2 - p1 ) × ( q2 - p1 ) ≥ 0
至此已經完全解決判斷線段是否相交的問題。
5.判斷線段和直線是否相交
如果線段 p1p2和直線q1q2相交,則p1p2跨立q1q2,即:
( p1 - q1 ) × ( q2 - q1 ) * ( q2 - q1 ) × ( p2 - q1 ) ≥ 0
6.判斷矩形是否包含點
只要判斷該點的橫座標和縱座標是否夾在矩形的左右邊和上下邊之間。
6.判斷線段、折線、多邊形是否在矩形中
因為矩形是個凸集,所以只要判斷所有端點是否都在矩形中就可以了。
7.判斷矩形是否在矩形中
只要比較左右邊界和上下邊界就可以了。
8.判斷圓是否在矩形中
圓在矩形中的充要條件是:圓心在矩形中且圓的半徑小於等於圓心到矩形四邊的距離的最小值。
9.判斷點是否在多邊形中
以點p為端點,向左方作射線l,由於多邊形是有界的,所以射線l的左端一定在多邊形外,考慮沿著l從無窮遠處開始自左向右移動,遇到和多邊形的第乙個交點的時候,進入到了多邊形的內部,遇到第二個交點的時候,離開了多邊形,……所以很容易看出當l和多邊形的交點數目c是奇數的時候,p在多邊形內,是偶數的話p在多邊形外。
但是有些特殊情況要加以考慮。如果l和多邊形的頂點相交,有些情況下交點只能計算乙個,有些情況下交點不應被計算(自己畫個圖就明白了);如果l和多邊形的一條邊重合,這條邊應該被忽略不計。為了統一起見,我們在計算射線l和多邊形的交點的時候,1。對於多邊形的水平邊不作考慮;2。對於多邊形的頂點和l相交的情況,如果該頂點是其所屬的邊上縱座標較大的頂點,則計數,否則忽略;3。對於p在多邊形邊上的情形,直接可判斷p屬於多邊行。由此得出演算法的偽**如下:
1. count ← 0;
2. 以p為端點,作從右向左的射線l;
3. for 多邊形的每條邊s
4. do if p在邊s上
5. then return true;
6. if s不是水平的
7. then if s的乙個端點在l上且該端點是s兩端點中縱座標較大的端點
9. then count ← count+1
10. else if s和l相交
11. then count ← count+1;
12. if count mod 2 = 1
13. then return true
14. else return false;
其中做射線l的方法是:設p'的縱座標和p相同,橫座標為正無窮大(很大的乙個正數),則p和p'就確定了射線l。這個演算法的複雜度為o(n)。
10.判斷線段是否在多邊形內
線段在多邊形內的乙個必要條件是線段的兩個端點都在多邊形內;如果線段和多邊形的某條邊內交(兩線段內交是指兩線段相交且交點不在兩線段的端點),因為多邊形的邊的左右兩側分屬多邊形內外不同部分,所以線段一定會有一部分在多邊形外。於是我們得到線段在多邊形內的第二個必要條件:線段和多邊形的所有邊都不內交;
命題1:
如果線段和多邊形的兩相鄰交點p1 ,p2的中點p' 也在多邊形內,則p1, p2之間的所有點都在多邊形內。
證明:假設p1,p2之間含有不在多邊形內的點,不妨設該點為q,在p1, p'之間,因為多邊形是閉合曲線,所以其內外部之間有界,而p1屬於多邊行內部,q屬於多邊性外部,p'屬於多邊性內部,p1-q-p'完全連續,所以p1q和qp'一定跨越多邊形的邊界,因此在p1,p'之間至少還有兩個該線段和多邊形的交點,這和p1p2是相鄰兩交點矛盾,故命題成立。證畢
由命題1直接可得出推論:
推論2:
設多邊形和線段pq的交點依次為p1,p2,……pn,其中pi和pi+1是相鄰兩交點,線段pq在多邊形內的充要條件是:p,q在多邊形內且對於i =1, 2,……, n-1,pi ,pi+1的中點也在多邊形內。
至此我們得出演算法如下:
1. if 線端pq的端點不都在多邊形內
2. then return false;
3. 點集pointset初始化為空;
4. for 多邊形的每條邊s
5. do if 線段的某個端點在s上
6. then 將該端點加入pointset;
8. then 將該端點加入pointset;
9. else if s和線段pq相交 // 這時候可以肯定是內交
10. then return false;
11. 將pointset中的點按照x-y座標排序,x座標小的排在前面,
對於x座標相同的點,y座標小的排在前面;
12. for pointset中每兩個相鄰點 pointset[i] , pointset[ i+1]
13. do if pointset[i] , pointset[ i+1] 的中點不在多邊形中
14. then return false;
15. return true;
這個演算法的複雜度也是o(n)。其中的排序因為交點數目肯定遠小於多邊形的頂點數目n,所以最多是常數級的複雜度,幾乎可以忽略不計。
11.判斷折線在多邊形內只要判斷折線的每條線段是否都在多邊形內即可。設折線有m條線段,多邊形有n個頂點,則複雜度為o(m*n)。
12.判斷多邊形是否在多邊形內只要判斷多邊形的每條邊是否都在多邊形內即可。判斷乙個有m個頂點的多邊形是否在乙個有n個頂點的多邊形內複雜度為o(m*n)。
13.判斷矩形是否在多邊形內將矩形轉化為多邊形,然後再判斷是否在多邊形內。
14.判斷圓是否在多邊形內只要計算圓心到多邊形的每條邊的最短距離,如果該距離大於等於圓半徑則該圓在多邊形內。計算圓心到多邊形每條邊最短距離的演算法在後文闡述。
15.判斷點是否在圓內計算圓心到該點的距離,如果小於等於半徑則該點在圓內。
16.判斷線段、折線、矩形、多邊形是否在圓內因為圓是凸集,所以只要判斷是否每個頂點都在圓內即可。
17.判斷圓是否在圓內
設兩圓為o1,o2,半徑分別為r1, r2,要判斷o2是否在o1內。先比較r1,r2的大小,如果r1 r 則l和圓沒有交點;
c)利用勾股定理,可以求出兩交點座標,如圖6(a)所示;但要注意考慮l和圓的相切情況
3.如果l平行於x軸,做法與l平行於y軸的情況類似;
4.如果l既不平行x軸也不平行y軸,可以求出l的斜率k,然後列出l的點斜式方程,和圓方程聯立即可求解出l和圓的兩個交點;
5.如果l是線段,對於2,3,4中求出的交點還要分別判斷是否屬於該線段的範圍內。
計算幾何常用演算法 ACM
複製自 1.向量減法 設二維向量 p x1,y1 q x2,y2 則向量減法定義為 p q x1 x2 y1 y2 顯然有性質 p q q p 如不加說明,下面所有的點都看作向量,兩點的減法就是向量相減 2.向量叉積 設向量p x1,y1 q x2,y2 則向量叉積定義為 p q x1 y2 x2 ...
C 常用計算幾何演算法
從網上轉來的幾何演算法,對點線的基本演算法,有興趣的可以學習下。include include include include define max a,b a b a b define min a,b a b b a define sign x x eps?1 x eps?1 0 using na...
演算法 計算幾何
剛寫了乙個計算幾何的模板,這樣可以減少很多的函式,實現起來也很清楚,以後自己就這樣寫好了 常用計算 define vector point struct point vector operator vector a,vector b vector operator vector a,vector b...