[Geometric Mathematics] [Python] [C++] Determine whether two line segments intersect, and if so, find the coordinates of the intersection point

The way to judge whether the line segments intersect (using the method of vector cross product):

首先,通过给定的线段端点坐标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 code implementation:

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()


Plotted graph:
insert image description here
insert image description here
disjoint:
insert image description here

C++ uses the data structure of 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;
}

Guess you like

Origin blog.csdn.net/x1131230123/article/details/131452632