向量叉积

叉积

叉积的计算是线段方法的核心,考虑下图所示的向量P1P2.我们可以把叉积理解为由原点(0,0),P1,P2P1+P2所构成的平行四边形的有向面积.另一种与之等价但是更有效的定义方式是将叉积看做行列式矩阵:

 

    P1=(x1,y1)

 

    P2=(x2,y2)

 

 

P1P2的叉积为正,说明相对于原点,P1位于P2的顺时针方向,反之P1位于P2的逆时针方向,若为0,表明两个向量共线,方向可能相同,也可能相反.

上代码:

 

 1 #ifndef GEO_GEOMETRY_H_
 2 #define GEO_GEOMETRY_H_
 3 
 4 #define MIN(x,y) (x>y?y:x)
 5 #define MAX(x,y) (x>y?x:y)
 6 
 7 struct Point 
 8 {
 9     float x,y;
10     Point()
11     {
12         x=0;
13         y=0;
14     }
15     Point(float px,float py)
16     {
17         x = px;
18         y = py;
19     }
20     //叉乘,返回一个数值
21     float CrossMulti(Point v)
22     {
23         return x*v.y - v.x*y;
24     }
25     // 减法
26     Point operator-(Point b)
27     {
28         return Point(x-b.x,y-b.y);
29     }
30     // 加法
31     Point operator+(Point b)
32     {
33         return Point(x+b.x,y+b.y);
34     }
35 };
36 
37 #define Vector Point;
38 
39 // 判断点(pAim)与直线(pStart--pEnd)的关系
40 // >0 pAim在顺时针
41 // <0 pAmi在逆时针
42 // =0 三点共线
43 static float Direction(Point pStart,Point pEnd,Point pAim)
44 {
45     return (pAim-pStart).CrossMulti(pEnd-pStart);
46 }
47 
48 // 判断点(pAim)是否在线段(pStart--pEnd)上
49 static bool OnSegment(Point pStart,Point pEnd,Point pAim)
50 {
51     if( MIN(pStart.x,pEnd.x) <= pAim.x && pAim.x <= MAX(pStart.x,pEnd.x)
52         && MIN(pStart.y,pEnd.y) <= pAim.y && pAim.y <= MAX(pStart.y,pEnd.y))
53         return true;
54     return false;
55 }
56 
57 // 判断线段(p1-p2)和线段(p3-p4)是否相交
58 static bool SegmentIntersect(Point p1,Point p2,Point p3,Point p4)
59 {
60     float d1 = Direction(p3,p4,p1);
61     float d2 = Direction(p3,p4,p2);
62     float d3 = Direction(p1,p2,p3);
63     float d4 = Direction(p1,p2,p4);
64     // 如果互相分隔,一定相交
65     if( (d1 < 0 && d2 > 0 || d1 >0 && d2 < 0 )
66         && ( d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0))
67         return true;
68     // 若有三点共线,需判断点是否在线段内
69     else if( d1 == 0 && OnSegment(p3,p4,p1))
70         return true;
71     else if( d2 == 0 && OnSegment(p3,p4,p2))
72         return true;
73     else if( d3 == 0 && OnSegment(p1,p2,p3))
74         return true;
75     else if( d4 == 0 && OnSegment(p1,p2,p4))
76         return true;
77     else
78         return false;
79 }
80 
81 #endif

 

 

 

 

 

利用上述性质,我们可以判断连续线段P0P1P1P2是左拐还是右拐,不需要计算角度,我们只需要判断向量P0P2在向量P0P1的顺时针方向还是逆时针方向就好了.m=(P2-P0)×(P1-P0),如果m>0说明,则在顺时针方向,P1处右拐,m<0,则在逆时针方向,P1处左拐

 

posted @ 2016-01-08 21:51  你好阿汤哥  Views(1665)  Comments(0Edit  收藏  举报