快速排斥、跨立實驗判斷線段是否相交
阿新 • • 發佈:2019-02-05
寫在前面
在其他部落格中看到這方面的知識,很多都是重複,並且說的總是雲裡霧裡的,所以這裡我就自己總結一下這種問題如何求解,判斷兩個線段是否相交在前面我們提到了會用到叉積的一點知識,那麼這裡就來詳細說一下怎麼判斷兩個線段是否相交
演算法詳解
首先我們看一下快速排斥實驗,快速排斥實驗也就是以兩條線段作為對角線做矩形,判斷兩個矩形是否相交,那麼我們這裡可以知道:
1)如果兩個矩形不相交,那麼線段一定不相交
2)如果兩個矩形相交,那麼線段不一定相交,如下圖
所以這裡我們首先就要判斷兩條線段形成的矩形是否相交,只有相交我們才要繼續進行判斷後面的線段是否相交.......
跨立實驗:前面我們知道叉積可以用來判斷兩個向量之間的位置關係(順時針還是逆時針關係),那麼這裡我們就會用到這個性質
我們知道如果兩個線段相交的話,那麼一條線段兩邊的兩個點要位於另一條線段的兩邊,只有兩條線段都滿足這個條件,我們就可以判定這兩條直線相交了,那麼我們這裡所說的一條線段兩個端點位於另一條線段的兩邊,這就是其他部落格中提到的跨立吧
那麼我們就用叉積來對是否滿足這個條件進行判斷:
取其中一個向量作為中間向量,中間向量中開始端點作為另外兩個向量的起點,判斷三個向量之間的位置關係即可:
第一個圖中: (ca × cd)(cd × cb) >= 0 我們即可判斷滿足跨立條件
第二個圖中: (bc × ba)(ba × bd) >=0 我們即可判斷滿足跨立條件
第三個圖中: (bc × ba)(ba × bd) < 0不滿足跨立條件
第四個圖中: (ca × cd)(cd × cb) >= 0我們即可判斷滿足跨立條件
那麼我們就可以知道上面條件就是判斷跨立是否成立的條件了,那麼這樣我們線段是否相交就已經可以解決了.栗子及模板
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 2100; struct Point { double x,y; }line[MAXN][2]; double mult(Point p0,Point p1,Point p2) //叉積計算,p0為公用節點 { return (p0.x - p1.x) * (p0.y - p2.y) - (p0.y - p1.y) * (p0.x - p2.x); } //aa、bb屬於同一個矩形 cc、dd屬於同一個矩形 相交返回true,不相交返回false bool Judge(Point aa,Point bb,Point cc,Point dd) { //判斷兩個形成的矩形不相交 if(max(aa.x , bb.x) < min(cc.x , dd.x)) return false; if(max(aa.y , bb.y) < min(cc.y , dd.y)) return false; if(max(cc.x , dd.x) < min(aa.x , bb.x)) return false; if(max(cc.y , dd.y) < min(aa.y , bb.y)) return false; //現在已經滿足快速排斥實驗,那麼後面就是跨立實驗內容(叉積判斷兩個線段是否相交) if(mult(aa,cc,bb) * mult(aa,bb,dd) < 0) return false; //正確的話也就是aa,bb要在cc或者dd的兩邊 if(mult(cc,aa,dd) * mult(cc,dd,bb) < 0) return false; return true; } int main() { int n; while(~scanf("%d",&n)) { bool flag = true; for(int i = 0;i < n;i ++) scanf("%lf%lf%lf%lf",&line[i][0].x,&line[i][0].y,&line[i][1].x,&line[i][1].y); for(int i = 0;i < n;i ++) for(int j = i+1;j < n;j ++) { if(Judge(line[i][0],line[i][1],line[j][0],line[j][1])) // 判斷兩條直線是否相交 { flag = false; break; } if(!flag) break; } if(!flag) printf("burned!\n"); else printf("ok!\n"); } return 0; }