拿来即用--python判断线段是否相交及求相应交点

编写了几个使用的函数,实现了:

  • 判断线段是否相交,或其延长线是否相交
  • 函数内定义了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
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值