平面几何–坐标值的精度编程语言写法
实数 用double类型精度高
偏差值eps 一般是10的-8次方
const double pi = acos(-1.0); //高精度圆周率
const double eps = 1e-8; //偏差值,有时用1e-10
判断浮点数是否等于0 = 看是否小于eps
int sgn(double x){ //判断x是否等于0
if(fabs(x) < eps) return 0;
else return x<0?-1:1;
}
比较两个浮点数 = 看两个数的差是否接近eps
int dcmp(double x, double y){ //比较两个浮点数:0 相等;-1 小于;1 大于
if(fabs(x - y) < eps) return 0;
else return x<y ?-1:1;
}
点的表示
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
};
结构体函数
结构体函数的意义:由于由于结构体内的变量无法初始化,所以
注意结构体函数的名字和结构体相同.
两点之间的距离
double Dist(Point A,Point B){
return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));
}
向量
向量的表示,在形式上与点的表示完全一样,可以用点的数据结构来表示向量:typedef Point Vector 注意,向量并不是一个有向线段,只是表示方向和大小。因此,向量平移后仍然不变。
加:点与点的加法运算没有意义;点与向量相加得到另一个点;向量与向量相加得到另外一个向量。 Point operator + (Point B){return Point(x+B.x,y+B.y);}
减:两个点的差是一个向量;向量 AA 减 BB,得到由 BB 指向 AA 的向量。Point operator - (Point B){return Point(x-B.x,y-B.y);}
乘:向量与实数相乘得到等比例放大的向量。 Point operator * (double k){return Point(x*k,y*k);}
除:向量与实数相除得到等比例缩小的向量。 Point operator / (double k){return Point(x/k,y/k);}
等于: bool operator == (Point B){return sgn(x-B.x)==0 && sgn(y-B.y)==0;}
点积
A•B=∣A∣∣B∣cosθ,其中 θ 为 A、B 之间的夹角。
ab=axbx+ayby
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}
点积的应用
1.判断 A 与 B 的夹角是钝角还是锐角
点积有正负,利用正负号,可以判断向量的夹角:
若 dot(A, B) > 0,A与 B 的夹角为锐角;
若 dot(A, B) < 0,A与 B 的夹角为钝角;
若 dot(A, B) = 0,A与 B 的夹角为直角。
2.求向量A的长度
double Len(Vector A){return sqrt(Dot(A,A));}
求长度的平方
ouble Len2(Vector A){return Dot(A,A);}
求向量A,B的夹角
double Angle(Vector A,Vector B){
return acos(Dot(A,B)/Len(A)/Len(B));
}
叉积
A×B=∣A∣∣B∣sinθ
double Cross(Vector A,Vector B){return A.x*B.y – A.y*B.x;}
注意函数 Cross() 中的 A、B 是有顺序的,叉积有正负,A×B 与B×A 相反。
叉积的基本应用
1.判断向量A,B的方向关系
若A×B>0,B 在 A 的逆时针方向;
若A×B<0,B 在 A 的顺时针方向;
若A×B=0,B 与 A共线,可能是同方向的,也可能是反方向的。
2.计算平行四边形有向面积
double Area2(Point A,Point B,Point C){
return Cross(B-A, C-A);//叉积
}
3. 计算三点构成的三角形的面积
大佬:三个点 A、B、C所构成的三角形面积,等于平行四边形面积 Area2(A, B, C) 的二分之一。
4. 向量旋转
大佬:使向量 (x, y)(x,y) 绕起点逆时针旋转,设旋转角度为 θθ,那么旋转后的向量(x’, y’)(x’,y’) 满足:
`x’ = xcosθ – ysinθ``
``y’ = xsinθ + ycosθ`
代码如下,设向量 AA 逆时针旋转角度为 radrad:
Vector Rotate(Vector A, double rad){
return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}
不过有个特殊情况是旋转 9090 度:
逆时针旋转 9090 度:Rotate(A, pi/2)
,返回 Vector(-A.y, A.x)
;
顺时针旋转 9090 度:Rotate(A, -pi/2)
,返回 Vector(A.y, - A.x)
。
有时需要求单位法向量,即逆时针转 9090 度,然后取单位值。代码如下:
Vector Normal(Vector A){
return Vector(-A.y/Len(A), A.x/Len(A));
}
copy
5. 用叉积检查两个向量是否平行或重合
bool Parallel(Vector A, Vector B){
return sgn(Cross(A,B)) == 0;
}