7

I'm looking for a definitive answer, maybe a function cos I'm slow, that will determine if a line segment and circle have collided, in javascript (working with canvas)

A function like the one below that simply returns true if collided or false if not would be awesome. I might even donate a baby to you.

function isCollided(lineP1x, lineP1y, lineP2x, lineP2y, circlex, circley, radius) {

    ...
}

I've found plenty of formulas, like this one, but they are over my head.

8
  • 1
    Well, even if you didn't follow the maths, there was code presented in the answer there, which should be useful to you. Commented Jun 9, 2012 at 1:29
  • 4
    This is the exact moment that your high school algebra will help you out in your life. Commented Jun 9, 2012 at 1:31
  • @Oli Charlesworth: I would have thought so, too. But I was confused on the first line: "float a = d.Dot( d )" :) Commented Jun 9, 2012 at 1:31
  • 1
    @Derek: Agree. Now I'm 30, balding and have nothing to show. Commented Jun 9, 2012 at 1:32
  • 1
    Facts: Circle formula: (x−h)^2+(y−k)^2=r^2 Line formula: y=a+bx You can solve for these 2 formula, and if you can get an answer, then there is a collision. Commented Jun 9, 2012 at 1:40

4 Answers 4

8

Here you will need some Math:

enter image description here This is the basic concept if you don't know how to solve equations in general. I will leave the rest of the thinking to you. ;) Figuring out CD's length isn't that hard.

If you are asking how, that's how: enter image description here Finding collisions in JavaScript is kind of complicated.

Sign up to request clarification or add additional context in comments.

8 Comments

A really really appreciate the help you've given me so far. But "find angle ABE then subtract angle DBE" is really not easy for me. I'm not mathematically inclined which is why I thought I'd give stackoverflow ago.
Nice graphics man! @Jarrod: Subtracting the numbers shouldn't be the problem, so I guess your problem is with trigonometry/vectors? There's lot of info about that on the internet, I doubt that it would be sensible to summarize it specifically for this question.
(Or simply Math.atan((m1 - m2)/(1 + m1*m2)), where m is the slope)
Don't be surprised if you found the angle does not look right, since in JavaScript all angle is in radian instead of degree.
Thanks again. Could you maybe go step by step as to how to get point C. I've still working on the problem but think I can work out the circle part.
|
4

I Spent about a day and a half to make it perfect.. Hope this helps.

function collisionCircleLine(circle, line) {
  // Both are objects

  var side1 = Math.sqrt(
    Math.pow(circle.x - line.p1.x, 2) + Math.pow(circle.y - line.p1.y, 2)
  ); // Thats the pythagoras theoram If I can spell it right

  var side2 = Math.sqrt(
    Math.pow(circle.x - line.p2.x, 2) + Math.pow(circle.y - line.p2.y, 2)
  );

  var base = Math.sqrt(
    Math.pow(line.p2.x - line.p1.x, 2) + Math.pow(line.p2.y - line.p1.y, 2)
  );

  if (circle.radius > side1 || circle.radius > side2) return true;

  var angle1 =
    Math.atan2(line.p2.x - line.p1.x, line.p2.y - line.p1.y) -
    Math.atan2(circle.x - line.p1.x, circle.y - line.p1.y); // Some complicated Math

  var angle2 =
    Math.atan2(line.p1.x - line.p2.x, line.p1.y - line.p2.y) -
    Math.atan2(circle.x - line.p2.x, circle.y - line.p2.y); // Some complicated Math again

  if (angle1 > Math.PI / 2 || angle2 > Math.PI / 2)
    // Making sure if any angle is an obtuse one and Math.PI / 2 = 90 deg
    return false;

  // Now if none are true then

  var semiperimeter = (side1 + side2 + base) / 2;

  var areaOfTriangle = Math.sqrt(
    semiperimeter *
      (semiperimeter - side1) *
      (semiperimeter - side2) *
      (semiperimeter - base)
  ); // Heron's formula for the area

  var height = (2 * areaOfTriangle) / base;

  if (height < circle.radius) return true;
  else return false;
}

And that is how you do it..

2 Comments

"And that is how you do it.."? But this is how you do not answer. on a lighter note, add some context to support your code buddy. Plainly posting some code is not a good way of answering.
I don't know if this works or not but Math.atan2 requires y and then x input you got it reversed.
1

Matt DesLauriers published a Javascript library for this problem at https://www.npmjs.com/package/line-circle-collision. The API is straightforward:

var circle = [5, 5],
    radius = 25,
    a = [5, 6],
    b = [10, 10]

var hit = collide(a, b, circle, radius)

Comments

0
function pointCircleCollide(point, circle, r) {
    if (r===0) return false
    var dx = circle[0] - point[0]
    var dy = circle[1] - point[1]
    return dx * dx + dy * dy <= r * r
}

var tmp = [0, 0]

function lineCircleCollide(a, b, circle, radius, nearest) {
    //check to see if start or end points lie within circle
    if (pointCircleCollide(a, circle, radius)) {
        if (nearest) {
            nearest[0] = a[0]
            nearest[1] = a[1]
        }
        return true
    } if (pointCircleCollide(b, circle, radius)) {
        if (nearest) {
            nearest[0] = b[0]
            nearest[1] = b[1]
        }
        return true
    }

    var x1 = a[0],
        y1 = a[1],
        x2 = b[0],
        y2 = b[1],
        cx = circle[0],
        cy = circle[1]

    //vector d
    var dx = x2 - x1
    var dy = y2 - y1

    //vector lc
    var lcx = cx - x1
    var lcy = cy - y1

    //project lc onto d, resulting in vector p
    var dLen2 = dx * dx + dy * dy //len2 of d
    var px = dx
    var py = dy
    if (dLen2 > 0) {
        var dp = (lcx * dx + lcy * dy) / dLen2
        px *= dp
        py *= dp
    }

    if (!nearest)
        nearest = tmp
    nearest[0] = x1 + px
    nearest[1] = y1 + py

    //len2 of p
    var pLen2 = px * px + py * py

    //check collision
    return pointCircleCollide(nearest, circle, radius)
            && pLen2 <= dLen2 && (px * dx + py * dy) >= 0
}

var circle = [5, 5],
    radius = 25,
    a = [5, 6],
    b = [10, 10]

var hit = lineCircleCollide(a, b, circle, radius)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.