计算几何的模板实在是太臭太长了....
直接粘代码, 大部分需要解释的都已经注释好了, 所以应该没什么问题.....本来很多东西就是高中知识嘛(并不)
包含有如下函数(和定义):
1.数字的符号判断(别问我为啥计算几何有这么个东西)
2.点与向量的结构体定义与部分符号的重载
3.直线与线段的结构体定义
4.点是否在直线上 与 直线上距离给定点最近的点
5.点是否在线段上 与 线段上距离给定点最近的点
6.两条线段是否相交 与 一条线段和一条直线是否相交
7.求两直线交点
p.s 这都啥玩意儿......这么长是要抄多久啊
int sign(double x)
{//一个很不起眼但是很重要的函数
if(x==0) return 0;
return x>0?1:-1;
}
struct dot{
double x,y;
dot(double xx=0,double yy=0){//默认初始化为原点 (0,0)
x=xx;y=yy;
}
dot operator - (const dot &p){//可以直接当成两个点形成一个向量
return dot(x-p.x,y-p.y);
}
dot operator + (const dot &p){//两点(向量)相加
return dot(x+p.x,y+p.y);
}
dot operator * (const double &p){//向量扩大p倍
return dot(x*p,y*p);
}
dot operator / (const double &p){//向量缩小p倍
return dot(x/p,y/p);
}
int operator *(const dot &p){//点积
//通常用于向量之间的计算
//注意左右(不满足交换律)
return x*p.x+y*p.y;
}
int operator ^(const dot &p){//叉积
//在二维平面上面,叉积相乘只能有模,因为两个二维向量作叉积后新向量方向是垂直于原平面的,即直接跳到了三维空间
//res=0 则a和b平行,但是可能同向也可能反向
//res>0 则向量a方向在b的顺时针那一边,否则就是逆时针那边
//res的绝对值意义是两向量共起点后组成的平行四边形的面积
return x*p.y-y*p.x;
}
double length(){//向量的模或者点距离
return sqrt(x*x+y*y);
}
};
typedef dot vec;//向量的表示跟点一样,都是有序实数对
struct line{//直线
double a,b,c;//Ax+By+C=0;
//ABC不唯一!
dot s,e;//直线上两个点,或者直接当成线段来用
line()
{
}
line(dot start,dot end){//两点式
s=start; e=end;
a=e.y-s.y; b=s.x-e.x; c=e^s;
}
};
typedef line segment;
bool dot_on_line(dot d,line l){//点是否在直线上
if((l.a*d.x+l.b*d.y+l.c)==0) return true;
else return false;
}
dot dot_to_line(dot p,line l){//直线上离给顶点最近的点
double t=((p-l.s)*(l.e-l.s))/((l.e-l.s)*(l.e-l.s));
return dot(l.s.x+(l.e.x-l.s.x)*t,l.s.y+(l.e.y-l.s.y));
}
bool dot_on_segment(dot p,line l){//点是否在线段上
return
sign((l.s-p)^(l.e-p))==0&&
sign((p.x-l.s.x)*(p.x-l.e.x))<=0&&
sign((p.y-l.s.y)*(p.y-l.e.y))<=0;
}
dot dot_to_segment(dot p,line l){//线段上离给顶点最近的点
double t=((p-l.s)*(l.e-l.s))/((l.e-l.s)*(l.e-l.s));
if(t>=0&&t<=1)
return dot(l.s.x+(l.e.x-l.s.x)*t,l.s.y+(l.e.y-l.s.y)*t);
else if(dot(l.s-p).length()<dot(l.e-p).length()) return l.s;
else return l.e;
}
bool segment_inter(segment l1,segment l2){//线段是否相交
return
max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
sign((l2.s-l1.e)^(l1.s-l1.e))*sign((l2.e-l1.e)^(l1.s-l1.e))<=0&&
sign((l1.s-l2.e)^(l2.s-l2.e))*sign((l1.e-l2.e)^(l2.s-l2.e))<=0;
}
bool line_segment_inter(line l1,segment l2){//直线l1与线段l2是否相交
return sign((l2.s-l1.e)^(l1.s-l1.e))*sign((l2.e-l1.e)^(l1.s-l1.e))<=0;
}
dot intersection(line l1,line l2)
{//求两直线交点(线段亦可,如果线段相交了的话)
dot ret = l1.s;
double t = ((l1.s.x-l2.s.x)*(l2.s.y-l2.e.y)-(l1.s.y-l2.s.y)*(l2.s.x-l2.e.x))/((l1.s.x-l1.e.x)*(l2.s.y-l2.e.y)-(l1.s.y-l1.e.y)*(l2.s.x-l2.e.x));
ret.x += (l1.e.x-l1.s.x)*t;
ret.y += (l1.e.y-l1.s.y)*t;
return ret;
}