Skip to content

Instantly share code, notes, and snippets.

@jupdike
Last active April 19, 2024 06:13
Show Gist options
  • Save jupdike/bfe5eb23d1c395d8a0a1a4ddd94882ac to your computer and use it in GitHub Desktop.
Save jupdike/bfe5eb23d1c395d8a0a1a4ddd94882ac to your computer and use it in GitHub Desktop.
Find the intersections (two points) of two circles, if they intersect at all
// based on the math here:
// http://math.stackexchange.com/a/1367732
// x1,y1 is the center of the first circle, with radius r1
// x2,y2 is the center of the second ricle, with radius r2
function intersectTwoCircles(x1,y1,r1, x2,y2,r2) {
var centerdx = x1 - x2;
var centerdy = y1 - y2;
var R = Math.sqrt(centerdx * centerdx + centerdy * centerdy);
if (!(Math.abs(r1 - r2) <= R && R <= r1 + r2)) { // no intersection
return []; // empty list of results
}
// intersection(s) should exist
var R2 = R*R;
var R4 = R2*R2;
var a = (r1*r1 - r2*r2) / (2 * R2);
var r2r2 = (r1*r1 - r2*r2);
var c = Math.sqrt(2 * (r1*r1 + r2*r2) / R2 - (r2r2 * r2r2) / R4 - 1);
var fx = (x1+x2) / 2 + a * (x2 - x1);
var gx = c * (y2 - y1) / 2;
var ix1 = fx + gx;
var ix2 = fx - gx;
var fy = (y1+y2) / 2 + a * (y2 - y1);
var gy = c * (x1 - x2) / 2;
var iy1 = fy + gy;
var iy2 = fy - gy;
// note if gy == 0 and gx == 0 then the circles are tangent and there is only one solution
// but that one solution will just be duplicated as the code is currently written
return [[ix1, iy1], [ix2, iy2]];
}
@Abhirikshma
Copy link

Abhirikshma commented Aug 17, 2023

Comparing with the math, shouldn't the denominator in line 17 be 2 * R instead of 2 * R2?
(I know this is an old thread, but still clarifying for those who use this as reference)

Never mind, I got confused by the similar notation of the math and the code! 2 * R2 is correct for a

@MattFerraro
Copy link

Thanks for posting! Here's a compatible Rust version!

struct Point2 {
    x: f64,
    y: f64,
}

struct Circle2 {
    center: Point2,
    radius: f64,
}


pub fn circle_intersection(&self, circle_a: &Circle2, circle_b: &Circle2) -> Vec<Point2> {
    let center_a = circle_a.center;
    let center_b = circle_b.center;
    let r_a = circle_a.radius;
    let r_b = circle_b.radius;

    let center_dx = center_b.x - center_a.x;
    let center_dy = center_b.y - center_a.y;
    let center_dist = center_dx.hypot(center_dy);

    if !(center_dist <= r_a + r_b && center_dist >= r_a - r_b) {
        return vec![];
    }

    let r_2 = center_dist * center_dist;
    let r_4 = r_2 * r_2;
    let a = (r_a * r_a - r_b * r_b) / (2.0 * r_2);
    let r_2_r_2 = r_a * r_a - r_b * r_b;
    let c = (2.0 * (r_a * r_a + r_b * r_b) / r_2 - r_2_r_2 * r_2_r_2 / r_4 - 1.0).sqrt();

    let fx = (center_a.x + center_b.x) / 2.0 + a * (center_b.x - center_a.x);
    let gx = c * (center_b.y - center_a.y) / 2.0;
    let ix1 = fx + gx;
    let ix2 = fx - gx;

    let fy = (center_a.y + center_b.y) / 2.0 + a * (center_b.y - center_a.y);
    let gy = c * (center_a.x - center_b.x) / 2.0;
    let iy1 = fy + gy;
    let iy2 = fy - gy;

    vec![Point2 { x: ix1, y: iy1 }, Point2 { x: ix2, y: iy2}]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment