如何判断二维的两个线段是否相交
2017-05-06 12:46
267 查看
本文算法见:http://www.faqs.org/faqs/graphics/algorithms-faq/ 中的Subject 1.03
所以一条线段AB的定义可以为(SPoint A, SPointB).很明显,这个线段用A,B来表示的话就是:
r=0的时候,线段AB其实就是A点,r=1的时候,线段AB就是B点。r的取值在0-1之间就描述了AB之间的的线段。
如果AB和CD有交叉,那么必然有对应的 r 和 s 满足下面的等式:
转换成坐标x, y也就是:
根据上面的两个等式可以得到 r 和 s 的值为:
很明显,当 0<= r <=1 并且 0<= s <=1的时候,两个线段是有相交的。
当 r 或者 s 的分母为0时,两条线段是平行的。
当 r 或者 s 的分母为0并且分子也为0时,两条线段是重合的。
如果r<0, 线段的交点位于BA的延长线上;
如果s>1, 线段的交点位于CD的延长线上;
如果s<0, 线段的交点位于DC的延长线上;
线段的定义
很明显,线段的端点由两个SPoint来定义,SPoint定义如下,坐标系中的x,y坐标可以决定一个点:class SPoint(object): def __init__(self, a=0.0, b=0.0): self._x = a self._y = b
所以一条线段AB的定义可以为(SPoint A, SPointB).很明显,这个线段用A,B来表示的话就是:
AB = A + r(B-A), r=[0,1]
r=0的时候,线段AB其实就是A点,r=1的时候,线段AB就是B点。r的取值在0-1之间就描述了AB之间的的线段。
线段的交叉
给定两个线段AB,CD,根据上面的定义,这两个线段的程序表达式如下:AB = A + r(B-A), r=[0,1]CD = C + s(D-C), s=[0,1]
如果AB和CD有交叉,那么必然有对应的 r 和 s 满足下面的等式:
A + r(B-A) = C + s(D-C)
转换成坐标x, y也就是:
A._x+r(B._x-A._x)=C._x+s(D._x-C._x) A._y+r(B._y-A._y)=C._y+s(D._y-C._y)
根据上面的两个等式可以得到 r 和 s 的值为:
(A._y-C._y)(D._x-C._x)-(A._x-C._x)(D._y-C._y) r = --------------------------------------------- (B._x-A._x)(D._y-C._y)-(B._y-A._y)(D._x-C._x) (A._y-C._y)(B._x-A._x)-(A._x-C._x)(B._y-A._y) s = --------------------------------------------- (B._x-A._x)(D._y-C._y)-(B._y-A._y)(D._x-C._x)
很明显,当 0<= r <=1 并且 0<= s <=1的时候,两个线段是有相交的。
当 r 或者 s 的分母为0时,两条线段是平行的。
当 r 或者 s 的分母为0并且分子也为0时,两条线段是重合的。
延长线上相交
如果r>1, 线段的交点位于AB的延长线上;如果r<0, 线段的交点位于BA的延长线上;
如果s>1, 线段的交点位于CD的延长线上;
如果s<0, 线段的交点位于DC的延长线上;
实现
实现的代码如下,注意在测试用例中有一个特殊的case:[(1,1), (2,2), (2,2), (3,3)], 线段AB和CD交于(2,2),但是线段AB和CD其实是一条直线,具体判断这种情况为相交线还是不相交就看应用场景了.# -*- coding: utf-8 -*-
class SPoint(object): def __init__(self, a=0.0, b=0.0): self._x = a self._y = b
def LineIntersection2D(A, B, C, D):
rDenominator = (B._x-A._x)*(D._y-C._y)-(B._y-A._y)*(D._x-C._x)
rNumerator = (A._y-C._y)*(D._x-C._x)-(A._x-C._x)*(D._y-C._y)
sDenominator = (B._x-A._x)*(D._y-C._y)-(B._y-A._y)*(D._x-C._x)
sNumerator = (A._y-C._y)*(B._x-A._x)-(A._x-C._x)*(B._y-A._y)
if rDenominator == 0: # rDenominator == sDenominator
# lines are parallel
return False
r = (1.0) * rNumerator / rDenominator
s = (1.0) * sNumerator / sDenominator
if 0<=r<=1.0 and 0<=s&l
4000
t;=1.0:
return True
else:
return False
if __name__ == '__main__':
TestLines = [[(1,1), (2,2), (1,2), (2,1)], # intersected: YES
[(1,1), (2,2), (1,1), (2,2)], # NO
[(1,1), (2,2), (1,1), (2,1)], # YES
[(1,1), (2,2), (1,2), (2,3)], # NO
[(1,1), (2,2), (2,2), (3,3)], # YES or NO???
[(1,1), (2,2), (2,2), (3,4)]] # YES
for points in TestLines:
A = SPoint(points[0][0], points[0][1])
B = SPoint(points[1][0], points[1][1])
C = SPoint(points[2][0], points[2][1])
D = SPoint(points[3][0], points[3][1])
intersected = "Yes" if LineIntersection2D(A,B,C,D) else "No"
print "AB and CD is intersected?", intersected
相关文章推荐
- 如何判断两个单向链表是否有相交,并找出交点
- hdu 1086 判断两个线段是否相交
- 如何判断两个单链表是否相交以及找出第一个相交的位置
- 关于如何判断在平面上的两条线段是否相交
- 如何判断两个链表是否相交并求出相交点
- 如何判断两个单向链表是否有相交,并找出交点
- 判断二维平面上两线段是否相交
- [几何]判断两个线段是否相交(多语言实现)
- 判断两个线段是否相交
- 百度笔试算法第二题:如何判断两个单向链表是否有相交,并找出交点
- 编程判断两个线段是否相交
- 判断两个线段是否相交
- 如何判断两个单向链表是否有相交,并找出交点
- 如何判断两个链表是否相交,以及交点
- 如何确定两个线段是否相交;叉积的利用;
- 判断两个线段是否相交
- 如何判断平面上两条线段(注意是线段)是否相交?(某公司校园招聘面试试题)
- 如何判断两个单向链表是否有相交,并找出交点
- 判断两个线段是否相交
- 德莱联盟(判断两个线段是否相交)