【几何数学】【Python】【C++】判断两条线段是否相交,若相交则求出交点坐标

判断线段是否相交的办法(使用了向量叉积的方法):

首先,通过给定的线段端点坐标p1、p2、p3和p4构建了四个向量v1、v2、v3和v4:
v1表示从p1指向p2的向量,其分量为[p2[0] - p1[0], p2[1] - p1[1]]。
v2表示从p3指向p4的向量,其分量为[p4[0] - p3[0], p4[1] - p3[1]]。
v3表示从p1指向p3的向量,其分量为[p3[0] - p1[0], p3[1] - p1[1]]。
v4表示从p1指向p4的向量,其分量为[p4[0] - p1[0], p4[1] - p1[1]]。
接下来,计算了两个叉积cross1和cross2:
cross1表示v1和v3的叉积,计算公式为v1[0] * v3[1] - v1[1] * v3[0]。
cross2表示v1和v4的叉积,计算公式为v1[0] * v4[1] - v1[1] * v4[0]。
最后,根据两个叉积的乘积进行判断:
如果cross1和cross2的乘积小于等于0,意味着v1和v3位于不同的半平面或者其中一个线段的某个端点在另一个线段上,这时可以判断两条线段相交。
如果cross1和cross2的乘积大于0,意味着v1和v3位于同一侧或者两个线段没有交点,这时可以判断两条线段不相交。
根据以上逻辑,如果条件满足,则返回True表示线段相交,否则返回False表示线段不相交。

Python代码实现:

def are_lines_intersect(p1, p2, p3, p4):
    v1 = [p2[0] - p1[0], p2[1] - p1[1]]
    v2 = [p4[0] - p3[0], p4[1] - p3[1]]
    v3 = [p3[0] - p1[0], p3[1] - p1[1]]
    v4 = [p4[0] - p1[0], p4[1] - p1[1]]

    cross1 = v1[0] * v3[1] - v1[1] * v3[0]
    cross2 = v1[0] * v4[1] - v1[1] * v4[0]

    if cross1 * cross2 <= 0:
        return True
    else:
        return False


def compute_intersection(p1, p2, p3, p4):
    if p1[0] == p2[0]:  # p1p2为垂直线
        x = p1[0]
        slope2 = (p4[1] - p3[1]) / (p4[0] - p3[0])
        intercept2 = p3[1] - slope2 * p3[0]
        y = slope2 * x + intercept2
    elif p3[0] == p4[0]:  # p3p4为垂直线
        x = p3[0]
        slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0])
        intercept1 = p1[1] - slope1 * p1[0]
        y = slope1 * x + intercept1
    else:
        slope1 = (p2[1] - p1[1]) / (p2[0] - p1[0])
        slope2 = (p4[1] - p3[1]) / (p4[0] - p3[0])
        intercept1 = p1[1] - slope1 * p1[0]
        intercept2 = p3[1] - slope2 * p3[0]
        x = (intercept2 - intercept1) / (slope1 - slope2)
        y = slope1 * x + intercept1

    return [x, y]


if __name__ == '__main__':
    p1 = [10, 20]
    p2 = [0, 100]
    p3 = [100, 50]
    p4 = [200, 30]
    # p1 p2 是一条线段
    # p3 p4 是另一条线段
    # 判断是否相交,相交且求交点
    if are_lines_intersect(p1, p2, p3, p4):
        print(compute_intersection(p1, p2, p3, p4))
        x, y = compute_intersection(p1, p2, p3, p4)
    else:
        print("No intersection")

    # 画图
    import matplotlib.pyplot as plt

    plt.plot([p1[0], p2[0]], [p1[1], p2[1]], color='r')
    plt.plot([p3[0], p4[0]], [p3[1], p4[1]], color='b')
    # 加注释
    plt.annotate('p1', xy=(p1[0], p1[1]), xytext=(p1[0] + 10, p1[1] + 10))
    plt.annotate('p2', xy=(p2[0], p2[1]), xytext=(p2[0] + 10, p2[1] + 10))
    plt.annotate('p3', xy=(p3[0], p3[1]), xytext=(p3[0] + 10, p3[1] + 10))
    plt.annotate('p4', xy=(p4[0], p4[1]), xytext=(p4[0] + 10, p4[1] + 10))
    try:
        # 绘制交点
        plt.scatter(x, y, color='g')
        # 给交点加注释
        plt.annotate('intersection', xy=(x, y), xytext=(x + 10, y + 10),
                     arrowprops=dict(facecolor='g', shrink=0.05))
    except:
        pass
    # 坐标轴等距
    plt.axis('equal')
    plt.show()


绘制的图:
在这里插入图片描述
在这里插入图片描述
不相交:
在这里插入图片描述

C++ 借助opencv的数据结构

// are_lines_intersect: 判断两条线段是否相交
// 原理:判断两条线段的端点是否在另一条线段的两侧
bool are_lines_intersect(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) {
    
    
    cv::Point2f v1 = p2 - p1;
    cv::Point2f v2 = p4 - p3;
    cv::Point2f v3 = p3 - p1;
    cv::Point2f v4 = p4 - p1;
    float cross1 = v1.x * v3.y - v1.y * v3.x;
    float cross2 = v1.x * v4.y - v1.y * v4.x;
    if (cross1 * cross2 <= 0) {
    
    
        return true;
    } else {
    
    
        return false;
    }
}
// compute_intersection: 计算两条线段的交点
// 原理:计算两条线段的斜率和截距,然后解方程
cv::Point2f compute_intersection(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) {
    
    
    cv::Point2f intersection;
    if (p1.x == p2.x) {
    
    
        intersection.x = p1.x;
        float slope2 = (p4.y - p3.y) / (p4.x - p3.x);
        float intercept2 = p3.y - slope2 * p3.x;
        intersection.y = slope2 * intersection.x + intercept2;
    } else if (p3.x == p4.x) {
    
    
        intersection.x = p3.x;
        float slope1 = (p2.y - p1.y) / (p2.x - p1.x);
        float intercept1 = p1.y - slope1 * p1.x;
        intersection.y = slope1 * intersection.x + intercept1;
    } else {
    
    
        float slope1 = (p2.y - p1.y) / (p2.x - p1.x);
        float slope2 = (p4.y - p3.y) / (p4.x - p3.x);
        float intercept1 = p1.y - slope1 * p1.x;
        float intercept2 = p3.y - slope2 * p3.x;
        intersection.x = (intercept2 - intercept1) / (slope1 - slope2);
        intersection.y = slope1 * intersection.x + intercept1;
    }
    return intersection;
}

猜你喜欢

转载自blog.csdn.net/x1131230123/article/details/131452632