POJ - 1296 Intersecting Lines(计算几何)

本文介绍如何通过叉乘判断两条直线是否平行、重合或相交,并提供求解交点的具体方法及C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点我看题

题意:给出两条直线,判断这两条直线的关系,即问是否相交,如果相交求出交点,如果不相交,那么他们是相离还是重合?

分析:首先去判断直线P1P2和Q1Q2和是否平行,判断直线平行可以利用叉乘。

如果(P2-P1)×(Q2-Q1)== 0的话,那么两直线平行;

得到直线平行,就要看是否重合了。

判断重合就相当于判断一条直线上的点是否存在于另一条直线上,假设这里我们看P1是否在Q1Q2上。

如果(Q1-P1)×(Q2-P1)== 0,说明重合。

反之,如果(Q1-P1)×(Q2-P1)!= 0,说明相离。

那么如果(P2-P1)×(Q2-Q1)!= 0的话,两直线一定相交,要求出交点.

求交点的方法http://blog.youkuaiyun.com/dgq8211/article/details/7952825

参考代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
#define eps 1e-8
int n;
int sgn( double x)
{
    if( fabs(x) < eps)
        return 0;
    if( x < 0)
        return -1;
    return 1;
}
struct Point{
    double x,y;
    Point(){}
    Point( double xx, double yy)
    {
        x = xx;
        y = yy;
    }
    Point operator - ( const Point &p)const
    {
        return Point(x-p.x,y-p.y);
    }
    double operator * ( const Point &p)const
    {
        return x*p.x+y*p.y;
    }
    double operator ^ ( const Point &p)const
    {
        return x*p.y-p.x*y;
    }
};
struct Line{
    Point s,e;
    Line(){}
    Line( Point ss, Point ee)
    {
        s = ss;
        e = ee;
    }
    //判断两条直线之间的关系
    pair<Point,int> operator &( const Line &p)const
    {
        Point res = s;
        if( sgn((s-e)^(p.s-p.e)) == 0)//两条直线平行
        {
            if( sgn((p.s-s)^(p.e-s)) == 0)//点s在线段p上
                return make_pair(res,0);//两直线重合
            return make_pair(res,1);//两直线平行
        }
        double t = ((s-p.s)^(p.s-p.e))/((s-e)^(p.s-p.e));
//        cout<<res.x<<" "<<res.y<<" "<<t<<endl;
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(res,2);//有交点
    }
};
Line l1,l2;

//计算p2p1×p3p1
int xmult( Point p1, Point p2, Point p3)
{
    return (p2-p1)^(p3-p1);
}

//判断两条线段是否相交
/*
int SegInterLine( Line l1, Line l2)
{
    //快速排斥实验
    if( min(l1.s.x,l1.e.x) <= max(l2.s.x,l2.e.x) && min(l2.s.x,l2.e.x) <= max(l1.s.x,l1.e.x) && min(l1.s.y,l1.e.y) <= max(l2.s.y,l2.e.y) && min(l2.s.y,l2.e.y)<= max(l1.s.y,l1.e.y))
    {
        //快速排斥实验得到可能相交
        //跨立实验
        if( xmult(l1.s,l2.s,l1.e)*xmult(l1.s,l1.e,l2.e) <= 0 && xmult(l2.s,l1.e,l2.s)*xmult(l2.s,l2.e,l1.e) <= 0)
            return true;
    }
    return false;
}
*/

int main()
{
    int T;
    scanf("%d",&T);
    puts("INTERSECTING LINES OUTPUT");
    while( T--)
    {
        double x1,y1,x2,y2,x3,y3,x4,y4;
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        l1 = Line(Point(x1,y1),Point(x2,y2));
        l2 = Line(Point(x3,y3),Point(x4,y4));
//      int check = SegInterLine(l1,l2);
        pair<Point,int> ans = l1&l2;
        if( ans.second == 2)
            printf("POINT %.2f %.2f\n",ans.first.x,ans.first.y);
        else if( ans.second == 1)
            puts("NONE");
        else if( ans.second == 0)
            puts("LINE");
    }
    puts("END OF OUTPUT");

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值