I got the (x,y) center location of two circles and their radius but I need to find their intersection points (marked with red) using JavaScript.
I think the best explanation as far as the math is concerned is found here (Intersection of two circles), but I don't really understand the math so I'm not able to implement it.
For example d = ||P1 - P0|| , what do the || stand for? Does it mean that the resulting number is always a positive?
And also P2 = P0 + a ( P1 - P0 ) / d , aren't the P's here something like (10, 50)? But doing (10,50)+13 in JavaScript gives you 63, so it just ignores the first number, so what's suppose to happen? Should the outcome be (23,63) here or? And also the P1-P0 part or (40,30)-(10,60), how do you express that in JavaScript?
Make equations of circles both start with x2+y2, subtract one from the other to get equation of its radical axis which is a straight line. Intersection of this radical axis and one of the circles can be found by plugging in for x or y of one circle into the other.
The intersections of two circles determine a line known as the radical line. If three circles mutually intersect in a single point, their point of intersection is the intersection of their pairwise radical lines, known as the radical center.
Description. [ xout , yout ] = circcirc( centerx1 , centery1 , radius1 , centerx2 , centery2 , radius2 ) finds the intersection of two circles with the specified centers and radii, in Cartesian coordinates.
Translated the C function on the site to JavaScript:
function intersection(x0, y0, r0, x1, y1, r1) {
var a, dx, dy, d, h, rx, ry;
var x2, y2;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy*dy) + (dx*dx));
/* Check for solvability. */
if (d > (r0 + r1)) {
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1)) {
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
/* Determine the coordinates of point 2. */
x2 = x0 + (dx * a/d);
y2 = y0 + (dy * a/d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0*r0) - (a*a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h/d);
ry = dx * (h/d);
/* Determine the absolute intersection points. */
var xi = x2 + rx;
var xi_prime = x2 - rx;
var yi = y2 + ry;
var yi_prime = y2 - ry;
return [xi, xi_prime, yi, yi_prime];
}
Based on AutoMonkey's answer I made some adjustments to give some more information in the response and also handle when the circles are the same.
/**
* @description Get information about the intersection points of a circle.
* Adapted from: https://stackoverflow.com/a/12221389/5553768.
* @param {Object} c1 An object describing the first circle.
* @param {float} c1.x The x coordinate of the circle.
* @param {float} c1.y The y coordinate of the circle.
* @param {float} c1.r The radius of the circle.
* @param {Object} c2 An object describing the second circle.
* @param {float} c2.x The x coordinate of the circle.
* @param {float} c2.y The y coordinate of the circle.
* @param {float} c2.r The radius of the circle.
* @returns {Object} Data about the intersections of the circles.
*/
function intersection(c1, c2) {
// Start constructing the response object.
const result = {
intersect_count: 0,
intersect_occurs: true,
one_is_in_other: false,
are_equal: false,
point_1: { x: null, y: null },
point_2: { x: null, y: null },
};
// Get vertical and horizontal distances between circles.
const dx = c2.x - c1.x;
const dy = c2.y - c1.y;
// Calculate the distance between the circle centers as a straight line.
const dist = Math.hypot(dy, dx);
// Check if circles intersect.
if (dist > c1.r + c2.r) {
result.intersect_occurs = false;
}
// Check one circle isn't inside the other.
if (dist < Math.abs(c1.r - c2.r)) {
result.intersect_occurs = false;
result.one_is_in_other = true;
}
// Check if circles are the same.
if (c1.x === c2.x && c1.y === c2.y && c1.r === c2.r) {
result.are_equal = true;
result.are_equal = true;
}
// Find the intersection points
if (result.intersect_occurs) {
// Centroid is the pt where two lines cross. A line between the circle centers
// and a line between the intersection points.
const centroid = (c1.r * c1.r - c2.r * c2.r + dist * dist) / (2.0 * dist);
// Get the coordinates of centroid.
const x2 = c1.x + (dx * centroid) / dist;
const y2 = c1.y + (dy * centroid) / dist;
// Get the distance from centroid to the intersection points.
const h = Math.sqrt(c1.r * c1.r - centroid * centroid);
// Get the x and y dist of the intersection points from centroid.
const rx = -dy * (h / dist);
const ry = dx * (h / dist);
// Get the intersection points.
result.point_1.x = Number((x2 + rx).toFixed(15));
result.point_1.y = Number((y2 + ry).toFixed(15));
result.point_2.x = Number((x2 - rx).toFixed(15));
result.point_2.y = Number((y2 - ry).toFixed(15));
// Add intersection count to results
if (result.are_equal) {
result.intersect_count = null;
} else if (result.point_1.x === result.point_2.x && result.point_1.y === result.point_2.y) {
result.intersect_count = 1;
} else {
result.intersect_count = 2;
}
}
return result;
}
Usage:
intersection(
{x: 1, y: 1, r: 2},
{x: 0, y: -1, r: 1}
)
// Result
result = {
intersect_count: 2,
intersect_occurs: true,
one_is_in_other: false,
are_equal: false,
point_1: { x: 1, y: -1 },
point_2: { x: -0.6, y: -0.2 },
}
Confirmation:
https://www.desmos.com/calculator/cj12hc9jsk
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With