博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【计算几何】线段相交
阅读量:6496 次
发布时间:2019-06-24

本文共 2874 字,大约阅读时间需要 9 分钟。

问题描述:已知两条线段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),结果如下所示:

1 typedef struct Point 2 { 3     int x; 4     int y; 5 }Point; 6 //排斥实验 7 bool IsRectCross(const Point &p1,const Point &p2,const Point &q1,const Point &q2) 8 { 9     bool ret = min(p1.x,p2.x) <= max(q1.x,q2.x)    &&10                 min(q1.x,q2.x) <= max(p1.x,p2.x) &&11                 min(p1.y,p2.y) <= max(q1.y,q2.y) &&12                 min(q1.y,q2.y) <= max(p1.y,p2.y);13     return ret;14 }15 //跨立判断16 bool IsLineSegmentCross(const Point &pFirst1,const Point &pFirst2,const Point &pSecond1,const Point &pSecond2)17 {18     long line1,line2;19     line1 = pFirst1.x * (pSecond1.y - pFirst2.y) +20         pFirst2.x * (pFirst1.y - pSecond1.y) +21         pSecond1.x * (pFirst2.y - pFirst1.y);22     line2 = pFirst1.x * (pSecond2.y - pFirst2.y) +23         pFirst2.x * (pFirst1.y - pSecond2.y) + 24         pSecond2.x * (pFirst2.y - pFirst1.y);25     if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))26         return false;27 28     line1 = pSecond1.x * (pFirst1.y - pSecond2.y) +29         pSecond2.x * (pSecond1.y - pFirst1.y) +30         pFirst1.x * (pSecond2.y - pSecond1.y);31     line2 = pSecond1.x * (pFirst2.y - pSecond2.y) + 32         pSecond2.x * (pSecond1.y - pFirst2.y) +33         pFirst2.x * (pSecond2.y - pSecond1.y);34     if (((line1 ^ line2) >= 0) && !(line1 == 0 && line2 == 0))35         return false;36     return true;37 }38 39 bool GetCrossPoint(const Point &p1,const Point &p2,const Point &q1,const Point &q2,long &x,long &y)40 {41     if(IsRectCross(p1,p2,q1,q2))42     {43         if (IsLineSegmentCross(p1,p2,q1,q2))44         {45             //求交点46             long tmpLeft,tmpRight;47             tmpLeft = (q2.x - q1.x) * (p1.y - p2.y) - (p2.x - p1.x) * (q1.y - q2.y);48             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);49 50             x = (int)((double)tmpRight/(double)tmpLeft);51 52             tmpLeft = (p1.x - p2.x) * (q2.y - q1.y) - (p2.y - p1.y) * (q1.x - q2.x);53             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); 54             y = (int)((double)tmpRight/(double)tmpLeft);55             return true;56         }57     }58     return false;59 }

 

 

转载地址:http://pdcyo.baihongyu.com/

你可能感兴趣的文章
【斗医】【18】Web应用开发20天
查看>>
python常用数据结构的常用操作
查看>>
深入Jetty源码之Servlet框架及实现(AsyncContext、RequestDispatcher、HttpSession)
查看>>
Guice系列之用户指南(七)
查看>>
PgSQL · 实战经验 · 如何预测Freeze IO风暴
查看>>
C与C++之间相互调用
查看>>
chrome dev debug network 的timeline说明
查看>>
Xcode中通过删除原先版本的程序来复位App
查看>>
彻底理解js中this
查看>>
深入Java虚拟机读书笔记[10:20]
查看>>
从AdventureWorks学习数据库建模——保留历史数据
查看>>
[j2me]类似于OperaMini二级菜单界面演练[1]
查看>>
云计算读书笔记(五)
查看>>
数据库模型设计——主键的设计
查看>>
说一说activity
查看>>
GCD之信号量机制二
查看>>
Oracle官方教程之Fork/Join
查看>>
手势识别之轻点
查看>>
[转载]Linux 线程实现机制分析
查看>>
LoadRunner 技巧之 手动关联与预关联
查看>>