constint N=1e6+5;struct point
{double x,y;};struct line
{
point p1,p2;} s[N];doubleheight(line a,int x)///计算直线某点y坐标{if(a.p1.x==a.p2.x)return a.p1.y;double k=(a.p1.y-a.p2.y)*1.0/(a.p1.x-a.p2.x);double b=a.p1.y-k*a.p1.x;return k*x+b;}doublePoint_distance(point a,point b)///线段距离{returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
bool circle(point a,double r,point b)///是否在圆内{returnPoint_distance(a,b)<=r;}doubleline_sin(point a,point b)///线段长度不能为0{return(a.y-b.y)/Point_distance(a,b);}doubleline_cos(point a,point b)///线段长度不能为0{return(a.x-b.x)/Point_distance(a,b);}
坐标+向量
constdouble eps =1e-7;constdouble pi =acos(-1.0);intdcmp(double x){if(fabs(x)< eps)return0;return(x <0?-1:1);}inlinedoublesqr(double x){return x * x;}//*************点struct Point
{double x, y;Point(double _x =0,double _y =0):x(_x),y(_y){}voidinput(){
cin>>x>>y;}voidoutput(){printf("%.2f %.2f\n", x, y);}
bool operator==(const Point &b)const{return(dcmp(x - b.x)==0&&dcmp(y - b.y)==0);}
bool operator<(const Point &b)const{return(dcmp(x - b.x)==0?dcmp(y - b.y)<0: x < b.x);}
Point operator+(const Point &b)const{returnPoint(x + b.x, y + b.y);}
Point operator-(const Point &b)const{returnPoint(x - b.x, y - b.y);}
Point operator*(double a){returnPoint(x * a, y * a);}
Point operator/(double a){returnPoint(x / a, y / a);}doublelen2()//返回长度的平方{returnsqr(x)+sqr(y);}doublelen()//返回长度{returnsqrt(len2());}
Point change_len(double r)//转化为长度为r的向量{double l =len();if(dcmp(l)==0)return*this;//零向量返回自身
r /= l;returnPoint(x * r, y * r);}
Point rotate_left()//顺时针旋转90度{returnPoint(-y, x);}
Point rotate_right()//逆时针旋转90度{returnPoint(y,-x);}
Point rotate(Point p,double ang)//绕点p逆时针旋转ang{
Point v =(*this)- p;double c =cos(ang), s =sin(ang);returnPoint(p.x + v.x * c - v.y * s, p.y + v.x * s + v.y * c);}
Point normal()//单位法向量{double l =len();returnPoint(-y / l, x / l);}};doublecross(Point a, Point b)//叉积{return a.x * b.y - a.y * b.x;}doubledot(Point a, Point b)//点积{return a.x * b.x + a.y * b.y;}doubledis(Point a, Point b)//两个点的距离{
Point p = b - a;return p.len();}doubledegree_rad(double ang)//角度转化为弧度{return ang /180* pi;}doublerad_degree(double rad)//弧度转化为角度{return rad / pi *180;}doublerad(Point a, Point b)//两个向量的夹角{returnfabs(atan2(fabs(cross(a, b)),dot(a, b)));}
bool parallel(Point a, Point b)//向量平行{double p =rad(a, b);returndcmp(p)==0||dcmp(p - pi)==0;}
Point Circum(Point a,Point b,Point c){//已知圆上三点求圆心double x1=a.x,y1=a.y;double x2=b.x,y2=b.y;double x3=c.x,y3=c.y;double a1=2*(x2-x1);double b1=2*(y2-y1);double c1=x2*x2+y2*y2-x1*x1-y1*y1;double a2=2*(x3-x2);double b2=2*(y3-y2);double c2=x3*x3+y3*y3-x2*x2-y2*y2;double x=(c1*b2-c2*b1)/(a1*b2-a2*b1);double y=(a1*c2-a2*c1)/(a1*b2-a2*b1);returnPoint(x,y);}
直线+线段
//************直线 线段struct Line
{
Point s, e;//直线的两个点double k;//极角 范围[-pi,pi]Line(){}Line(Point _s, Point _e){
s = _s, e = _e;
k =atan2(e.y - s.y, e.x - s.x);}// ax+by+c = 0Line(double a,double b,double c){if(dcmp(a)==0){
s =Point(0,-c / b);
e =Point(1,-c / b);}elseif(dcmp(b)==0){
s =Point(-c / a,0);
e =Point(-c / a,1);}else{
s =Point(0,-c / b);
e =Point(1,(-c - a)/ b);}get_angle();}//一个点和倾斜角确定直线Line(Point p,double ang){
k = ang;
s = p;if(dcmp(ang - pi /2)==0){
e = s +Point(0,1);}else
e = s +Point(1,tan(ang));}voidinput(){
s.input();
e.input();}voidoutput(){printf("%.2f,%.2f %.2f,%.2f\n", s.x, s.y, e.x, e.y);}voidadjust(){if(e < s)swap(e, s);}doublelength()//求线段长度{returndis(s, e);}voidget_angle(){
k =atan2(e.y - s.y, e.x - s.x);}doubleangle()//直线的倾斜角{if(dcmp(k)<0)
k += pi;if(dcmp(k - pi)==0)
k -= pi;return k;}
Point operator&(const Line &b)const//直线的交点(保证存在){
Point res = s;double t =(cross(s - b.s, b.s - b.e))/cross(s - e, b.s - b.e);
res.x +=(e.x - s.x)* t;
res.y +=(e.y - s.y)* t;return res;}};intrelation(Point p, Line l)//点和直线的关系{// 1:在左侧 2:在右侧 3:在直线上int c =dcmp(cross(p - l.s, l.e - l.s));if(c <0)return1;elseif(c >0)return2;elsereturn3;}
bool point_on_halfline(Point p, Line l)//判断点在射线上{int id =relation(p, l);if(id !=3)return0;returndcmp(dot(p - l.s, l.e - l.s))>=0;}
bool point_on_seg(Point p, Line l)//判断点在线段上{returndcmp(cross(p - l.s, l.e - l.s))==0&&dcmp(dot(p - l.s, p - l.e))<=0;//如果忽略端点交点改成小于号就好了}
bool parallel(Line a, Line b)//直线平行{returnparallel(a.e - a.s, b.e - b.s);}intseg_cross_seg(Line a, Line v)//线段相交判断{// 2:规范相交 1:不规范相交 0:不相交int d1 =dcmp(cross(a.e - a.s, v.s - a.s));int d2 =dcmp(cross(a.e - a.s, v.e - a.s));int d3 =dcmp(cross(v.e - v.s, a.s - v.s));int d4 =dcmp(cross(v.e - v.s, a.e - v.s));if((d1 ^ d2)==-2&&(d3 ^ d4)==-2)return2;return(d1 ==0&&dcmp(dot(v.s - a.s, v.s - a.e))<=0)||(d2 ==0&&dcmp(dot(v.e - a.s, v.e - a.e))<=0)||(d3 ==0&&dcmp(dot(a.s - v.s, a.s - v.e))<=0)||(d4 ==0&&dcmp(dot(a.e - v.s, a.e - v.e))<=0);}intline_cross_seg(Line a, Line v)//直线和线段相交判断 a直线v线段{// 2:规范相交 1:非规范相交 0:不相交int d1 =dcmp(cross(a.e - a.s, v.s - a.s));int d2 =dcmp(cross(a.e - a.s, v.e - a.s));if((d1 ^ d2)==-2)return2;return(d1 ==0|| d2 ==0);}intline_cross_line(Line a, Line v)//直线相交判断{// 0:平行 1:重合 2:相交if(parallel(a, v))returnrelation(a.e, v)==3;return2;}
Point line_intersection(Line a, Line v)//直线交点{//调用前确保有交点double a1 =cross(v.e - v.s, a.s - v.s);double a2 =cross(v.e - v.s, a.e - v.s);returnPoint((a.s.x * a2 - a.e.x * a1)/(a2 - a1),(a.s.y * a2 - a.e.y * a1)/(a2 - a1));}intseg_intersectiong(Line a, Line b, Point &p)//求线段交点{// 0:没有交点 1:规范相交 2:非规范相交//调用前确包只有一个交点int rel =seg_cross_seg(a, b);if(rel ==0)return0;int cnt =0;if(rel ==1){if(point_on_seg(a.e, b))
p = a.e, cnt++;if(point_on_seg(a.s, b))
p = a.s, cnt++;if(point_on_seg(b.e, a))
p = b.e, cnt++;if(point_on_seg(b.s, a))
p = b.s, cnt++;return2;}
p =line_intersection(a, b);return1;}doublepoint_to_line(Point p, Line a)//点到直线的距离{returnfabs(cross(p - a.s, a.e - a.s)/ a.length());}doublepoint_to_seg(Point p, Line a)//点到线段的距离{if(dcmp(dot(p - a.s, a.e - a.s))<0||dcmp(dot(p - a.e, a.s - a.e))<0)returnmin(dis(p, a.e),dis(p, a.s));returnpoint_to_line(p, a);}
Point projection(Point p, Line a)//点在直线上的投影{return a.s +(((a.e - a.s)*dot(a.e - a.s, p - a.s))/(a.e - a.s).len2());}
Point symmetry(Point p, Line a)//点关于直线的对称点{
Point q =projection(p, a);returnPoint(2* q.x - p.x,2* q.y - p.y);}