二维几何——线类:

这些代码未经过题目测试,存在安全隐患。。。。


struct Line
{
    Point s,e;
    Line(){}

    //两点
    Line(const Point ss,const Point ee)
    {
        s=ss,e=ee;
    }

    //点斜
    Line(const Point p,const double angle)
    {
        s=p;
        if(sgn(angle-pi/2)==0)
            e=(s+Point(0,1));
        else e=(s+Point(1,tan(angle)));
    }

    //ax+by+c=0
    Line(double a,double b,double c)
    {
        if(sgn(a)==0)
        {
            s=Point(0,-c/b);
            e=Point(1,-c/b);
        }
        else if(sgn(b)==0)
        {
            s=Point(-c/a,0);
            e=Point(-c/a,1);
        }
        else
        {
            s=Point(0,-c/b);
            e=Point(1,(-c-a)/b);
        }
    }

    void input(void)
    {
        s.input();
        e.input();
    }

    void output(void)
    {
        s.output();
        e.output();
    }

    //两点应该是由s——>e,
    //由x负向指向x正向。
    void adjust(void)
    {
        if(e<s) swap(s,e);
    }

    //判断两线段是否重合
    bool operator == (Line b)
    {
        adjust(),b.adjust();
        return (s==b.s)&&(e==b.e);
    }

    //求线段长度
    double len(void)
    {
        return s.dis(e);
    }

    //返回直线倾斜角
    //0<=angle<pi
    double angle(void)
    {
        double k=atan2(e.y-s.y,e.x-s.x);
        if(sgn(k)<0) k+=pi;
        if(sgn(k-pi)==0) k-=pi;
        return k;
    }

    //点和直线的关系
    //1 在左侧 (在s——>e的逆时针侧)
    //2 在右侧 (在s——>e的顺时针侧)
    //3 在直线上
    int relation(const Point &p)
    {
        int c=sgn((p-s)^(e-s));
        if(c<0) return 1;
        else if(c>0) return 2;
        else return 3;
    }

    //点是否在线段上
    bool p_is_on_seg(const Point &p)
    {
        return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0;
    }

    //两向量平行,对应直线平行或者重合
    bool parallel(const Line &v)
    {
        return sgn((e-s)^(v.e-v.s))==0;
    }

    //两线段相交判断
    //2 规范相交
    //1 非规范相交
    //0 不相交
    int seg_cross_seg(const Line &v)
    {
        int d1=sgn((e-s)^(v.s-s));
        int d2=sgn((e-s)^(v.e-s));
        int d3=sgn((v.e-v.s)^(s-v.s));
        int d4=sgn((v.e-v.s)^(e-v.s));
        if((d1^d2)==-2&&(d3^d4)==-2) return 2;
        d1=(d1==0&&sgn((v.s-s)*(v.s-e))<=0);
        d2=(d2==0&&sgn((v.e-s)*(v.e-e))<=0);
        d3=(d3==0&&sgn((s-v.s)*(s-v.e))<=0);
        d4=(d4==0&&sgn((e-v.s)*(e-v.e))<=0);
        return d1||d2||d3||d4;
    }

    //直线和线段相交
    //2 规范相交
    //1 非规范相交
    //0 不相交
    int line_cross_seg(const Line &v)
    {
        int d1=sgn((e-s)^(v.s-s));
        int d2=sgn((e-s)^(v.e-s));
        if(d1^d2==-2) return 2;
        return (d1==0||d2==0);
    }

    //两直线的关系
    //0 平行
    //1 重合
    //2 相交
    int line_cross_line(Line &v)
    {
        if((*this).parallel(v))
            return v.relation(s)==3;
        return 2;
    }

    //求两直线的交点
    //要保证两直线不平行或重合
    Point cross_point(Line v)
    {
        double a1=(v.e-v.s)^(s-v.s);
        double a2=(v.e-v.s)^(e-v.s);
        return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    }

    //点到直线的距离
    double dis_point_to_line(const Point &p)
    {
        return abs((p-s)^(e-s))/len();
    }

    //点到线段的距离
    double dis_point_to_seg(const Point &p)
    {
        if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
            return min(p.dis(s),p.dis(e));
        return dis_point_to_line(p);
    }

    //返回线段到线段的距离
    //前提是两线段不相交,相交就是0了
    double dis_seg_to_seg(Line &v)
    {
        double s1=min(dis_point_to_seg(v.s),dis_point_to_seg(v.e));
        double s2=min(v.dis_point_to_seg(s),v.dis_point_to_seg(e));
        return min(s1,s2);
    }

    //返回点p在直线上的投影
    Point point_proj_line(Point &p)
    {
        return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
    }

    //返回点p关于直线的对称点
    Point point_sym_line(Point &p)
    {
        Point q=point_proj_line(p);
        return Point(2*q.x-p.x,2*q.y-p.y);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值