原理:
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。
上式可改写成(P1-Q1)×(Q2 -Q1) * (Q2 - Q1)×(P2 -Q1) > 0。
当(P1 -Q1)×(Q2 -Q1)=0 时,说明( P1 - Q1)和(Q2 - Q1)共线,
但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,(Q2 -Q1)×(P2 -Q1)=0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:
( P1 - Q1 )×(Q2 - Q1) * (Q2 - Q1)×( P2 -Q1) >= 0。
同理判断Q1Q2跨立P1P2的依据是:
( Q1 - P1 )×( P2 - P1) * ( P2 - P1)×(Q2 - P1) >= 0。
X:为叉积 叉积的计算公式为: P1 X P2 = x1y2 - x2y1;
'判断两线段是否是相交,参数为四个点坐标
Function L2L_Intersect(p1_s() As Double, p1_e() As Double, p2_s() As Double, p2_e() As Double) As Boolean
Dim Xmax_1, Xmax_2, Xmin_1, Xmin_2, Ymax_1, Ymax_2, Ymin_1, Ymin_2 As Double
Dim V1 As Double, V2 As Double
Dim V3 As Double, V4 As Double
If p1_s(0) > p1_e(0) Then
Xmax_1 = p1_s(0)
Xmin_1 = p1_e(0)
Else
Xmax_1 = p1_e(0)
Xmin_1 = p1_s(0)
End If
If p1_s(1) > p1_e(1) Then
Ymax_1 = p1_s(1)
Ymin_1 = p1_e(1)
Else
Ymax_1 = p1_e(1)
Ymin_1 = p1_s(1)
End If
If p2_s(0) > p2_e(0) Then
Xmax_2 = p2_s(0)
Xmin_2 = p2_e(0)
Else
Xmax_2 = p2_e(0)
Xmin_2 = p2_s(0)
End If
If p2_s(1) > p2_e(1) Then
Ymax_2 = p2_s(1)
Ymin_2 = p2_e(1)
Else
Ymax_2 = p2_e(1)
Ymin_2 = p2_s(1)
End If
L2L_Intersect = False
If Xmax_1 < Xmin_2 Or Xmin_1 > Xmax_2 Or Ymin_1 > Ymax_2 Or Ymax_1 < Ymin_2 Then '两线段最小矩形不相交,得出两线段不相交
L2L_Intersect = False
Exit Function
Else '利用向量的叉积性质,当其中一条线段的两个端点在另一条线段的同一侧时,不相交。否则,相交。
V1 = (p1_e(0) - p1_s(0)) * (p2_s(1) - p1_s(1)) - (p2_s(0) - p1_s(0)) * (p1_e(1) - p1_s(1))
V2 = (p1_e(0) - p1_s(0)) * (p2_e(1) - p1_s(1)) - (p2_e(0) - p1_s(0)) * (p1_e(1) - p1_s(1))
V3 = (p2_e(0) - p2_s(0)) * (p1_s(1) - p2_s(1)) - (p1_s(0) - p2_s(0)) * (p2_e(1) - p2_s(1))
V4 = (p2_e(0) - p2_s(0)) * (p1_e(1) - p2_s(1)) - (p1_e(0) - p2_s(0)) * (p2_e(1) - p2_s(1))
If V3 * V4 <= 0 And V1 * V2 <= 0 Then
L2L_Intersect = True
End If
End If
End Function