计算几何--二维几何前置基础知识

内容参考书籍——《算法竞赛入门经典训练指南》

  在平面坐标系下,向量和点一样用两个数,x和y表示。判断相等使用“三态函数”dcmp,减少精度问题。另外,向量有一个所谓的“极角”,即从x轴正半轴旋转到该方向所需的角度。c标准库里的atan2函数就是用来求极角的,例如:向量(x,y)的极角就是atan2(y,x)(单位:弧度)。

  点积,高中知识。

  叉积。简单地说,两个向量的叉积等于两个向量组成的三角形的有向面积的两倍。(图中带箭头的向量为v,和v同一个起点的另外一条向量为w,忘记标v和w了尴尬)

         cross(v,w)>0                   cross(v,w)<0 

   顺着第一个向量v看,,如果w在左边,那么v和w的叉积大于0,否则小于0.如果两个向量共线(方向相同),那么叉积等于0(三角形退化成为线段)。不难发现,叉积不满足交换律。事实上,cross(v,w)=-cross(w,v)。在坐标系下,两个向量的叉积等于xAyB-xByA。

  位置。当我们把叉积和点积组合在一起时,我们便可以细致地判断两个向量的位置关系。第一个向量v总是水平向右的,那么另外一个点就可以用这样的方式确定位置关系(点积符号,叉积符号)。例如,当w在第二象限时点积为负但叉积均为正,用(-,+)表示。

  旋转。向量可以绕起点旋转,公式为x= xcosa-ysina , y= xsina+ycosa。其中a为逆时针旋转的角。

扫描二维码关注公众号,回复: 7345576 查看本文章

  单位法线。旋转90°后把长度归一化即可。

  以上内容采用如下代码实现:

 1 struct Point
 2 {
 3     double x,y;
 4     Point(double x=0, double y=0):x(x),y(y) {}//构造函数,方便编写代码
 5 };
 6 typedef Point Vector;//别名
 7 //向量+向量=向量,点+向量=点
 8 Vector operator + (Vector A, Vector B){return Vector(A.x+B.x,A.y+B.y);}
 9 //点-点=向量
10 Vector operator - (Vector A, Vector B){return Vector(A.x-B.x,A.y-B.y);}
11 //向量*数=向量
12 Vector operator * (Vector A, double p){return Vector(A.x*p,A.y*p);}
13 //向量/数=向量
14 Vector operator / (Vector A, double p){return Vector(A.x/p,A.y/p);}
15 
16 bool operator < (const Point& a, const Point& b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
17 
18 const double eps = 1e-10;
19 int dcmp(double x)
20 {
21     if (fabs(x) < eps) return 0;
22     else return x < 0 ? -1 : 1;
23 }
24 
25 bool operator == (const Point& a, const Point &b){return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}
26 
27 //计算点积、向量长度、夹角函数
28 double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;}
29 double Length(Vector A){return sqrt(Dot(A,A));}
30 double Angle(Vector A, Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}
31 
32 //计算叉积
33 double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
34 double Area2(Point A, Point B, Point C){return Cross(B-A,C-A);}
35 
36 //计算旋转和单位法向量
37 //rad为弧度
38 Vector Rotate(Vector A, double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
39 Vector Normal(Vector A)
40 {
41     double L =Length(A);
42     return Vector(-A.y/L,A.x/L);
43 }

  点和直线。采用参数方程表示直线。直线上一点P0和方向向量v表示

猜你喜欢

转载自www.cnblogs.com/125418a/p/11575865.html