struct Point{
double x, y;Point(double x =0,double y =0):x(x),y(y){
}};typedef Point Vector;
Vector operator+(Vector A, Vector B){
returnVector(A.x+B.x, A.y+B.y);}
Vector operator-(Point A, Point B){
returnVector(A.x-B.x, A.y-B.y);}
Vector operator*(Vector A,double p){
returnVector(A.x*p, A.y*p);}
Vector operator/(Vector A,double p){
returnVector(A.x/p, A.y/p);}booloperator<(const Point& a,const Point& b){
if(a.x == b.x)return a.y < b.y;return a.x < b.x;}constdouble eps =1e-6;intsgn(double x){
if(fabs(x)< eps)return0;if(x <0)return-1;return1;}booloperator==(const Point& a,const Point& b){
if(sgn(a.x-b.x)==0&&sgn(a.y-b.y)==0)returntrue;returnfalse;}doubleDot(Vector A, Vector B){
return A.x*B.x + A.y*B.y;}doubleLength(Vector A){
returnsqrt(Dot(A, A));}doubleAngle(Vector A, Vector B){
returnacos(Dot(A, B)/Length(A)/Length(B));}doubleCross(Vector A, Vector B){
return A.x*B.y-A.y*B.x;}doubleArea2(Point A, Point B, Point C){
returnCross(B-A, C-A);}
Vector Rotate(Vector A,double rad){
//rad为弧度 且为逆时针旋转的角returnVector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));}
Vector Normal(Vector A){
//向量A左转90°的单位法向量double L =Length(A);returnVector(-A.y/L, A.x/L);}boolToLeftTest(Point a, Point b, Point c){
returnCross(b - a, c - b)>0;}
2.2 复数黑科技
#include<complex>usingnamespace std;typedef complex<double> Point;typedef Point Vector;//复数定义向量后,自动拥有构造函数、加减法和数量积constdouble eps =1e-9;intsgn(double x){
if(fabs(x)< eps)return0;if(x <0)return-1;return1;}doubleLength(Vector A){
returnabs(A);}doubleDot(Vector A, Vector B){
//conj(a+bi)返回共轭复数a-bireturnreal(conj(A)*B);}doubleCross(Vector A, Vector B){
returnimag(conj(A)*B);}
Vector Rotate(Vector A,double rad){
return A*exp(Point(0, rad));//exp(p)返回以e为底复数的指数}
3 点与线
3.1 直线定义
struct Line{
//直线定义
Point v, p;Line(Point v, Point p):v(v),p(p){
}
Point point(double t){
//返回点P = v + (p - v)*treturn v +(p - v)*t;}};
3.2 求两直线交点
//调用前需保证 Cross(v, w) != 0
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
Vector u = P-Q;double t =Cross(w, u)/Cross(v, w);return P+v*t;}
3.3 求点到直线距离
//点P到直线AB距离doubleDistanceToLine(Point P, Point A, Point B){
Vector v1 = B-A, v2 = P-A;returnfabs(Cross(v1, v2)/Length(v1));}//不去绝对值,得到的是有向距离
3.4 求点到线段距离
//点P到线段AB距离公式doubleDistanceToSegment(Point P, Point A, Point B){
if(A == B)returnLength(P-A);
Vector v1 = B-A, v2 = P-A, v3 = P-B;if(dcmp(Dot(v1, v2))<0)returnLength(v2);if(dcmp(Dot(v1, v3))>0)returnLength(v3);returnDistanceToLine(P, A, B);}
3.5 求点在直线上的投影点
//点P在直线AB上的投影点
Point GetLineProjection(Point P, Point A, Point B){
Vector v = B-A;return A+v*(Dot(v, P-A)/Dot(v, v));}
3.6 判断点是否在线段上
//判断p点是否在线段a1a2上boolOnSegment(Point p, Point a1, Point a2){
returndcmp(Cross(a1-p, a2-p))==0&&dcmp(Dot(a1-p, a2-p))<0;}
3.7 判断两线段是否相交
//判断两线段是否相交boolSegmentProperIntersection(Point a1, Point a2, Point b1, Point b2){
double c1 =Cross(a2-a1, b1-a1), c2 =Cross(a2-a1, b2-a1);double c3 =Cross(b2-b1, a1-b1), c4 =Cross(b2-b1, a2-b1);//if判断控制是否允许线段在端点处相交,根据需要添加if(!sgn(c1)||!sgn(c2)||!sgn(c3)||!sgn(c4)){
bool f1 =OnSegment(b1, a1, a2);bool f2 =OnSegment(b2, a1, a2);bool f3 =OnSegment(a1, b1, b2);bool f4 =OnSegment(a2, b1, b2);bool f =(f1|f2|f3|f4);return f;}return(sgn(c1)*sgn(c2)<0&&sgn(c3)