-
-
Save jupdike/bfe5eb23d1c395d8a0a1a4ddd94882ac to your computer and use it in GitHub Desktop.
// 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]]; | |
} |
Here is an example using turtletoy which is based on Java Script
see: https://turtletoy.net/turtle/c60ea8510d
// Locate the intersection(s) of 2 circles
// thanks to jupdike/IntersectTwoCircles.js
// https://gist.github.com/jupdike/bfe5eb23d1c395d8a0a1a4ddd94882ac
// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);
const radius = 40; // min=5 max=100 step=1
const X1 = -14; // min=-100 max=100 step=1
const Y1 = -12; // min=-100 max=100 step=1
const X2 = 28; // min=-100 max=100 step=1
const Y2 = 23; // min=-100 max=100 step=1
// Global code will be evaluated once.
const turtle = new Turtle();
centeredCircle(X1, Y1, radius, 360);
centeredCircle(X2, Y2, radius, 360);
array_name = intersectTwoCircles(X1, Y1,radius, X2, Y2 ,radius)
// thanks to jupdike/IntersectTwoCircles.js
// https://gist.github.com/jupdike/bfe5eb23d1c395d8a0a1a4ddd94882ac
// 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 = RR;
var R4 = R2R2;
var a = (r1r1 - r2r2) / (2 * R2);
var r2r2 = (r1r1 - r2r2);
var c = Math.sqrt(2 * (r1r1 + r2r2) / 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;
centeredCircle(ix1, iy1, 2, 360); // highlight intersection point 1
centeredCircle(ix2, iy2, 2, 360); // highlight intersection point 1
// 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];
}
// thanks to Reinder for this function
// Draws a circle centered a specific x,y location
// and returns the turtle to the original angle after it completes the circle.
function centeredCircle(x,y, radius, ext) {
turtle.penup();
turtle.goto(x,y);
turtle.backward(radius);
turtle.left(90);
turtle.pendown(); turtle.circle(radius, ext);
turtle.right(90); turtle.penup(); turtle.forward(radius); turtle.pendown();
}
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
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}]
}
A simple TypeScript adaptation:
interface Point {
x: number;
y: number;
}
interface Circle {
cx: number;
cy: number;
r: number;
}
const intersectCircleCircle = (c1: Circle, c2: Circle): Point[] => {
const { cx: x1, cy: y1, r: r1 } = c1;
const { cx: x2, cy: y2, r: r2 } = c2;
const centerdx = x1 - x2;
const centerdy = y1 - y2;
const 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
const R2 = R * R;
const R4 = R2 * R2;
const a = (r1 * r1 - r2 * r2) / (2 * R2);
const r2r2 = r1 * r1 - r2 * r2;
const c = Math.sqrt((2 * (r1 * r1 + r2 * r2)) / R2 - (r2r2 * r2r2) / R4 - 1);
const fx = (x1 + x2) / 2 + a * (x2 - x1);
const gx = (c * (y2 - y1)) / 2;
const ix1 = fx + gx;
const ix2 = fx - gx;
const fy = (y1 + y2) / 2 + a * (y2 - y1);
const gy = (c * (x1 - x2)) / 2;
const iy1 = fy + gy;
const 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 [
{ x: ix1, y: iy1 },
{ x: ix2, y: iy2 },
];
};
Python 3.11.2