計算幾何-判斷線段相交
判斷兩線段是否相交:
- 快速排斥
- 跨立實驗(這兩個詞也是我看博客的時候看到的,覺得挺高大上的就拿過來用了,哈哈哈)
1. 快速排斥:就是初步的判斷一下,兩條線段是不是相交,以兩條線段為對角線的矩形,如果不重合的話,那么兩條線段一定不可能相交。看下圖:
1.線段ab的低點低於cd的最高點(可能重合)
2.cd的最左端小於ab的最右端(可能重合)
3.cd的最低點低於ab的最高點(加上條件1,兩線段在豎直方向上重合)
4.ab的最左端小於cd的最右端(加上條件2,兩直線在水平方向上重合)
綜上4個條件,兩條線段組成的矩形是重合的
用代碼實現(c++):
if(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y))
return true;
2. 跨立實驗:如果兩條線段相交,那么必須跨立,就是以一條線段為標准,另一條線段的兩端點一定在這條線段的兩段
也就是說a b兩點在線段cd的兩端,c d兩點在線段ab的兩端
這里就用到了向量X乘的知識點,有向量X乘的物理意義知:AB x CD=-CD x AB
看下圖:
(ca x cd)·(cb x cd)<=0 則說明ca cb先對於cd的方向不同,則a b在線段cd的兩側,由此可以判斷其他點
代碼實現:
double u,v,w,z;//分別記錄兩個向量 u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y); v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y); w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y); z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y); return (u*v<=0.00000001 && w*z<=0.00000001); 因為double沒法直接比較大小嘛,所以來看這篇博客的應該能看懂
由此就完全判斷出兩條線段是否相交了。
模板:
/***************************************線段相交模板****************************************/ struct Point{//點 double x,y; Point(){} Point(int a,int b){ x=a; y=b; } void input(){//定義輸入函數方便用的時候 scanf("%lf%lf",&x,&y); } }; struct Line{//線段 Point a,b; Line(){} Line(Point x,Point y){ a=x; b=y; } void input(){ a.input(); b.input(); } }; bool judge(Point &a,Point &b,Point &c,Point &d) { /* 快速排斥: 兩個線段為對角線組成的矩形,如果這兩個矩形沒有重疊的部分,那么兩條線段是不可能出現重疊的 */ if(!(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y)))//這里的確如此,這一步是判定兩矩形是否相交 //1.線段ab的低點低於cd的最高點(可能重合) 2.cd的最左端小於ab的最右端(可能重合) //3.cd的最低點低於ab的最高點(加上條件1,兩線段在豎直方向上重合) 4.ab的最左端小於cd的最右端(加上條件2,兩直線在水平方向上重合) //綜上4個條件,兩條線段組成的矩形是重合的 /*特別要注意一個矩形含於另一個矩形之內的情況*/ return false; /* 跨立實驗: 如果兩條線段相交,那么必須跨立,就是以一條線段為標准,另一條線段的兩端點一定在這條線段的兩段 也就是說a b兩點在線段cd的兩端,c d兩點在線段ab的兩端 */ double u,v,w,z;//分別記錄兩個向量 u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y); v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y); w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y); z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y); return (u*v<=0.00000001 && w*z<=0.00000001); } /***************************************線段相交模板****************************************/