计算几何内容

叉乘是三维才有意义, 这里虽然是二维的, 但可以看成第三维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 }
View Code

 

posted @ 2019-04-23 15:56  saaas  阅读(216)  评论(0编辑  收藏  举报