Skip to content Skip to sidebar Skip to footer

Circle Line Segment Collision

I need to detect collision circle with any line. I have array with verticles of polygon (x, y) and draw this polygon in loop. For detection I use algorithm, which calculate triangl

Solution 1:

Circle line segment intercept

UPDATE

This answer includes line line intercept, moving a line along its normal, distance point (circle) to line, and circle line intercept.

The circle is

varcircle= {
    radius :500,
    center :point(1000,1000),
}

The line segment is

varline= {
    p1 :point(500,500),
    p2 :point(2000,1000),
}

A point is

varpoint= {
    x :100,
    y :100,
}

Thus the function to find the intercept of a line segment width a circle

The function returns an array of up to two point on the line segment. If no points found returns an empty array.

functioninteceptCircleLineSeg(circle, line){
    var a, b, c, d, u1, u2, ret, retP1, retP2, v1, v2;
    v1 = {};
    v2 = {};
    v1.x = line.p2.x - line.p1.x;
    v1.y = line.p2.y - line.p1.y;
    v2.x = line.p1.x - circle.center.x;
    v2.y = line.p1.y - circle.center.y;
    b = (v1.x * v2.x + v1.y * v2.y);
    c = 2 * (v1.x * v1.x + v1.y * v1.y);
    b *= -2;
    d = Math.sqrt(b * b - 2 * c * (v2.x * v2.x + v2.y * v2.y - circle.radius * circle.radius));
    if(isNaN(d)){ // no interceptreturn [];
    }
    u1 = (b - d) / c;  // these represent the unit distance of point one and two on the line
    u2 = (b + d) / c;    
    retP1 = {};   // return points
    retP2 = {}  
    ret = []; // return arrayif(u1 <= 1 && u1 >= 0){  // add point if on the line segment
        retP1.x = line.p1.x + v1.x * u1;
        retP1.y = line.p1.y + v1.y * u1;
        ret[0] = retP1;
    }
    if(u2 <= 1 && u2 >= 0){  // second add point if on the line segment
        retP2.x = line.p1.x + v1.x * u2;
        retP2.y = line.p1.y + v1.y * u2;
        ret[ret.length] = retP2;
    }       
    return ret;
}

UPDATE

Line line intercept.

Returns a point if found else returns undefined.

functioninterceptLines(line,line1){  
    var v1, v2, c, u;
    v1 = {};
    v2 = {};
    v3 = {};
    v1.x = line.p2.x - line.p1.x; // vector of line
    v1.y = line.p2.y - line.p1.y;
    v2.x = line1.p2.x - line1.p1.x; //vector of line2
    v2.y = line1.p2.y - line1.p1.y;
    var c = v1.x * v2.y - v1.y * v2.x; // cross of the two vectorsif(c !== 0){ 
        v3.x = line.p1.x - line1.p1.x; 
        v3.y = line.p1.y - line1.p1.y;                
        u = (v2.x * v3.y - v2.y * v3.x) / c; // unit distance of intercept point on this linereturn {x : line.p1.x + v1.x * u, y : line.p1.y + v1.y * u};
    }
    returnundefined;
}

Lift Line

Move line along its normal

functionliftLine(line,dist){
    var v1,l
    v1 = {};
    v1.x = line.p2.x - line.p1.x; // convert line to vector
    v1.y = line.p2.y - line.p1.y;
    l = Math.sqrt(v1.x * v1.x + v1.y * v1.y); // get length;
    v1.x /= l;  // Assuming you never pass zero length lines
    v1.y /= l;
    v1.x *= dist; // set the length
    v1.y *= dist;
    // move the line along its normal the required distance
    line.p1.x -= v1.y;
    line.p1.y += v1.x;
    line.p2.x -= v1.y;
    line.p2.y += v1.x;

    return line; // if needed 
}

Distance circle (or point) to a line segment

Returns the closest distance to the line segment. It is just the circle center that I am using. So you can replace circle with a point

functioncircleDistFromLineSeg(circle,line){
    var v1, v2, v3, u;
    v1 = {};
    v2 = {};
    v3 = {};
    v1.x = line.p2.x - line.p1.x;
    v1.y = line.p2.y - line.p1.y;
    v2.x = circle.center.x - line.p1.x;
    v2.y = circle.center.y - line.p1.y;
    u = (v2.x * v1.x + v2.y * v1.y) / (v1.y * v1.y + v1.x * v1.x); // unit dist of point on lineif(u >= 0 && u <= 1){
        v3.x = (v1.x * u + line.p1.x) - circle.center.x;
        v3.y = (v1.y * u + line.p1.y) - circle.center.y;
        v3.x *= v3.x;
        v3.y *= v3.y;
        returnMath.sqrt(v3.y + v3.x); // return distance from line
    } 
    // get distance from end points
    v3.x = circle.center.x - line.p2.x;
    v3.y = circle.center.y - line.p2.y;
    v3.x *= v3.x;  // square vectors
    v3.y *= v3.y;    
    v2.x *= v2.x;
    v2.y *= v2.y;
    returnMath.min(Math.sqrt(v2.y + v2.x), Math.sqrt(v3.y + v3.x)); // return smaller of two distances as the result
}

Post a Comment for "Circle Line Segment Collision"