判斷平面上兩線段是否相交


首先引出計算幾何學中一個最基本的問題:如何判斷向量的順時針方向還是逆時針方向?

把p0定為原點,p1的坐標是(x1,y1),p2的坐標是(x2,y2)。向量的叉積(cross product)實際上就是矩陣的行列式:

當叉積為正時,說明的順時針方向上;叉積為0說明兩向量共線(同向或反向)。

當同時滿足:

(1)的兩側(即一個順時針方向上,一個在逆時針方向上)

(2)的兩側

時可肯定相交。

            圖1

圖1是線段相交的一般情形。

圖2只滿足第(1)條,不滿足第(2)條所以不能證明相交。

            圖2

圖3和圖4是一種特殊情況,它不滿足第(2)條,因為重合,即的叉積為0。

可見當叉積為0時要分情況討論,當p3在線段p1p2上時兩線段相交;當p3在線段p1p2的延長線上時兩線段不相交。

double direction(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
    pair<double,double> d1=make_pair(p3.first-p1.first,p3.second-p1.second);
    pair<double,double> d2=make_pair(p2.first-p1.first,p2.second-p1.second);
    return d1.first*d2.second-d1.second*d2.first;
}

direction函數用於計算的叉積。

bool OnSegment(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3){
    double x_min,x_max,y_min,y_max;
    if(p1.first<p2.first){
        x_min=p1.first;
        x_max=p2.first;
    }else{
        x_min=p2.first;
        x_max=p1.first;
    }
    if(p1.second<p2.second){
        y_min=p1.second;
        y_max=p2.second;
    }else{
        y_min=p2.second;
        y_max=p1.second;
    }
    if(p3.first<x_min || p3.first>x_max || p3.second<y_min || p3.second>y_max)
        return false;
    else
        return true;
}

當p3在直線p1p2上時,OnSegment函數用於確認p3在上,還是在的延長線上。

下面是用於判斷兩線段是否相交的主函數。

bool SegmentIntersect(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3,pair<double,double> p4){
    double d1=direction(p3,p4,p1);
    double d2=direction(p3,p4,p2);
    double d3=direction(p1,p2,p3);
    double d4=direction(p1,p2,p4);

    if(d1*d2<0 && d3*d4<0)
        return true;
    else if(d1==0 && OnSegment(p3,p4,p1))
        return true;
    else if(d2==0 && OnSegment(p3,p4,p2))
        return true;
    else if(d3==0 && OnSegment(p1,p2,p3))
        return true;
    else if(d4==0 && OnSegment(p1,p2,p4))
        return true;
    else
        return false;
}

測試函數:

int main(){
    double x1,y1,x2,y2,x3,y3,x4,y4;
    cout<<"Please input x1,y1,x2,y2,x3,y3,x4,y4 by order"<<endl;
    cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
    pair<double,double> p1=make_pair(x1,y1);
    pair<double,double> p2=make_pair(x2,y2);
    pair<double,double> p3=make_pair(x3,y3);
    pair<double,double> p4=make_pair(x4,y4);
    if(SegmentIntersect(p1,p2,p3,p4))
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM