Circle line-segment collision detection algorithm?

前端 未结 28 1773
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 06:38

I have a line from A to B and a circle positioned at C with the radius R.

\"Image\"

What is a good alg

28条回答
  •  没有蜡笔的小新
    2020-11-22 06:58

    This solution I found seemed a little easier to follow then some of the other ones.

    Taking:

    p1 and p2 as the points for the line, and
    c as the center point for the circle and r for the radius
    

    I would solve for the equation of the line in slope-intercept form. However, I didn't want to have to deal with difficult equations with c as a point, so I just shifted the coordinate system over so that the circle is at 0,0

    p3 = p1 - c
    p4 = p2 - c
    

    By the way, whenever I subtract points from each other I am subtracting the x's and then subtracting the y's, and putting them into a new point, just in case someone didn't know.

    Anyway, I now solve for the equation of the line with p3 and p4:

    m = (p4_y - p3_y) / (p4_x - p3) (the underscore is an attempt at subscript)
    y = mx + b
    y - mx = b (just put in a point for x and y, and insert the m we found)
    

    Ok. Now I need to set these equations equal. First I need to solve the circle's equation for x

    x^2 + y^2 = r^2
    y^2 = r^2 - x^2
    y = sqrt(r^2 - x^2)
    

    Then I set them equal:

    mx + b = sqrt(r^2 - x^2)
    

    And solve for the quadratic equation (0 = ax^2 + bx + c):

    (mx + b)^2 = r^2 - x^2
    (mx)^2 + 2mbx + b^2 = r^2 - x^2
    0 = m^2 * x^2 + x^2 + 2mbx + b^2 - r^2
    0 = (m^2 + 1) * x^2 + 2mbx + b^2 - r^2
    

    Now I have my a, b, and c.

    a = m^2 + 1
    b = 2mb
    c = b^2 - r^2
    

    So I put this into the quadratic formula:

    (-b ± sqrt(b^2 - 4ac)) / 2a
    

    And substitute in by values then simplify as much as possible:

    (-2mb ± sqrt(b^2 - 4ac)) / 2a
    (-2mb ± sqrt((-2mb)^2 - 4(m^2 + 1)(b^2 - r^2))) / 2(m^2 + 1)
    (-2mb ± sqrt(4m^2 * b^2 - 4(m^2 * b^2 - m^2 * r^2 + b^2 - r^2))) / 2m^2 + 2
    (-2mb ± sqrt(4 * (m^2 * b^2 - (m^2 * b^2 - m^2 * r^2 + b^2 - r^2))))/ 2m^2 + 2
    (-2mb ± sqrt(4 * (m^2 * b^2 - m^2 * b^2 + m^2 * r^2 - b^2 + r^2)))/ 2m^2 + 2
    (-2mb ± sqrt(4 * (m^2 * r^2 - b^2 + r^2)))/ 2m^2 + 2
    (-2mb ± sqrt(4) * sqrt(m^2 * r^2 - b^2 + r^2))/ 2m^2 + 2
    (-2mb ± 2 * sqrt(m^2 * r^2 - b^2 + r^2))/ 2m^2 + 2
    (-2mb ± 2 * sqrt(m^2 * r^2 + r^2 - b^2))/ 2m^2 + 2
    (-2mb ± 2 * sqrt(r^2 * (m^2 + 1) - b^2))/ 2m^2 + 2
    

    This is almost as far as it will simplify. Finally, separate out to equations with the ±:

    (-2mb + 2 * sqrt(r^2 * (m^2 + 1) - b^2))/ 2m^2 + 2 or     
    (-2mb - 2 * sqrt(r^2 * (m^2 + 1) - b^2))/ 2m^2 + 2 
    

    Then simply plug the result of both of those equations into the x in mx + b. For clarity, I wrote some JavaScript code to show how to use this:

    function interceptOnCircle(p1,p2,c,r){
        //p1 is the first line point
        //p2 is the second line point
        //c is the circle's center
        //r is the circle's radius
    
        var p3 = {x:p1.x - c.x, y:p1.y - c.y} //shifted line points
        var p4 = {x:p2.x - c.x, y:p2.y - c.y}
    
        var m = (p4.y - p3.y) / (p4.x - p3.x); //slope of the line
        var b = p3.y - m * p3.x; //y-intercept of line
    
        var underRadical = Math.pow((Math.pow(r,2)*(Math.pow(m,2)+1)),2)-Math.pow(b,2)); //the value under the square root sign 
    
        if (underRadical < 0){
        //line completely missed
            return false;
        } else {
            var t1 = (-2*m*b+2*Math.sqrt(underRadical))/(2 * Math.pow(m,2) + 2); //one of the intercept x's
            var t2 = (-2*m*b-2*Math.sqrt(underRadical))/(2 * Math.pow(m,2) + 2); //other intercept's x
            var i1 = {x:t1,y:m*t1+b} //intercept point 1
            var i2 = {x:t2,y:m*t2+b} //intercept point 2
            return [i1,i2];
        }
    }
    

    I hope this helps!

    P.S. If anyone finds any errors or has any suggestions, please comment. I am very new and welcome all help/suggestions.

提交回复
热议问题