← Back to index

Circle ↔ circle intersection

Two circles intersect at 0, 1, or 2 points. Drop a perpendicular from the line between centres at distance a, then step ±h along it. The first circle is fixed; the second follows the mouse.

See also: Circle ↔ line intersection — same idea (foot of perpendicular ± offset), with a line replacing the second circle.

Pseudocode

d = distance(c1, c2)
if (d > r1 + r2)        return []           // too far apart
if (d < |r1 - r2|)      return []           // one contained
a = (r1*r1 - r2*r2 + d*d) / (2 * d)
h = sqrt(r1*r1 - a*a)
mid = c1 + (c2 - c1) * (a / d)
perp = perpendicular(c2 - c1) / d     // unit, 90°
return [mid + perp * h, mid - perp * h]

Source

const c1x = 120, c1y = 150, r1 = 70
const c2x = mouseX, c2y = mouseY, r2 = 55

const dx = c2x - c1x
const dy = c2y - c1y
const d = Math.sqrt(dx * dx + dy * dy)

if (d > r1 + r2 || d < Math.abs(r1 - r2) || d === 0) {
    // no intersection
} else {
    const a = (r1 * r1 - r2 * r2 + d * d) / (2 * d)
    const h = Math.sqrt(r1 * r1 - a * a)
    const mx = c1x + dx * a / d
    const my = c1y + dy * a / d
    // perpendicular to (dx, dy), scaled by h/d
    const ix1 = mx + (dy * h / d)
    const iy1 = my - (dx * h / d)
    const ix2 = mx - (dy * h / d)
    const iy2 = my + (dx * h / d)
}