I have a line from A to B and a circle positioned at C with the radius R.
What is a good algorithm to use to check whether the line intersects the circle? And at what coordinate along the circles edge it occurred?
I have a line from A to B and a circle positioned at C with the radius R.
What is a good algorithm to use to check whether the line intersects the circle? And at what coordinate along the circles edge it occurred?
Taking
Compute:
d = L - E ( Direction vector of ray, from start to end )
f = E - C ( Vector from center sphere to ray start )
Then the intersection is found by..
Plugging:
P = E + t * d
This is a parametric equation:
Px = Ex + tdx
Py = Ey + tdy
into
(x - h)2 + (y - k)2 = r2
(h,k) = center of circle.
to get:
x2 - 2xh + h2 + y2 - 2yk + k2 - r2 = 0
x = ex + tdx
y = ey + tdy
( ex + tdx )2 - 2( ex + tdx )h + h2 + ( ey + tdy )2 - 2( ey + tdy )k + k2 - r2 = 0
ex2 + 2extdx + t2dx2 - 2exh - 2tdxh + h2 + ey2 + 2eytdy + t2dy2 - 2eyk - 2tdyk + k2 - r2 = 0
t2( dx2 + dy2 ) + 2t( exdx + eydy - dxh - dyk ) + ex2 + ey2 - 2exh - 2eyk + h2 + k2 - r2 = 0
t2( _d * _d ) + 2t( _e * _d - _d * _c ) + _e * _e - 2( _e*_c ) + _c * _c - r2 = 0
*Where _d is the vector d and * is the dot product.*
t2( _d * _d ) + 2t( _d * ( _e - _c ) ) + ( _e - _c ) * ( _e - _c ) - r2 = 0
t2( _d * _d ) + 2t( _d * _f ) + _f * _f - r2 = 0
So we get:
t2 * (d DOT d) + 2t*( f DOT d ) + ( f DOT f - r2 ) = 0
So solving the quadratic equation:
Here is good solution in JavaScript (with all required mathematics and live illustration) https://bl.ocks.org/milkbread/11000965
Though
is_on
function in that solution needs modifications:No one seems to consider projection, am I completely off track here?
Project the vector
AC
ontoAB
. The projected vector,AD
, gives the new pointD
.If the distance between
D
andC
is smaller than (or equal to)R
we have an intersection.Like this:
In this post circle line collision will be checked by checking distance between circle center and point on line segment (Ipoint) that represent intersection point between normal N (Image 2) from circle center to line segment.
(https://i.stack.imgur.com/3o6do.png)
On image 1 one circle and one line are shown, vector A point to line start point, vector B point to line end point, vector C point to circle center. Now we must find vector E (from line start point to circle center) and vector D (from line start point to line end point) this calculation is shown on image 1.
(https://i.stack.imgur.com/7098a.png)
At image 2 we can see that vector E is projected on Vector D by "dot product" of vector E and unit vector D, result of dot product is scalar Xp that represent the distance between line start point and point of intersection (Ipoint) of vector N and vector D. Next vector X is found by multiplying unit vector D and scalar Xp.
Now we need to find vector Z (vector to Ipoint), its easy its simple vector addition of vector A (start point on line) and vector X. Next we need to deal with special cases we must check is Ipoint on line segment, if its not we must find out is it left of it or right of it, we will use vector closest to determine which point is closest to circle.
(https://i.stack.imgur.com/p9WIr.png)
When projection Xp is negative Ipoint is left of line segment, vector closest is equal to vector of line start point, when projection Xp is greater then magnitude of vector D then Ipoint is right of line segment then closest vector is equal to vector of line end point in any other case closest vector is equal to vector Z.
Now when we have closest vector , we need to find vector from circle center to Ipoint (dist vector), its simple we just need to subtract closest vector from center vector. Next just check if vector dist magnitude is less then circle radius if it is then they collide, if its not there is no collision.
(https://i.stack.imgur.com/QJ63q.png)
For end, we can return some values for resolving collision , easiest way is to return overlap of collision (subtract radius from vector dist magnitude) and return axis of collision, its vector D. Also intersection point is vector Z if needed.
I wrote a small script to test intersection by projecting circle's center point on to line.
http://jsfiddle.net/ercang/ornh3594/1/
If you need to check the collision with the segment, you also need to consider circle center's distance to start and end points.
https://jsfiddle.net/ercang/menp0991/
This solution I found seemed a little easier to follow then some of the other ones.
Taking:
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 at0,0
By the way, whenever I subtract points from each other I am subtracting the
x
's and then subtracting they
'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
andp4
:Ok. Now I need to set these equations equal. First I need to solve the circle's equation for
x
Then I set them equal:
And solve for the quadratic equation (
0 = ax^2 + bx + c
):Now I have my
a
,b
, andc
.So I put this into the quadratic formula:
And substitute in by values then simplify as much as possible:
This is almost as far as it will simplify. Finally, separate out to equations with the ±:
Then simply plug the result of both of those equations into the
x
inmx + b
. For clarity, I wrote some JavaScript code to show how to use this: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.