計算幾何 --- 判斷兩條線段是否相交(平面內)


  計算幾何中,判斷線段是否相交是最基本的題目。 所謂幾何, 最基本的當然就是坐標, 從坐標中我們可以知道位置和方向,比如:一個點就是一個位置,兩點確定一條直線,從某點指向另一點的有向線段所在的直線是一向量。要處理幾何題,我們又不得不涉及到叉積和點積, 判斷線段相交就要用到叉積。

  下面先講講相交的形式:

  說到線段, 我們很自然想到直線,判斷兩條直線是否相交只需判斷它們斜率是否相等,相等就為平行或重合, 不等就相交(注:判斷相交我們不采用除法,因為除法容易產生浮點誤差,當兩條直線斜率接近時,很容易出錯。 事實上,幾乎所有幾何題都不建議采用除法)。

  線段相交有兩種形式:

    規范相交非規范相交 。 區別就是交點是否是其中一條線段的端點,不是的是規范相交。

  叉積的概念: 設向量 a(x1, y1) 、 b(x2, y2) ;

        a x b = x1*y2 - x2*y1; (與數學中的叉積不太一樣)

  判斷線段相交比較繁瑣,主要就是判斷異側:

    我們以一條線段的一端點為起點,沿着線段方向看去(一條射線),在左手邊為逆時針方向,右手邊為順時針方向。如果另一線段兩端點分別在這一線段的兩側,那么線段可能相交(也可能在線段外),否則不可能相交。對另一線段采用相同方法就可判斷出是否相交了。

     這個過程主要通過叉積來判斷: 叉積大於 0 ,在點在向量的順時針方向,小於 0 , 在逆時針方向 ; 等於 0, 端點在直線上。

 

  具體實現:

    設:線段 a :P1(x1, y1)、P2(x2, y2)      線段 b: Q1(x3, y3)、Q2(x4, y4)

    d1 ====>   (P2 - P1) x (Q1 - P1) (叉積)

    d2 ====>   (P2 - P1) x (Q2 - P1) (叉積)

    d3 ====>   (Q2 - Q1) x (P1 - Q1) (叉積)

    d4 ====>   (Q2 - Q1) x (P2 - P1) (叉積)

  

  首先,先判斷端點是否在另一線段上。

  然后,我們只需判斷 d1 * d2 < 0  並且 d3 * d4 < 0 便可判斷線段相交。

   

  

 1 #define cs const
 2 #define cp const P&
 3 #define op operator
 4 const  double eps = 1e-8;
 5 inline int sig(double x) {return (x>eps)-(x<-eps);}
 6 
 7 struct P{
 8     double x, y;
 9     void in() { scanf("%lf%lf", &x, &y); }
10     P(double x=0.0, double y=0.0) : x(x), y(y) {}
11 
12     P op-(cp a)cs { return P(x-a.x, y-a.y); }
13     double op^(cp a)cs { return x*a.y - y*a.x; }    //叉積
14     double op*(cp a)cs {return x*a.x + y*a.y;}
15 
16     double cross(P a, P b) { return (a-*this) ^ (b-*this); }
17     double dot(P a, P b)  { return (a-(*this)) * (b-(*this)); }
18     bool on_seg(P a, P b) { return !sig(cross(a, b)) && sig(dot(a, b)) <= 0; }//判斷是否在點上
19 };
20 
21 bool seg(P a, P b, P c, P d) { //判斷相交(a - b)線段 、(c - d)線段
22     if(a.on_seg(c, d) || b.on_seg(c, d) || c.on_seg(a, b) || d.on_seg(a, b))
23         return true;
24     return sig(a.cross(b, c)*a.cross(b, d)) < 0 && sig(c.cross(d, a)*c.cross(d, b)) < 0;
25 }

 

 

 

訓練題:杭電oj 1086 :

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1086

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM