问题描述:已知两条线段P1P2和Q1Q2,判断P1P2和Q1Q2是否相交,若相交,求出交点。

两条线段的位置关系可以分为三类:有重合部分、无重合部分但有交点、无交点。

算法的步骤如下:

1.快速排斥实验。

设以线段P1P2为对角线的矩形为R,设以线段Q1Q2为对角线的矩形为T,如果R和T不相交,则两线段不相交。

2.跨立实验。

如果两线段相交,则两线段必然相互跨立对方。

若P1P2跨立Q1Q2,则矢量(P1-Q1)和(P2-Q1)位于矢量(Q2-Q1)的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。

若Q1Q2跨立P1P2,则矢量(Q1-P1)和(Q2-P1)位于矢量(P2-P1)的两侧,即( Q1 - P1 ) × ( P2 - P1 ) * ( Q2 - P1 ) × ( P2 - P1 ) < 0。

排斥实验和跨立实验的示例如下图所示。

3.计算交点。

当判定两条线段相交后,可以进行交点的求解,求交点可以用平面几何方法,列点斜式方程来完成。但由于点斜式方程难以处理斜率为0的特殊情况,不方便求解。因而,参用向量法求解交点。

设交点为(x0,y0),则下列方程组成立:

根据以上方程组,消除参数k1和k2,得到如下方程:

然后求解(x0,y0),结果如下所示:

typedef struct Point
{
    int x;
    int y;
}Point;
//排斥实验
bool IsRectCross(const Point &p1,const Point &p2,const Point &q1,const Point &q2)
{
    bool ret = min(p1.x,p2.x) <= max(q1.x,q2.x)    &&
                min(q1.x,q2.x) <= max(p1.x,p2.x) &&
                min(p1.y,p2.y) <= max(q1.y,q2.y) &&
                min(q1.y,q2.y) <= max(p1.y,p2.y);
    return ret;
}
//跨立判断
bool IsLineSegmentCross(const Point &pFirst1,const Point &pFirst2,const Point &pSecond1,const Point &pSecond2)
{
    long line1,line2;
    line1 = pFirst1.x * (pSecond1.y - pFirst2.y) +
        pFirst2.x * (pFirst1.y - pSecond1.y) +
        pSecond1.x * (pFirst2.y - pFirst1.y);
    line2 = pFirst1.x * (pSecond2.y - pFirst2.y) +
        pFirst2.x * (pFirst1.y - pSecond2.y) +
        pSecond2.x * (pFirst2.y - pFirst1.y);
    if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
        return false;

line1 = pSecond1.x * (pFirst1.y - pSecond2.y) +
        pSecond2.x * (pSecond1.y - pFirst1.y) +
        pFirst1.x * (pSecond2.y - pSecond1.y);
    line2 = pSecond1.x * (pFirst2.y - pSecond2.y) +
        pSecond2.x * (pSecond1.y - pFirst2.y) +
        pFirst2.x * (pSecond2.y - pSecond1.y);
    if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))
        return false;
    return true;
}

bool GetCrossPoint(const Point &p1,const Point &p2,const Point &q1,const Point &q2,long &x,long &y)
{
    if(IsRectCross(p1,p2,q1,q2))
    {
        if (IsLineSegmentCross(p1,p2,q1,q2))
        {
            //求交点
            long tmpLeft,tmpRight;
            tmpLeft = (q2.x - q1.x) * (p1.y - p2.y) - (p2.x - p1.x) * (q1.y - q2.y);
            tmpRight = (p1.y - q1.y) * (p2.x - p1.x) * (q2.x - q1.x) + q1.x * (q2.y - q1.y) * (p2.x - p1.x) - p1.x * (p2.y - p1.y) * (q2.x - q1.x);

x = (int)((double)tmpRight/(double)tmpLeft);

tmpLeft = (p1.x - p2.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q1.x - q2.x);
            tmpRight = p2.y * (p1.x - p2.x) * (q2.y - q1.y) + (q2.x- p2.x) * (q2.y - q1.y) * (p1.y - p2.y) - q2.y * (q1.x - q2.x) * (p2.y - p1.y);
            y = (int)((double)tmpRight/(double)tmpLeft);
            return true;
        }
    }
    return false;
}

【计算几何】线段相交相关推荐

  1. NYOJ 1016 德莱联盟(计算几何 线段相交判定)

    判断两条线段是否相交. 在判断两条线段是否相交时,我们常用快速排斥实验跟跨立实验这两种方法,快速排斥实验能很快的排除掉线段不相交的情况,但并没法成为线段相交的充要条件,在快速排斥实验之后接上跨立实验就 ...

  2. 德莱联盟 计算几何 线段相交

    难度:1 描述 欢迎来到德莱联盟.... 德莱文... 德莱文在逃跑,卡兹克在追.... 我们知道德莱文的起点和终点坐标,我们也知道卡兹克的起点和 终点坐标,问:卡兹克有可能和德莱文相遇吗?,并且保证 ...

  3. zoj 1010 Area【线段相交问题】

    链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1010 http://acm.hust.edu.cn/vjudge/ ...

  4. 【POJ - 1556】The Doors (计算几何,线段相交)

    题干: You are to find the length of the shortest path through a chamber containing obstructing walls. ...

  5. 【计算几何】判断线段相交(跨立实验)

    题意:有n条线段(编号为1n),按1n的顺序放在二维坐标系上(就是先放1号,再放2号--),要求输出最上面的那些线段的编号.(就是没有其他线段压在它上面的那些线段) 注意:有交点即为被压. 1.叉积 ...

  6. 计算几何 快速排斥和跨立实验 判断两线段相交

    线段P1P2, Q1Q2,判断其是否相交,通过快速排斥和跨立实验则说明相交 首先要知道:向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的逆时针方向:若结果大于0,表示向量b在向量a的 ...

  7. 几何常用算法与判断线段相交【转】

    下面这个函数在我写的计算几何库函数里面有,那个库可以在http://algorithm.126.com/的资源中心   -   代码角   找到. 算法简单说明: 首先判断以两条线段为对角线的矩形是否 ...

  8. POJ1410线段相交、快速排斥实验、跨立实验

    题目 Intersection 给出二维平面中一条线段和一个矩形,问线段和矩形是否有交点,矩形包括边和内部. 解题思路 先判断线段和四条边是否相交,如果没交点,再继续判断线段是否在矩形内. 判断线段相 ...

  9. poj3304(线段相交问题)

    题意:是否存在这样一条直线,使这条直线和所有的线段相交. #include<iostream> #include<algorithm> #include<cstring& ...

最新文章

  1. unity 关闭自己脚本_Unity3D 挂载的脚本取消勾选居然还会运行!!
  2. 数据结构 排序和查找
  3. 三十天学不会TCP,UDP/IP网络编程-TraceRoute的哲学
  4. 人脸识别python face_recognize_【python+face_recognition】人脸识别初始
  5. 解析:Python为什么这么流行?
  6. 从思维图到基础再到深入,java空间查询
  7. 代码逆流成河,深入C++如何又快又有效?
  8. Linux多线程工作笔记0005---Linux多线程基础_创建线程pthread_create_线程等待_线程终止
  9. Python图片攻击
  10. 【实习之T100开发】T100 双档程序开发流程
  11. objective-c和java哪个简单_Objective-C和Java的简单对比
  12. 汇编:call和jmp
  13. excel计算式自动计算_全套Excel版工程自动计算表格+实用小工具,高效工作不加班...
  14. excel打开超链接不使用浏览器,使用默认图片浏览软件
  15. 如何在自己的板子上实现android关机
  16. SQL Injection Bypassing WAF ——from DVWA ——2012-12-8
  17. 刚上市就名声鹊起,nova3和NEX拍照谁能更甚一筹?
  18. 如何打通微信账号体系?
  19. 城域网的互联网专线接入带宽合规合法
  20. Jlink V9刷入自动升级固件

热门文章

  1. AI应用开发基础傻瓜书系列3-激活函数
  2. 服务器winsxs文件夹怎么清理工具,winsxs,教您winsxs文件夹清理方法
  3. JAVA入门级教学之(猜数字测试)
  4. Java转JSON串的几种方式
  5. 奥鹏20年12月作业考核(C语言专科),《C语言(专科)》20年12月作业考核【答案100分】...
  6. 物联卡的使用_物联卡在手机上使用有什么影响?网友:寿命分别是3个月,16天,9天...
  7. python中哪个符号用于从包中导入模块__学小易找答案
  8. jsp是在html里面嵌入哪种代码?_奶茶店铺用哪种制冰机才合适?
  9. python 读文件写数据库_python读文件写数据库
  10. mysql主库从库在同一台服务器_MySQL数据库的主从配置(多主对一从)