编写了几个使用的函数,实现了:
- 判断线段是否相交,或其延长线是否相交
- 函数内定义了
isinline
方法,能判断所给点是否在给定的直线上。这个方法通过控制precision
允许给定的点有一定的误差 - 函数内定义了
isinsegment
方法,能判断所给点是否在给定的直线上。这个方法通过控制precision
允许给定的点有一定的误差
下面是具体的代码,拿来即用:
import numpy as np
import logging
logger_line_intersection = logging.getLogger("line_intersection")
log_format = logging.Formatter('%(message)s')
logger_line_intersection.setLevel(logging.DEBUG)
console_hander = logging.StreamHandler()
console_hander.setFormatter(log_format)
logger_line_intersection.addHandler(console_hander)
def line_intersection(line1, line2,external=True,precision=1e-3,verbose=False):
'''
求两个线段是否相交,并返回交点
:param line1:[(x0,y0),(x1,y1)]
:param line2:[(x0,y0),(x1,y1)]
:param external:是否判断其延长线相交
:param precision: 精度,判断交点是否在线上时允许有一定的误差
:return:
'''
if verbose:
console_hander.setLevel(logging.DEBUG)
else:
console_hander.setLevel(logging.WARNING)
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
def isinline(point:tuple,line,precision=1e-3):
'''
判断点是否在线上
:param point: (x,y)
:param line:
:param precision:
:return:
'''
line_slope=(line[1][1]-line[0][1])/(line[1][0]-line[0][0])
logger_line_intersection.debug(f"line_slope:{line_slope}")
point_slope=(point[1]-line[0][1])/(point[0]-line[0][0])
logger_line_intersection.debug(f"point_slope:{point_slope}")
# 当斜率与斜率的百分比误差在1e-3以内,就认为在线上
if np.abs((point_slope-line_slope)/line_slope)<=precision:
logger_line_intersection.debug(f"isline:{True}")
return True
else:
return False
def isinsegment(point:tuple,line,precision=1e-3,external=True):
'''
判断点是否在线段上
:param point:
:param line:
:param precision:
:param external:
:return:
'''
# 先判断是不是在线上,在判断是不是在线段内
if isinline(point,line,precision=precision):
# 如果允许查找延长线上的点,只判断在线上就行了。
if external:
return True
else:
x_sign = np.sign((point[0] - line[1][0]) * (point[0] - line[0][0]))
y_sign = np.sign((point[1] - line[1][1]) * (point[1] - line[0][1]))
logger_line_intersection.debug(f"x_sign{x_sign}")
logger_line_intersection.debug(f"y_sign{y_sign}")
# 均异号,是在线段内
if x_sign<= 0 and y_sign<=0 :
logger_line_intersection.debug(f"isinsegment:{True}")
return True
else:
logger_line_intersection.debug(f"isinsegment:{False}")
return False
else:
logger_line_intersection.debug(f"isinsegment:{False}")
return False
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
div = det(xdiff, ydiff)
if div == 0:
raise Exception('lines do not intersect')
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
logger_line_intersection.debug(f"line_intersection:{x,y}")
# 允许交点在延长线上
if external:
return x, y
# 交点是否在线段内
elif isinsegment((x,y),line1,precision=precision,external=external) and isinsegment((x,y),line2,precision=precision,external=external):
return x, y
#如果交点不再任何线上,返回None
else:
return None,None