線段判交--ACM


給定兩個點:

typedef  struct {

  double  x, y;

} Point;

Point A1,A2,B1,B2;

首先引入兩個實驗:

a.快速排斥實驗

設以線段A1A2和線段B1B2為對角線的矩形為M,N;

若M,N 不相交,則兩個線段顯然不相交;

所以:滿足第一個條件時:兩個線段可能相交。

 

b.跨立實驗

如果兩線段相交,則兩線段必然相互跨立對方.若A1A2跨立B1B2,則矢量( A1 - B1 ) 和(A2-B1)位於矢量(B2-B1)的兩側,

即(A1-B1) × (B2-B1) * (A2-B1) × (B2-B1)<0。

上式可改寫成(A1-B1) × (B2-B1) * (B2-B1) × (A2-A1)>0。

應該判斷兩次,即兩條線段都要為直線,判斷另一直線的兩端點是否在它兩邊,若是則兩線段相交。

若積極滿跨立實驗是不行的,如下面的情況:

即兩條線段在同一條直線上。所以我們要同時滿足兩次跨立和快速排斥實驗。

 

總體分析:

當(A1-B1) × (B2-B1)=0時,說明(A1-B1)和(B2-B1)共線,但是因為已經通過快速排斥試驗,所以 A1一定在線段 B1B2上;同理,(B2-B1)×(A2-B1)=0 說明A2一定在線段B1B2上。所以判斷A1A2跨立B1B2的依據是:(A1-B1) × (B2-B1) * (B2-B1) × (A2-B1) >= 0。

同理判斷B1B2跨立A1A2的依據是:(B1-A1) × (A2-A1) * (A2-A1) × (B2-A1) >= 0。

如圖:

應用:

1.       判斷兩個線段相交

2.       判斷線段與直線相交

3.       判斷點在矩形內

代碼:


 1  /*
 2  (A1-B1) × (B2-B1) * (B2-B1) × (A2-A1) >= 0
 3  (B1-A1) × (A2-A1) * (A2-A1) × (B2-A1) >= 0
 4  */
 5 
 6 #include<stdio.h>
 7  #define min(a,b) a<b?a:b
 8  #define max(a,b) a>b?a:b
 9 typedef  struct {
10  double x,y;
11 }Point;
12 Point A1,A2,B1,B2;
13 Point  A1B1, B2B1, A2A1, B2A1;
14  double xx(Point &s,Point &t)
15 {
16      return (s.x*t.y+s.y*t.x);
17 }
18  int kua()                            // 跨立實驗
19  {
20     A1B1.x=A1.x-B1.x;  A1B1.y=A1.y-B1.y;
21     B2B1.x=B2.x-B1.x;  B2B1.y=B2.y-B1.y;
22     A2A1.x=A2.x-A1.x;  A2A1.y=A2.y-A1.y;
23     B2A1.x=B2.x-A1.x;  B2A1.y=B2.y-A1.y;
24      if(xx(A1B1,B2B1)*xx(B2B1,A2A1)>= 0)
25     {
26         A1B1.y=-A1B1.y;A1B1.x=-A1B1.x;
27          if(xx(A1B1,A2A1)*xx(A2A1,B2A1)>= 0)
28              return  1;
29          else
30              return  0;
31     }
32      else
33          return  0;
34 }
35  int main()
36 {
37     Point A1,A2,B1,B2;
38      int flag= 1,i,j,a,b,c,d,e,f;
39      while( 1)
40     {
41         scanf( " %lf%lf%lf%lf ",&A1.x,&A1.y,&A2.x,&A2.y);
42         scanf( " %lf%lf%lf%lf ",&B1.x,&B1.y,&B2.x,&B2.y);
43          if( min(A1.x,A2.x) <= max(B1.x,B2.x) &&
44             min(B1.x,B2.x) <= max(A1.x,A2.x) &&
45             min(A1.y,A2.y) <= max(B1.y,B2.y) &&
46             min(B1.y,B2.y) <= max(A1.y,A2.y)   )    // 快速排斥實驗
47          {
48              if(kua())
49                 printf( " 線段相交\n ");
50              else
51                 printf( " 線段不相交\n ");
52         }
53          else
54             printf( " 線段不相交\n ");
55 
56     }
57      return  0;

58 }

轉載自: http://blog.csdn.net/ice2013/article/details/7444406

 


免責聲明!

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



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