使用 Python 判断线段是否与矩形相交

直线相交的判定

我们在初等几何中学过如何判断两条直线是否相交在欧几里得平面上, 两条直线要么平行, 要么相交, 要么重合这是欧几里得第五公设的推论相交的两条直线恰好有一个交点, 而重合的两条直线有无数个交点判断两条直线位置关系的代数方法是: 联立两条之直线方程, 无解, 则两条直线平行, 存在唯一解则两条直线相交, 存在两个及以上的解, 则两直线重合


联立直线方程

线段相交的判定:

分为矩形判定和叉积判定两步

step1: 矩形判定

判断分别以两线段为对角线的两个矩形是否相交, 若不相交, 则两线段一定不相交两个矩形是否相交的条件是: 任一矩形的最右端都大于另一矩形的最左端, 且任一矩形最高端大于另一矩形的最低端; 只要其中任一条件不满足, 则两矩形不相交, 也即两线段不相交


矩形判定: 不相交

这一步判定不相交的两条线段直接返回 False

step2: 叉积判定

经过上面判定未得到结果的两条线段那进入此步进行判定

叉积判定: 相交

这一步的目的是确定一条线段的两个端点是否在另一线段的两侧, 如果两条线段的端点互相位于另一条线段的两侧, 则这两条线段相交defcross(p1,p2,p3):# 叉积判定

x1=p2[0]-p1[0]
y1=p2[1]-p1[1]
x2=p3[0]-p1[0]
y2=p3[1]-p1[1]
returnx1*y2-x2*y1
defsegment(p1,p2,p3,p4):#判断两线段是否相交
#矩形判定, 以 l1l2 为对角线的矩形必相交, 否则两线段不相交
if(max(p1[0],p2[0])>=min(p3[0],p4[0])#矩形 1 最右端大于矩形 2 最左端
andmax(p3[0],p4[0])>=min(p1[0],p2[0])#矩形 2 最右端大于矩形 1 最左端
andmax(p1[1],p2[1])>=min(p3[1],p4[1])#矩形 1 最高端大于矩形 2 最低端
andmax(p3[1],p4[1])>=min(p1[1],p2[1])):#矩形 2 最高端大于矩形 1 最低端
if(cross(p1,p2,p3)*self.cross(p1,p2,p4)<=0
andcross(p3,p4,p1)*self.cross(p3,p4,p2)<=0):
D=1
else:
D=0
else:
D=0
returnD

线段与矩形相交的判定:

矩形的特殊之处在于其有 2 条对角线, 小于其边数 4 对于凸多边形, 只要一条线段穿越矩形必定与某一条对角线相交因此我们将线段与矩形相交问题转化为线段与矩形对角线的交点问题, 为了排除特殊情况, 在检测线段与对角线交点前, 我们检测线段的两个端点是否在矩形内

step1: 检测线段端点是否在矩形内

step2: 分别检测线段与矩形的两条对角线是否相交defcheck(l1,l2,sq):

# step 1 check if end point is in the square
if(l1[0]>=sq[0]andl1[1]>=sq[1]andl1[0]<=sq[2]andl1[1]<=sq[3])or
(l2[0]>=s1[0]andl2[1]>=s1[1]andl2[0]<=sq[2]andl2[1]<=sq[3]):
return1
else:
# step 2 check if diagonal cross the segment
p1=[sq[0],sq[1]]
p2=[sq[2],sq[3]]
p3=[sq[2],sq[1]]
p4=[sq[0],sq[3]]
ifsegment(l1,l2,p1,p2)orsegment(l1,l2,p3,p4):
return1
else:
return0

其中

sq=[x_leftdown,y_leftdown,x_rightup,y_rightup]