点线相关
目录
1、点线的表示
2、常用常数和函数
3、点与矢量
4、点与点的距离
5、点与线的距离
6、点绕点旋转
7、点在直线的左侧还是右侧
8、过点作线的垂线
9、点到线的垂足
10、两条直线的交点
11、判断线段规范相交
12、线与线的夹角
1、点线的表示
//矢量和点的表示法相同
struct Point{
double x,y;
};
struct Line{
Point x,y;
};
2、常用常数和函数
double PI=acos(-1);
double INF=1e20;
double EPS=1e-6;
bool zero(double x)
{
return -EPS<x&&x<EPS;
}
bool lager(double a,double b)
{
return a-b>EPS;
}
bool less(double a,double b)
{
return b-a>EPS;
}
3、点与矢量
从A点指向B点的矢量AB可用B-A表示
将A点沿矢量p的方向移动矢量p长度的距离到B,B可以用A+p表示
4、点与点的距离
利用两点间矢量的长度
double dist(Point p,Point q)
{
return length(p-q);
}
5、点与线的距离
利用叉积求面积,然后除以底即为高
double dist(Point p,Line l)
{
return fabs((p-l.a)^(l.b-l.a))/length(l.b-l.a);
}
6、点绕点旋转
旋转矢量alpha角度使得AB到AC,求C点的坐标
Point rotate(Point b,Point a,double alpha)//返回C点坐标 alpha为弧度制
{
Cvector p=b-a;
double x=a.x+p.x*cos(alpha)-p.y*sin(alpha);
double y=a.y+p.x*sin(alpha)+p.y*cos(alpha);
return Point(x,y);
}
7、点在直线的左侧还是右侧
//判断p在直线a->b的哪一侧
int side(Point p,Point a,Point b)
{
double res=(b-a)^(p-a);
if(zero(res))
return 0;//p在ab上
else if(res>0)
return 1;//p在ab的左侧
else
return -1;//p在ab的右侧
}
8、过点作线的垂线
Line vertical(Point p,Line l)
{
return Line(p,p+(rotate(l.b,l.a,PI/2))-l.a);
}
9、点到线的垂足
利用点积求投影,进而求出垂足
应用:求对称点
Point foot(Point p,Line l)
{
return l.a+project(p-l.a,l.b-l.a)*unit(l.b-l.a);
}
10、两条直线的交点
Point intersect(Line l,Line m,string s)
{
double x=area(m.a-l.a,l.b-l.a);
double y=area(l.b-l.a,m.b-l.a);
if(zero(x+y))
{
if(zero(dist(l,m)))
s="重合";
else
s="平行";
return NULL;
}
return m.a+x/(x+y)*(m.b-m.a);
}
11、判断线段规范相交
即判断是否任一条线段的两个端点都分属另一条线段的两侧
//叉积
double cross(const Vector &v1,const Vector &v2)
{
return v1.x*v2.y-v2.x*v1.y;
}
bool IsFormalCross(Point p1,Point p2,Point P3,Point P4)
{
//判断p1->p2和p3->p4是否规范相交
return cross(p2-p1,p3-p1)*cross(p2-p1,p4,p1)<-EPS&&cross(p4-p3,p1-p3)*cross(p4-p3,p2-p3)<-EPS;
}
12、线与线的夹角
double angle(Line l,Line m)
{
return acos(fabs(project(l.b-l.a,m.b-m.a)/length(l.b-l.a)));
}