幾何模板判斷線段與直線相交模板

判斷線段與直線是否相交html

  對於線段相交的問題網上模板一大堆,但線段與直線相交的卻不多,作幾何計算的時候偶爾須要用到,若是沒有相關的模板每每難如下手。這裏就關於線段與直線相交的問題整理出一份模板,但願有所幫助。如有不足之處,請路過的大牛門不惜賜教。c++

  對於線段相交問題有兩種版本:ide

       ①  包括端點相交和部分重合函數

       ②  不包括端點相交和部分重合spa

  那麼對於直線與線段問題一樣能夠分爲兩種版本:code

       ①  包括端點(線段端點)相交和重合htm

        ②  不包括端點和重合blog


    原理:判斷線段兩個端點是否在直線異側ip


  預備函數:
it

struct point//定義點
{
    double x,y;
    point() {}
    point(double _x,double _y)
    {
        x=_x,y=_y;
    }
    point operator -(const point &b)const
    {
        return point(x-b.x,y-b.y);
    }
    double operator ^(const point &b)const
    {
        return x*b.y-y*b.x;
    }
    double operator *(const point &b)const
    {
        return x*b.x+y*b.y;
    }
} ;
struct line//線
{
    point a,b;
};
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    return 1;
}

  叉積

double mult(point p0,point p1,point p2)//叉積
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

  版本一:  判斷兩點(p1,p2)是否在直線異側,不包括端點和重合

bool opposite_side(point p1,point p2,point l1,point l2)
{
    return mult(l1,p1,l2)*mult(l1,p2,l2)<-eps;
}

  版本二:  判斷線段l1與直線l2是否相交,包括端點相交

bool seg_inter_line(line l1,line l2)
{
    return sgn((l1.a-l2.b)^(l2.a-l2.b))*sgn((l1.b-l2.b)^(l2.a-l2.b))<=0;
}

  test:
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
struct point//定義點
{
    double x,y;
    point() {}
    point(double _x,double _y)
    {
        x=_x,y=_y;
    }
    point operator -(const point &b)const
    {
        return point(x-b.x,y-b.y);
    }
    double operator ^(const point &b)const
    {
        return x*b.y-y*b.x;
    }
    double operator *(const point &b)const
    {
        return x*b.x+y*b.y;
    }
} ;
struct line//線
{
    point a,b;
};
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    return 1;
}
double mult(point p0,point p1,point p2)//叉積
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool opposite_side(point p1,point p2,point l1,point l2)
{
    return mult(l1,p1,l2)*mult(l1,p2,l2)<-eps;
}
bool seg_inter_line(line l1,line l2)
{
    return sgn((l1.a-l2.b)^(l2.a-l2.b))*sgn((l1.b-l2.b)^(l2.a-l2.b))<=0;
}
bool inter(point s1,point e1,point s2,point e2)//判斷線段相交
{
//    return opposite_side(s1,e1,s2,e2) && opposite_side(s2,e2,s1,e1);
    return (max(s1.x,e1.x)>=min(s2.x,e2.x)) &&
           (max(s2.x,e2.x)>=min(s1.x,e1.x)) &&
           (max(s1.y,e1.y)>=min(s2.y,e2.y)) &&
           (max(s2.y,e2.y)>=min(s1.y,e1.y)) &&
           (mult(s1,s2,e1)*mult(s1,e1,e2)>0)&&
           (mult(s2,s1,e2)*mult(s2,e2,e1)>0);
}
int main()
{
    line Seg,Line;
    Seg.a.x=0,Seg.a.y=0;
    Seg.b.x=1,Seg.b.y=1;
    Line.a.x=0,Line.a.y=2;
    Line.b.x=2,Line.b.y=0;
    printf("test1: ");
    if(opposite_side(Seg.a,Seg.b,Line.a,Line.b)) puts("opposite_side");
    else puts("in_side!");
    printf("test2: ");
    if(seg_inter_line(Seg,Line)) puts("opposite_side");
    else puts("in_side!");
}
相關文章
相關標籤/搜索