計算幾何-判斷線段是否相交


計算幾何-判斷線段相交

判斷兩線段是否相交:

  1. 快速排斥
  2. 跨立實驗(這兩個詞也是我看博客的時候看到的,覺得挺高大上的就拿過來用了,哈哈哈)

 

  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);
}

/***************************************線段相交模板****************************************/

 


免責聲明!

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



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