SegmentIntersection 线段相交

问题

判断两线段l1l_{1}l2l_{2}是否相交。

解法

对于一条线段和一条直线,若线段两端点在直线的不同两侧则称该线段“跨越”了该直线。根据该公理,线段l1l_{1}l2l_{2}相交有两种情况:

(1)(1) 两条线段l1l_{1}l2l_{2},任意一条线段的两个端点都在另一线段所在直线的两侧。即l1l_{1}的两端点跨越l2l_{2}所在的直线,l2l_{2}的两端点也跨越l1l_{1}所在直线。如图所示:

对于图11l2l_{2}的两端点ccdd分别在l1l_{1}所在直线的两边,且l1l_{1}的两端点aabb分别在l2l_{2}所在直线的两边,因此l1l_{1}l2l_{2}相交。

ab\vec{ab}ac\vec{ac}的叉积为abac\vec{ab-ac}ab\vec{ab}ad\vec{ad}的叉积为abad\vec{ab-ad}cd\vec{cd}ca\vec{ca}的叉积为cdca\vec{cd-ca}cd\vec{cd}cb\vec{cb}的叉积为cdcb\vec{cd-cb}。根据Cross中的转向可知,abac\vec{ab-ac}abad\vec{ab-ad}两个叉积的转向相反,一正一负(表示一个方向与方向向量kkx,y,zx, y, z平面中的zz轴)相同,另一个方向相反),cdca\vec{cd-ca}cdcb\vec{cd-cb}两个叉积的转向相反,一正一负。

对于图22abac\vec{ab-ac}abad\vec{ab-ad}的叉积转向相反,但cdca\vec{cd-ca}cdcb\vec{cd-cb}的叉积转向相同,同正同负,因此图2中的两线段不相交。

(2)(2) 线段l1l_{1}的其中一个端点在线段l2l_{2}上,这是一种边界情况,无需考虑l1l_{1}的另一个端点的位置,也可以确定l1l_{1}l2l_{2}相交。如图所示:

aa在线段l2l_{2}上的条件为:ca\vec{ca}ad\vec{ad}两向量方向相同,即两向量的叉积值为00;且点aax,yx, y坐标在线段l2l_{2}x,yx, y范围内。

该算法的时间复杂度为O(1)O(1)

Introduction to Algorithms

源码

SegmentIntersection.h

SegmentIntersection.cpp

测试

SegmentIntersectionTest.cpp

Last updated