給定兩個點:
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. 判斷點在矩形內
代碼:
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