计算几何内容
叉乘是三维才有意义, 这里虽然是二维的, 但可以看成第三维z是0
所以计算结果就变成了(0, 0, x1y2 - x2y1)
叉积只在空间向量中才有意义,平面向量只有点积。
设向量a= (x1,y1, z1),b=(x2, y2,z2),
则axb= (y1Z2一Y2Z1, 一(X1Z2一X2Z1),X1Y2 一X2Y1) 。axb是与d、b都垂直的向量。
叉积的应用:
通过结果的正负判断两矢量之间的顺逆时针关系
若 a x b > 0表示a在b的顺时针方向上
若 a x b < 0表示a在b的逆时针方向上
若 a x b == 0表示a在b共线,但不确定方向是否相同
1 #include <iostream> 2 #include <cmath> 3 #include <algorithm> 4 #include <string> 5 #include <cstring> 6 using namespace std; 7 8 const double eps = 1e-8; 9 const double PI = acos(-1.0); 10 11 12 13 int sgn(double x) 14 { 15 if(fabs(x) < eps) 16 return 0; 17 if(x < 0) 18 return -1; 19 else 20 return 1; 21 } 22 23 struct Point 24 { 25 double x,y; 26 Point(){} 27 Point(double _x,double _y) 28 { 29 x = _x;y = _y; 30 } 31 Point operator -(const Point &b)const 32 { 33 return Point(x - b.x,y - b.y); 34 } 35 //叉积 36 double operator ^(const Point &b)const 37 { 38 return x*b.y - y*b.x; 39 } 40 //点积 41 double operator *(const Point &b)const 42 { 43 return x*b.x + y*b.y; 44 } 45 //绕原点旋转角度B(弧度值),后x,y的变化 46 void transXY(double B) 47 { 48 double tx = x,ty = y; 49 x = tx*cos(B) - ty*sin(B); 50 y = tx*sin(B) + ty*cos(B); 51 } 52 }; 53 54 void show(Point p){ 55 cout<<"P.x : "<<p.x <<" ,p.y : "<<p.y<<endl; 56 } 57 58 struct Line 59 { 60 Point s,e; 61 Line(){} 62 Line(Point _s,Point _e) 63 { 64 s = _s;e = _e; 65 } 66 67 pair<int,Point> operator &(const Line &b)const 68 { 69 Point res = s; 70 if(sgn((s-e)^(b.s-b.e)) == 0) 71 { 72 if(sgn((s-b.e)^(b.s-b.e)) == 0) 73 return make_pair(0,res);//重合 74 else 75 return make_pair(1,res);//平行 76 } 77 double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); 78 res.x += (e.x-s.x)*t; 79 res.y += (e.y-s.y)*t; 80 return make_pair(2,res); 81 } 82 }; 83 84 double dist(Point a,Point b) 85 { 86 return sqrt((a-b)*(a-b)); 87 } 88 89 bool inter(Line l1,Line l2) 90 { 91 return 92 max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && 93 max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && 94 max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && 95 max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && 96 sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 && 97 sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; 98 } 99 100 bool Seg_inter_line(Line l1,Line l2) //判断直线l1和线段l2是否相交 101 { 102 return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0; 103 } 104 105 Point PointToLine(Point P,Line L) 106 { 107 Point result; 108 double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); 109 result.x = L.s.x + (L.e.x-L.s.x)*t; 110 result.y = L.s.y + (L.e.y-L.s.y)*t; 111 return result; 112 } 113 114 Point NearestPointToLineSeg(Point P,Line L) 115 { 116 Point result; 117 double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); 118 if(t >= 0 && t <= 1) 119 { 120 result.x = L.s.x + (L.e.x - L.s.x)*t; 121 result.y = L.s.y + (L.e.y - L.s.y)*t; 122 } 123 else 124 { 125 if(dist(P,L.s) < dist(P,L.e)) 126 result = L.s; 127 else result = L.e; 128 } 129 return result; 130 } 131 132 //计算多边形面积 133 //点的编号从0~n-1 134 double CalcArea(Point p[],int n) 135 { 136 double res = 0; 137 for(int i = 0;i < n;i++){ 138 res += (p[i]^p[(i+1)%n])/2; 139 cout<<"res += "<<(p[i]^p[(i+1)%n])/2<<endl; 140 } 141 return fabs(res); 142 } 143 144 //*判断点在线段上 145 bool OnSeg(Point P,Line L) 146 { 147 return 148 sgn((L.s-P)^(L.e-P)) == 0 && 149 sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 && 150 sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0; 151 } 152 153 154 //*判断点在凸多边形内 155 //点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0) 156 //点的编号:0~n-1 157 //返回值: 158 //-1:点在凸多边形外 159 //0:点在凸多边形边界上 160 //1:点在凸多边形内 161 int inConvexPoly(Point a,Point p[],int n) 162 { 163 for(int i = 0;i < n;i++) 164 { 165 if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0) 166 return -1; 167 else if(OnSeg(a,Line(p[i],p[(i+1)%n]))) 168 return 0; 169 } 170 return 1; 171 } 172 173 174 //*判断点在任意多边形内 175 //射线法,poly[]的顶点数要大于等于3,点的编号0~n-1 176 //返回值 177 //-1:点在凸多边形外 178 //0:点在凸多边形边界上 179 //1:点在凸多边形内 180 int inPoly(Point p,Point poly[],int n) 181 { 182 int cnt; 183 Line ray,side; 184 cnt = 0; 185 ray.s = p; 186 ray.e.y = p.y; 187 ray.e.x = -100000000000.0;//-INF,注意取值防止越界 188 for(int i = 0;i < n;i++) 189 { 190 side.s = poly[i]; 191 side.e = poly[(i+1)%n]; 192 if(OnSeg(p,side)) 193 return 0; 194 //如果平行轴则不考虑 195 if(sgn(side.s.y - side.e.y) == 0) 196 continue; 197 if(OnSeg(side.s,ray)) 198 { 199 if(sgn(side.s.y - side.e.y) > 0) 200 cnt++; 201 } 202 else if(OnSeg(side.e,ray)) 203 { 204 if(sgn(side.e.y - side.s.y) > 0)cnt++; 205 } 206 else if(inter(ray,side)) 207 cnt++; 208 // cout<<"cnt = "<<cnt<<" while i = "<<i<<endl; 209 } 210 // cout<<"cnt : "<<cnt<<endl; 211 if(cnt % 2 == 1) return 1; 212 else return -1; 213 } 214 215 //判断凸多边形 216 //允许共线边 217 //点可以是顺时针给出也可以是逆时针给出 218 //点的编号1~n-1 219 bool isconvex(Point poly[],int n) 220 { 221 bool s[3]; 222 memset(s,false,sizeof(s)); 223 for(int i = 0;i < n;i++) 224 { 225 s[sgn( (poly[(i+1)%n]-poly[i])^(poly[(i+2)%n]-poly[i]) )+1] = true; 226 if(s[0] && s[2])return false; 227 } 228 return true; 229 } 230 231 232 int main() 233 { 234 Point pp[4] = {Point(2,2),Point(2,4),Point(3,3),Point(5,2)}; 235 // cout<<"area : "<<CalcArea(pp,4)<<endl; 236 Point p = Point(3,4); 237 238 cout<<isconvex(pp,4)<<endl; 239 return 0; 240 }