线段,射线,直线的关系

二维坐标系

#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;
}

一、直线与直线的关系

1.判断两直线的关系

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)

2.计算两直线的交点

当直线相交时

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);
        }
    }
}

二、判断直线与射线的关系

1.判断直线与射线的关系

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;
    }
}

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);
}

三、判断直线与线段的关系

1.直线与线段的关系

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;
    }
}

2.直线与线段的交点

已知线段与直线有交点,则直接可以求直线相交的方式计算交点

Point Line_SegmentIntersection(Line L, Line S)//直线与线段的交点,states是两条直线的状态
{
    int state=CheckLineIntersection(L,S);
    return LineIntersection(L,S,state);
}

四、射线与射线的关系 //暂时空缺

 

五、射线与线段的关系

1.射线与线段的关系

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;
    }
}

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);
}

六、线段与线段的关系

1.线段与线段的关系

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;
}

2.线段与线段的交点

已知线段有交点,则直接可以求直线相交的方式计算交点

Point SegmentIntersection(Line S1, Line S2)//线段与线段的交点,states是两条直线的状态
{
    int state=CheckLineIntersection(S1,S2);
    return LineIntersection(S1,S2,state);
}

 

 

你可能感兴趣的:(模板,知识点,计算几何)