Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A JavaScript function that returns the x,y points of intersection between two circles?

enter image description here

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?

like image 625
01AutoMonkey Avatar asked Aug 31 '12 17:08

01AutoMonkey


People also ask

How can I find the points at which two circles intersect?

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.

What do you call the intersection of two circles?

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.

How do you find the intersection of two circles in Matlab?

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.


2 Answers

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];
    }
like image 180
01AutoMonkey Avatar answered Sep 20 '22 12:09

01AutoMonkey


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

Plotted

like image 22
Steve Avatar answered Sep 19 '22 12:09

Steve