日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

判断两线段是否相交——快速排斥与跨立实验

發(fā)布時(shí)間:2024/9/5 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 判断两线段是否相交——快速排斥与跨立实验 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  如何判斷兩條線段是否相交呢?如果是我們?nèi)ソ鉀Q這個(gè)問(wèn)題,用眼睛很容易就看出來(lái)了,但是如果用計(jì)算機(jī)來(lái)解決這個(gè)問(wèn)題,該怎么辦呢?下面介紹兩個(gè)方法,這兩個(gè)方法結(jié)合起來(lái)就能完美解決這個(gè)問(wèn)題了。 一、快速排斥
對(duì)于兩條線段,我們以這兩條線段為對(duì)角線各自作一個(gè)矩形,如圖所示,如果這兩個(gè)矩形沒有相交的部分那么這兩條線段一定不相交,這樣我們可以排除一部分不相交的情況了。

那么又該怎么判斷這兩個(gè)矩形是否相交呢?這就比判斷線段要簡(jiǎn)單的多了,若:
·線段1下面的端點(diǎn)高于線段2上面的端點(diǎn);
·線段1上面的端點(diǎn)低于線段2下面的端點(diǎn);
·線段1左面的端點(diǎn)位于線段2右面的端點(diǎn)的右邊;
·線段1右面的端點(diǎn)位于線段2左面的端點(diǎn)的左邊;
那么我們就可以說(shuō)這兩個(gè)矩形不相交,即這兩個(gè)線段不相交,用代碼實(shí)現(xiàn)如下:
1 bool quick_judge(point a,point b,point c,point d) 2 { 3 if(a.y>c.y||b.y<d.y||a.x>d.x||b.x<c.x) 4 return false; 5 else return true; 6 }

但是僅這一種判斷方式無(wú)法解決我們的問(wèn)題,有反例如下圖,兩矩形相交但是線段并沒有相交,這就需要我們用第二種方法來(lái)加以輔助。

二、跨立實(shí)驗(yàn) 首先簡(jiǎn)單介紹一下向量的叉乘:   假設(shè)有兩個(gè)二維向量a,b,那么它們的的叉乘結(jié)果為a×b=a.x*b.y-b.x*a.y,我們可以通過(guò)這個(gè)值得到很多有用的性質(zhì):
  ·a,b向量構(gòu)成的平行四邊形的面積。
  ·如果k>0時(shí),那么a正旋轉(zhuǎn)到b的角度為<180°,如果k<0,那么a正旋轉(zhuǎn)到b的角度為>180°,如果k=0 那么a,b向量平行。 跨立實(shí)驗(yàn)用到的就是上面的第二個(gè)性質(zhì)。 我們?cè)賮?lái)看跨立實(shí)驗(yàn),簡(jiǎn)單來(lái)說(shuō),就是兩條相交線段,其中一條的兩個(gè)點(diǎn)一定在另一條的兩邊,如下圖。

那么如何去判斷呢,這就需要用到我們上面說(shuō)到的叉乘了。如在下圖中,我們選擇線段AB為基準(zhǔn),然后去判斷AC×AB與AD×AB是否是同向的,若不是同向的,則證明了B,D兩點(diǎn)在線段AB的兩邊。即?
用代碼來(lái)實(shí)現(xiàn): 1 bool cross_judge(point a,point b,point c,point d) 2 { 3 const double eps=1e-9; 4 double ac,ad,cb,ca; 5 ac=(c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x); 6 ad=(d.x-a.x)*(b.y-a.y)-(d.y-a.y)*(b.x-a.x); 7 ca=(a.x-c.x)*(d.y-c.y)-(a.y-c.y)*(d.x-c.x); //保險(xiǎn)起見,把另一條邊也判斷一下 8 cb=(b.x-c.x)*(d.y-c.y)-(b.y-c.y)*(d.x-c.x); 9 if(ac*ad<eps&&ca*cb<eps) return true; 10 else return false; 11 }

至此,我們將這兩個(gè)方法結(jié)合一下,就可以解決我們的問(wèn)題了。

三、相關(guān)題目 1.例題 ZOJ P1648 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const double eps=1e-9; 6 7 struct segment 8 { 9 double x1,x2,y1,y2; 10 }seg[2005]; 11 12 bool judge(segment a,segment b) 13 { 14 if(min(a.x1,a.x2)<max(b.x1,b.x2)&&max(a.x1,a.x2)>min(b.x1,b.x2)&&min(a.y1,a.y2)<max(b.y1,b.y2)&&max(a.y1,a.y2)>min(b.y1,b.y2)) 15 { 16 double v1,v2,v3,v4; 17 v1=(b.x1-a.x1)*(a.y2-a.y1)-(b.y1-a.y1)*(a.x2-a.x1); 18 v2=(b.x2-a.x1)*(a.y2-a.y1)-(b.y2-a.y1)*(a.x2-a.x1); 19 v3=(a.x1-b.x1)*(b.y2-b.y1)-(a.y1-b.y1)*(b.x2-b.x1); 20 v4=(a.x2-b.x1)*(b.y2-b.y1)-(a.y2-b.y1)*(b.x2-b.x1); 21 if(v1*v2<eps&&v3*v4<eps) return true; 22 else return false; 23 } 24 else return false; 25 } 26 27 int main() 28 { 29 int i,j,n,flag=0; 30 while(~scanf("%d",&n)) 31 { 32 flag=0; 33 for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&seg[i].x1,&seg[i].y1,&seg[i].x2,&seg[i].y2); 34 for(i=0;i<n;i++) 35 for(j=i+1;j<n;j++) 36 { 37 if(judge(seg[i],seg[j])) 38 { 39 flag=1; 40 break; 41 } 42 } 43 if(flag) printf("burned!\n"); 44 else printf("ok!\n"); 45 } 46 return 0; 47 } ZOJ P1648

?

Author : Houge  Date : 2019.5.31 Update log :?

轉(zhuǎn)載于:https://www.cnblogs.com/CSGOBESTGAMEEVER/p/10939868.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的判断两线段是否相交——快速排斥与跨立实验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。