主要运用到向量间的点乘和叉乘.
const double eps = 1e-9;
// 1.精度
inline int sgn(double x) {
if(abs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
//向量
typedef struct Vector{
double x,y;
Vector(){x = 0,y = 0;}
Vector(double _x,double _y):x(_x),y(_y){}
bool operator < (const Vector &a) const {
return sgn(x-a.x) < 0 || (sgn(x-a.x)==0&&sgn(y-a.y)<0);
}
void print(){printf("%lf %lf\n",x,y);}
}Point;
//各种重载
Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator *(Vector a,double b){return Vector(a.x*b,a.y*b);}
Vector operator /(Vector a,double b){return Vector(a.x/b,a.y/b);}
bool operator ==(Vector a,Vector b){return sgn(a.x-b.x)==0&&sgn(a.y-b.y);}
double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}//点乘
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//叉乘
double Len(Vector a){return sqrt(Dot(a,a));}//a的模
double Len2(Vector a) {return Dot(a,a);} //a方
//线段类
struct Line{
Point s,t;
Line(){}
Line(Point a,Point b):s(a),t(b){}
bool operator <(Line a)const{
return sgn(Cross(t-s,a.t-a.s))>=0;
}
};
//向量旋转 rad
Vector Rotate(Vector a,double rad){
return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
//点到线距离
double DisTL(Point p,Point a,Point b){
Vector v1 = b - a, v2 = p - a;
return abs(Cross(v1,v2)/Len(v1));
}
//点到线段距离
double DisTS(Point p,Point a,Point b){
if(a == b) return Len(p-a);
Vector v1 = b - a, v2 = p - a, v3 = p - b;
if(sgn(Dot(v1,v2)) < 0) return Len(v2);
else if(sgn(Dot(v1,v3)) > 0) return Len(v3);
else return DisTL(p,a,b);
}
//点线位置关系
bool OnLeft(Line l,Point p) {
return sgn(Cross(l.t-l.s,p-l.s)) >= 0;
}
//点在线段上
bool OnSeg(Point p,Point a,Point b){
return DisTL(p,a,b)==0&&sgn(Dot(p-a,p-b))&&!(p==a)&&!(p==b);
}
//直线相交交点 面积求比例
Point LI(Line a,Line b){
Vector v = a.s-b.s, v2 = a.t-a.s v3 = b.t-b.s;
double t = Cross(v2,v)/Cross(v1,v2);
return a.s+v1*t;
}
// 直线与线段相交:端点叉积不同
bool isLSI(Line l1,Line l2){
Vector v=l1.t-l1.s,u=l2.s-l1.s,w=l2.t-l1.s;
return sgn(Cross(v,u))!=sgn(Cross(v,w));
}
//线段与线段相交
bool isSSI(Line l1,Line l2){
return isLSI(l1,l2)&&isLSI(l1,l2);
}