Determine whether the two line segments intersect, and find the intersection point

 

 

First, the previous schematic.

According to the illustration, the line segment a is represented as endpoints a1 and a2, and the line segment b is represented as endpoints b1 and b2. In order to use the cross product relationship of vectors, the endpoints of the line segment are regarded as four vectors, and the vectors are represented in bold below. According to vector operations It can be seen that 
a=a2-a1, 
b=b2-b1. 
Express the line segment as a parametric equation: 
a=a1 + ta 
b=b1 + ub 
where the parameters t, u take the value [0,1]

The intersection of two line segments has the following relationship: 
a1 + ta=b1 + ub 
. Multiply both sides of the above equation by b at the same time, and get: 
(a1+ta) xb=(b1+ub) xb 
Since bxb=0, we can get 
a1 xb + taxb =b1 xb 
solves the parameter t 
t=(b1-a1)xb/(axb) the 
same, solves the parameter u 
u=ax (a1-b1)/(axb)

When 0<=t<=1, and 0<=u<=1, the two line segments have intersections. 
Substituting into the parametric equation of line segment a, you can get the line segment intersection coordinates: 
a1+ta 
uses the intermediate variable in the above formula The original line segment endpoint representation can get the intersection point represented by the line segment endpoint.

code 1

// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines 
// intersect the intersection point may be stored in the floats i_x and i_y.
char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, 
    float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
{
    float s1_x, s1_y, s2_x, s2_y;
    s1_x = p1_x - p0_x;     s1_y = p1_y - p0_y;
    s2_x = p3_x - p2_x;     s2_y = p3_y - p2_y;

    float s, t;
    s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
    t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
    {
        // Collision detected
        if (i_x != NULL)
            *i_x = p0_x + (t * s1_x);
        if (i_y != NULL)
            *i_y = p0_y + (t * s1_y);
        return 1;
    }

    return 0; // No collision
}
code 2

Optimized version to exclude parallel line segments and avoid accuracy errors

int get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y, 
    float p2_x, float p2_y, float p3_x, float p3_y, float *i_x, float *i_y)
{
    float s02_x, s02_y, s10_x, s10_y, s32_x, s32_y, s_numer, t_numer, denom, t;
    s10_x = p1_x - p0_x;
    s10_y = p1_y - p0_y;
    s32_x = p3_x - p2_x;
    s32_y = p3_y - p2_y;

    denom = s10_x * s32_y-s32_x * s10_y;
    if (denom == 0)//Parallel or collinear
        return 0; //
    Collinear bool denomPositive = denom> 0;

    s02_x = p0_x-p2_x;
    s02_y = p0_y-p2_y;
    s_numer = s10_x * s02_y-s10_y * s02_x;
    if ((s_numer <0) == denomPositive)//The parameters must be greater than or equal to 0 and less than or equal to 1, and the numerator and denominator must be the same Number and the numerator is less than or equal to the denominator
        return 0; // No collision

    t_numer = s32_x * s02_y - s32_y * s02_x;
    if ((t_numer < 0) == denomPositive)
        return 0; // No collision

    if (fabs(s_numer) > fabs(denom) || fabs(t_numer) > fabs(denom))
        return 0; // No collision
    // Collision detected
    t = t_numer / denom;
    if (i_x != NULL)
        *i_x = p0_x + (t * s10_x);
    if (i_y != NULL)
        *i_y = p0_y + (t * s10_y);

    return 1;
}

Guess you like

Origin blog.csdn.net/u011105442/article/details/88746870