判斷兩線段相交

點乘php

  一個向量在另外一個向量上的投影長度,標量,用於判斷角度html

叉乘ios

  垂直兩向量的平面,右手定則,矢量,用於判斷方向spa

參考博客:點擊進入
code

(1)快速排斥試驗htm

   設以線段 P1P2 爲對角線的矩形爲R, 設以線段 Q1Q2 爲對角線的矩形爲T,若是R和T不相交,顯然兩線段不會相交。blog

(2)跨立試驗
ci

   若是兩線段相交,則兩線段必然相互跨立對方。若P1P2跨立Q1Q2 ,則矢量 ( P1 - Q1 ) 和( P2 - Q1 )位於矢量( Q2 - Q1 ) 的兩側,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改寫成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。當 ( P1 - Q1 ) × ( Q2 - Q1 ) = 0 時,說明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共線,可是由於已經經過快速排斥試驗,因此 P1 必定在線段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 說明 P2 必定在線段 Q1Q2上。因此判斷P1P2跨立Q1Q2的依據是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判斷Q1Q2跨立P1P2的依據是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。get

 

例題:51nod1264博客

 1 #include<iostream>
 2 using namespace std;
 3 
 4 struct Point
 5 {
 6     double x, y;
 7 } dot[4];
 8 
 9 double cross(Point a, Point b, Point c)
10 {
11     double nx1, ny1, nx2, ny2;
12     nx1 = b.x - a.x;
13     ny1 = b.y - a.y;
14     nx2 = c.x - b.x;
15     ny2 = c.y - b.y;
16     return nx1 * ny2 - ny1 * nx2;
17 }
18 
19 int main()
20 {
21     int t;
22     cin >> t;
23     while(t--)
24     {
25         for(int i = 0; i < 4; i++)
26             cin >> dot[i].x >> dot[i].y;
27         double s1, s2, s3, s4;
28         //這裏的三點順序須要注意,可由叉乘相關性質推導出
29         s1 = cross(dot[0], dot[2], dot[3]);
30         s2 = cross(dot[3], dot[2], dot[1]);
31         s3 = cross(dot[2], dot[0], dot[1]);
32         s4 = cross(dot[1], dot[0], dot[3]);
33         if(s1 * s2 >= 0 && s3 * s4 >= 0)
34             cout << "YES" << endl;
35         else
36             cout << "NO" << endl;
37     }
38     return 0;
39 }

 

關於上面的順序問題,畫個圖加深一下理解

 

 

例題:hdu1086

 1 #include<iostream>
 2 using namespace std;
 3 
 4 struct Point
 5 {
 6     double x, y;
 7 } dot[220];
 8 
 9 struct Seg
10 {
11     Point fir, sec;
12 } Seg[110];
13 
14 double cross(Point a, Point b, Point c)
15 {
16     double nx1, ny1, nx2, ny2;
17     nx1 = b.x - a.x;
18     ny1 = b.y - a.y;
19     nx2 = c.x - b.x;
20     ny2 = c.y - b.y;
21     return nx1 * ny2 - ny1 * nx2;
22 }
23 
24 int is_cross(Point a, Point b, Point c, Point d)
25 {
26     double s1, s2, s3, s4;
27     s1 = cross(a, c, d);
28     s2 = cross(d, c, b);
29     s3 = cross(c, a, b);
30     s4 = cross(b, a, d);
31     if(s1 * s2 >= 0 && s3 * s4 >= 0)
32         return 1;
33     return 0;
34 }
35 int main()
36 {
37     int n;
38     while(cin >> n && n)
39     {
40         int ans = 0;
41         for(int i = 0; i < n; i++)
42         {
43             cin >> Seg[i].fir.x >> Seg[i].fir.y >> Seg[i].sec.x >> Seg[i].sec.y;
44         }
45         for(int i = 0; i < n; i++)
46         {
47             for(int j = i + 1; j < n; j++)
48             {
49                 if(is_cross(Seg[i].fir, Seg[i].sec, Seg[j].fir, Seg[j].sec))
50                     ans++;
51             }
52         }
53         cout << ans << endl;
54     }
55     return 0;
56 }

 

 體會:

  計算幾何題須要對幾何知識有必定的熟悉,有時一行公式代碼可能要推導一下子時間,因此我的感受這類題模板和公式總結很重要,慢慢積累吧~

相關文章
相關標籤/搜索