收藏 分享(赏)

一种判断线段相交方法.doc

上传人:myw993772 文档编号:6333570 上传时间:2019-04-07 格式:DOC 页数:5 大小:42.50KB
下载 相关 举报
一种判断线段相交方法.doc_第1页
第1页 / 共5页
一种判断线段相交方法.doc_第2页
第2页 / 共5页
一种判断线段相交方法.doc_第3页
第3页 / 共5页
一种判断线段相交方法.doc_第4页
第4页 / 共5页
一种判断线段相交方法.doc_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

1、一.矢量基本知识因为后面的计算需要一些矢量的基本知识,这里只是简单的列举如下,如果需要更加详细的信息,可以自行搜索 wikipedia 或 google。1.矢量的概念:如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。如果有向线段 p1p2 的起点 p1 在坐标原点,我们可以把它称为矢量(vector)p2。2.矢量加减法:设二维矢量 P = ( x1, y1 ),Q = ( x2 , y2 ),则矢量加法定义为: P + Q = ( x1 + x2 , y1 + y2 ),同样的,矢量减法定义为: P - Q = ( x1 - x2 , y1

2、 - y2 )。显然有性质 P + Q = Q + P,P - Q = - ( Q - P )。3.矢量的叉积:计算矢量叉积是与直线和线段相关算法的核心部分。设矢量 P = ( x1, y1 ),Q = ( x2, y2 ),则矢量叉积定义为由(0,0)、p1、p2 和 p1+p2所组成的平行四边形的带符号的面积,即:P Q = x1*y2 - x2*y1,其结果是一个标量。显然有性质 P Q = - ( Q P ) 和 P ( - Q ) = - ( P Q )。一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。叉积的一个非常重要

3、性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:若 P Q 0 , 则 P 在 Q 的顺时针方向。若 P Q 0,则 p0p1 在 p1 点拐向右侧后得到 p1p2。若(p2 - p0) (p1 - p0) end.x - v1-start.x; 8. vt1.end.y = v1-end.y - v1-start.y; 9. 10. vt2.start.x = 0; 11. vt2.start.y = 0; 12. vt2.end.x = v2-end.x - v2-start.x; 13. vt2.end.y = v2-end.y - v2-start.y; 14. 15. res

4、ult = vt1.end.x * vt2.end.y - vt2.end.x * vt1.end.y; 16. return result; 17. 二.判断两条直线相交先来看一个简单的情况,即判断两条直线是否相交。第一个可能会想到的办法,就是判断斜率,这个在中学时代就学过了,不过斜率需要考虑垂直的特殊情况,比较麻烦。更好的办法或许是计算两个向量的叉积,如果为 0,则是平行或者重合的,否则两直线相交。代码就不贴了,直接调用上面的函数就 ok 了。三.判断两线段相交经典方法,就是跨立试验了,即如果一条线段跨过另一条线段,则线段的两个端点分别在另一条线段的两侧。但是,还需要检测边界情况,即两条线

5、段中可能某条线段的某个端点正好落在另一条线段上。这也是算法导论中介绍的算法。程序模拟如下:1. int direction(point* pi, point* pj, point* pk) 2. point p1, p2; 3. 4. p1.x = pk-x - pi-x; 5. p1.y = pk-y - pi-y; 6. 7. p2.x = pj-x - pi-x; 8. p2.y = pj-y - pi-y; 9. 10. return crossProduct( 11. 12.13.int onSegment(point* pi, point* pj, point* pk) 14. i

6、nt minx, miny, maxx, maxy; 15. if (pi-x pj-x) 16. minx = pj-x; 17. maxx = pi-x; 18. 19. else 20. minx = pi-x; 21. maxx = pj-x; 22. 23. 24. if (pi-y pj-y) 25. miny = pj-y; 26. maxy = pi-y; 27. 28. else 29. miny = pi-y; 30. maxy = pj-y; 31. 32. 33. if (minx x 35. else 36. return 0; 37. 38.39.int segme

7、ntIntersect(point* p1, point* p2, point* p3, point* p4) 40. int d1 = direction(p3, p4, p1); 41. int d2 = direction(p3, p4, p2); 42. int d3 = direction(p1, p2, p3); 43. int d4 = direction(p1, p2, p4); 44. if (d1 * d2 0 46. else if (!d1 48. else if (!d2 50. else if (!d3 52. else if (!d4 54. else 55. r

8、eturn 0; 56. 实际上,如果想改进上述算法,还可以在跨立试验前加一步,就是先做快速排斥试验。那就是,先分别判断以两条线段为对角线的矩形是否相交,如果不相交,则两个线段肯定不相交。四.判断两条线段相交,然后计算交点设一条线段为 L0=P1P2, 另一条线段或直线为 L1=Q1Q2, 要计算的就是 L0 和 L1的交点。1.首先判断 L0 和 L1 是否相交(方法已在前文讨论过), 如果不相交则没有交点, 否则说明 L0 和 L1 一定有交点, 下面就将 L0 和 L1 都看作直线来考虑. 2.如果 P1 和 P2 横坐标相同, 即 L0 平行于 Y 轴 a)若 L1 也平行于 Y 轴

9、i.若 P1 的纵坐标和 Q1 的纵坐标相同, 说明 L0 和 L1 共线, 假如 L1 是直线的话他们有无穷的交点, 假如 L1 是线段的话可用“计算两条共线线段的交点“的算法求他们的交点(该方法在前文已讨论过);ii.否则说明 L0 和 L1 平行, 他们没有交点; b)若 L1 不平行于 Y 轴, 则交点横坐标为 P1 的横坐标, 代入到 L1 的直线方程中可以计算出交点纵坐标; 3.如果 P1 和 P2 横坐标不同, 但是 Q1 和 Q2 横坐标相同 , 即 L1 平行于 Y 轴, 则交点横坐标为 Q1 的横坐标, 代入到 L0 的直线方程中可以计算出交点纵坐标; 4.如果 P1 和

10、P2 纵坐标相同, 即 L0 平行于 X 轴a)若 L1 也平行于 X 轴,i.若 P1 的横坐标和 Q1 的横坐标相同, 说明 L0 和 L1 共线, 假如 L1 是直线的话他们有无穷的交点, 假如 L1 是线段的话可用“计算两条共线线段的交点“的算法求他们的交点(该方法在前文已讨论过);ii.否则说明 L0 和 L1 平行, 他们没有交点; b)若 L1 不平行于 X 轴, 则交点纵坐标为 P1 的纵坐标, 代入到 L1 的直线方程中可以计算出交点横坐标; 5.如果 P1 和 P2 纵坐标不同, 但是 Q1 和 Q2 纵坐标相同 , 即 L1 平行于 X 轴, 则交点纵坐标为 Q1 的纵坐

11、标, 代入到 L0 的直线方程中可以计算出交点横坐标; 6.剩下的情况就是 L1 和 L0 的斜率均存在且不为 0 的情况 a)计算出 L0 的斜率 K0, L1 的斜率 K1;b)如果 K1 = K2 i.如果 Q1 在 L0 上, 则说明 L0 和 L1 共线, 假如 L1 是直线的话有无穷交点, 假如 L1 是线段的话可用“计算两条共线线段的交点“的算法求他们的交点(该方法在前文已讨论过);ii.如果 Q1 不在 L0 上, 则说明 L0 和 L1 平行, 他们没有交点.c)联立两直线的方程组可以解出交点来这个算法并不复杂, 但是要分情况讨论清楚, 尤其是当两条线段共线的情况需要单独考虑

12、, 所以在前文将求两条共线线段的算法单独写出来 . 另外, 一开始就先利用矢量叉乘判断线段与线段(或直线)是否相交, 如果结果是相交, 那么在后面就可以将线段全部看作直线来考虑. 需要注意的是, 我们可以将直线或线段方程改写为 ax+by+c=0 的形式, 这样一来上述过程的部分步骤可以合并, 缩短了代码长度, 但是由于先要求出参数, 这种算法将花费更多的时间.已知一条线段的两个端点为 A(x1,y1),B(x2,y2),另一条线段的两个端点为 C(x3,y3),D(x4,y4),要判断 AB 与 CD 是否有交点,若有求出 . 首先判断 d = (y2-y1)(x4-x3)-(y4-y3)(

13、x2-x1), 若 d=0,则直线 AB 与 CD 平行或重合, 若 d!=0,则直线 AB 与 CD 有交点,且交点(x0,y0)为: x0 = (x2-x1)*(x4-x3)*(y3-y1)+(y2-y1)*(x4-x3)*x1-(y4-y3)*(x2-x1)*x3/d x0 = (y2-y1)*(y4-y3)*(x3-x1)+(x2-x1)*(y4-y3)*y1-(x4-x3)*(y2-y1)*y3/(-d) 求出交点后在判断交点是否在线段上,即判断以下的式子: (x0-x1)*(x0-x2)=0 (x0-x3)*(x0-x4)=0 (y0-y1)*(y0-y2)=0 (y0-y3)*(y0-y4)=0 只有上面的四个式子都成立才可判定(x0,y0)是线段 AB 与 CD 的交点,否则两线段无交点

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报