#include
using namespace std;
#define LL long long
#define EPS 1e-8
struct Point//二维坐标点
{
double x;
double y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (const Point &rh) const
{
return Point(x+rh.x, y+rh.y);
}
Point operator - (const Point &rh)const
{
return Point(x-rh.x, y-rh.y);
}
bool operator == (const Point &rh)const
{
if(x==rh.x && y==rh.y)
return true;
return false;
}
};
struct Line//表示直线上已知两点或者表示线段
{
Point a;
Point b;
Line(){}
Line(Point a,Point b):a(a),b(b){}
};
double Cross(Point a, Point b)//叉积
{
return a.x*b.y-b.x*a.y;
// double t=a.x*b.y-b.x*a.y;
// if(t>0)
// return 1;//锐角
// else if(t<0)
// return -1;//钝角
// else
// return 0;//平行
}
int main()
{
return 0;
}
int CheckLineIntersection(Line L1, Line L2)//判断直线是否有交点
{
// -1表示直线重合
// 0表示都平行于y轴,没有交点
// 1表示L2平行于y轴
// 2表示L1平行于y轴
// 3表示不平行于y轴且两条直线也不平行或重合
// 4表示不平行于y轴但两条直线平行
int state=0;
double KL1,KL2;
if( fabs(L1.a.x-L1.b.x)>EPS )//直线L1不平行于y轴没有斜率
{
KL1=(L1.b.y-L1.a.y)/(L1.b.x-L1.a.x);//斜率L1
state+=1;
}
if( fabs(L2.a.x-L2.b.x)>EPS )//直线L1不平行于y轴没有斜率
{
KL2=(L2.b.y-L2.a.y)/(L2.b.x-L2.a.x);//斜率L2
state+=2;
}
if(state==0)
{
if( fabs(L1.a.x-L2.a.x)
当直线相交时
Point LineIntersection(Line L1, Line L2, int state)//先判断是否有交点,并交两条线段的类型当参数输入,返回直线交点
{
switch(state)
{
case 1://L1存在斜率, L2平行Y轴
{
double x=L2.a.x;
double KL1=(L1.b.y-L1.a.y)/(L1.b.x-L1.a.x);//斜率L1
double y=(L2.a.x-L1.a.x)*KL1+L1.a.y;
return Point(x,y);
}
case 2://L2存在斜率, L1平行Y轴
{
double x=L1.a.x;
double KL2=(L2.b.y-L2.a.y)/(L2.b.x-L2.a.x);//斜率L2
double y=(L1.a.x-L2.a.x)*KL2+L2.a.y;
return Point(x,y);
}
case 3://都有斜率
{
double KL1=(L1.b.y-L1.a.y)/(L1.b.x-L1.a.x);//斜率L1
double KL2=(L2.b.y-L2.a.y)/(L2.b.x-L2.a.x);//斜率L2
double x=(L1.a.x*KL1-L2.a.x*KL2-L1.a.y+L2.a.y)/(KL1-KL2);
double y=KL1*x-KL1*L1.a.x+L1.a.y;
return Point(x,y);
}
}
}
int CheckLine_Rays(Line L, Point c, Point v)//直线L,与以c为起点,v为方向的射线的关系
{
// -1表示射线直线重合
// 0表示射线直线平行
// 1表示射线直线相交
// 2表示射线直线不相交
if( fabs(Cross(L.b-L.a, v)) < EPS)//直线与向量v平行
{
if( fabs(Cross(L.a-c, L.b-c)) < EPS)//射线与直线重合
return -1;
return 0;
}
else
{
if( Cross(c-L.a, L.b-L.a)*Cross(L.b-L.a,v) >=0 )//直线射线相交
return 1;
return 2;
}
}
当射线与直线相交时,可以用求两直线交点的方式计算
Point Line_RaysIntersection(Line L,Point c,Point v)
{
Line L2(c,c+v);//c+v为射线上一点
int state=CheckLineIntersection(L,L2);
return LineIntersection(L,L2,state);
}
int CheckLine_SegmentIntersection(Line L, Line S)//直线与线段S的关系
{
// -1表示线段直线重合
// 0表示线段直线平行
// 1表示线段直线相交
// 2表示线段直线不相交
if( fabs(Cross(L.b-L.a, S.b-S.a)) < EPS)//直线与线段平行
{
if( fabs(Cross(L.a-S.a, L.b-S.a)) < EPS)//射线与直线重合
return -1;
return 0;
}
else
{
double tmp = Cross(L.b-L.a, S.a-L.a)*Cross(L.b-L.a, S.b-L.a);
if( tmp < 0.0 || fabs(tmp) < EPS )
return 1;
return 2;
}
}
已知线段与直线有交点,则直接可以求直线相交的方式计算交点
Point Line_SegmentIntersection(Line L, Line S)//直线与线段的交点,states是两条直线的状态
{
int state=CheckLineIntersection(L,S);
return LineIntersection(L,S,state);
}
int CheckRays_SegmentIntersection(Line S, Point c, Point v)//以c为起点方向为v的射线 是否经过线段S
{
// -1表示线段重合
// 0表示线段平行
// 1表示线段相交
// 2表示线段不相交
if( fabs(Cross(S.b-S.a, v)) =0 || v.x*(S.b.x-c.x)>=0) // 点c在线段S上,有重合部分
return -1;
else
return 0;
}
else
{
if( Cross(c-S.a, S.b-S.a)*Cross(S.b-S.a,v)>=0)//c为起点,v为方向的射线经过线段S
{
if(Cross(S.a-c, v)*Cross(S.b-c, v)<=0)//c为起点,v为方向的射线经过线段S,即向量v在向量a-c与b-c之间
return 1;
else
return 2;
}
else
return 2;
}
}
已知线段与射线有交点,则直接可以求直线相交的方式计算交点
Point Rays_SegmentIntersection(Line S,Point c,Point v)//直线L,与以c为起点,v为方向的射线的交点
{
Line L2(c,c+v);//c+v为射线上一点
int state=CheckLineIntersection(S,L2);
return LineIntersection(S,L2,state);
}
bool CheckSegmentIntersection(Line S1,Line S2)
{
double t1=Cross(S1.b-S1.a,S2.a-S1.a);
double t2=Cross(S1.b-S1.a,S2.b-S1.a);
double t3=Cross(S1.a-S2.a,S2.b-S2.a);
double t4=Cross(S1.b-S2.a,S2.b-S2.a);
if(t1*t2<=0 && t3*t4<=0)
return true;
return false;
}
已知线段有交点,则直接可以求直线相交的方式计算交点
Point SegmentIntersection(Line S1, Line S2)//线段与线段的交点,states是两条直线的状态
{
int state=CheckLineIntersection(S1,S2);
return LineIntersection(S1,S2,state);
}