# Math / Circle and Ray Intersection

Posted On 04.16.2022

Let $P$ be the intersection point, $A$ is the anchor point of the ray, $B$ is the endpoint of the ray (assuming the ray is length-limited) and $C$ is the circle’s center point, with radius $r$.

\begin{align} a &= (B_x - A_x) ^ 2 + (B_y - A_y) ^ 2 \\ b &= 2((B_x - A_x)(A_x - C_x) + (B_y - A_y)(A_y - C_y)) \\ c &= (A_x - C_x) ^ 2 + (A_y - C_y) ^ 2 - r ^ 2 \\ \Delta &= b ^ 2 - 4ac \end{align}

Now we have 3 cases:

• $\Delta < 0$: ray does not intersect the circle
• $\Delta = 0$: ray intersects the circle in one point (tangent)
• $\Delta > 0$: ray intersects the circle in two points (secant)

If $\Delta = 0$, we have $t = \tfrac{-b}{2a}$, and if $t \geq 0$, we can calculate the position of $P$ as:

\begin{align} P_x &= t(B_x - A_x) + A_x \ P_y &= t(B_y - A_y) + A_y \end{align}

If $\Delta > 0$, we have:

\begin{align} t_1 &= \tfrac{-b -\sqrt{\Delta}}{2a} \\ t_2 &= \tfrac{-b +\sqrt{\Delta}}{2a} \\ \end{align}

In this case, if $t_i \geq 0$ then the two intersection points can be calculated as:

\begin{align} P_{i_x} &= t_i(B_x - A_x) + A_x \\ P_{i_y} &= t_i(B_y - A_y) + A_y \end{align}

Implementation in JavaScript:

function getIntersectionPoint(ray, circle) {
const [A, B] = ray;
const C = { x: circle.x, y: circle.y };

const a = (B.x - A.x) ** 2 + (B.y - A.y) ** 2;
const b = 2 * ((B.x - A.x) * (A.x - C.x) + (B.y - A.y) * (A.y - C.y));
const c = (A.x - C.x) ** 2 + (A.y - C.y) ** 2 - r ** 2;
const discriminant = b ** 2 - 4 * a * c;

const result = [];

if(discriminant === 0) {
const t = -b / (2 * a);

if(t >= 0) {
const x = t * (B.x - A.x) + A.x;
const y = t * (B.y - A.y) + A.y;

result.push({ x, y });
}
} else if(discriminant > 0) {
const discriminantSqrt = Math.sqrt(discriminant);
const t1 = (-b + discriminantSqrt) / (2 * a);
const t2 = (-b - discriminantSqrt) / (2 * a);

if(t1 >= 0) {
const x = t1 * (B.x - A.x) + A.x;
const y = t1 * (B.y - A.y) + A.y;

result.push({ x, y })
}

if(t2 >= 0) {
const x = t2 * (B.x - A.x) + A.x;
const y = t2 * (B.y - A.y) + A.y;

result.push({ x, y });
}
}

return result;
}


References: