Area of Intersection between Two Circles

前端 未结 5 1810
时光说笑
时光说笑 2020-12-07 23:57

Given two circles:

  • C1 at (x1, y1) with radius1
  • C2 at (x2, y2) with radius2
相关标签:
5条回答
  • 2020-12-08 00:00

    You might want to check out this analytical solution and apply the formula with your input values.

    Another Formula is given here for when the radii are equal:

    Area = r^2*(q - sin(q))  where q = 2*acos(c/2r),
    where c = distance between centers and r is the common radius.
    
    0 讨论(0)
  • 2020-12-08 00:02

    Here here i was making character generation tool, based on circle intersections... you may find it useful.

    with dynamically provided circles:

        C: {
            C1: {id: 'C1',x:105,y:357,r:100,color:'red'},
            C2: {id: 'C2',x:137,y:281,r:50, color:'lime'},
            C3: {id: 'C3',x:212,y:270,r:75, color:'#00BCD4'}
        },
    

    Check FULL fiddle... FIDDLE

    0 讨论(0)
  • 2020-12-08 00:06

    Okay, using the Wolfram link and Misnomer's cue to look at equation 14, I have derived the following Java solution using the variables I listed and the distance between the centers (which can trivially be derived from them):

    Double r = radius1;
    Double R = radius2;
    Double d = distance;
    if(R < r){
        // swap
        r = radius2;
        R = radius1;
    }
    Double part1 = r*r*Math.acos((d*d + r*r - R*R)/(2*d*r));
    Double part2 = R*R*Math.acos((d*d + R*R - r*r)/(2*d*R));
    Double part3 = 0.5*Math.sqrt((-d+r+R)*(d+r-R)*(d-r+R)*(d+r+R));
    
    Double intersectionArea = part1 + part2 - part3;
    
    0 讨论(0)
  • 2020-12-08 00:15

    Here is an example in Python.

    """Intersection area of two circles"""
    
    import math
    from dataclasses import dataclass
    from typing import Tuple
    
    
    @dataclass
    class Circle:
        x: float
        y: float
        r: float
    
        @property
        def coord(self):
            return self.x, self.y
    
    
    def find_intersection(c1: Circle, c2: Circle) -> float:
        """Finds intersection area of two circles.
    
        Returns intersection area of two circles otherwise 0
        """
    
        d = math.dist(c1.coord, c2.coord)
        rad1sqr = c1.r ** 2
        rad2sqr = c2.r ** 2
    
        if d == 0:
            # the circle centers are the same
            return math.pi * min(c1.r, c2.r) ** 2
    
        angle1 = (rad1sqr + d ** 2 - rad2sqr) / (2 * c1.r * d)
        angle2 = (rad2sqr + d ** 2 - rad1sqr) / (2 * c2.r * d)
    
        # check if the circles are overlapping
        if (-1 <= angle1 < 1) or (-1 <= angle2 < 1):
            theta1 = math.acos(angle1) * 2
            theta2 = math.acos(angle2) * 2
    
            area1 = (0.5 * theta2 * rad2sqr) - (0.5 * rad2sqr * math.sin(theta2))
            area2 = (0.5 * theta1 * rad1sqr) - (0.5 * rad1sqr * math.sin(theta1))
    
            return area1 + area2
        elif angle1 < -1 or angle2 < -1:
            # Smaller circle is completely inside the largest circle.
            # Intersection area will be area of smaller circle
            # return area(c1_r), area(c2_r)
            return math.pi * min(c1.r, c2.r) ** 2
        return 0
    
    
    if __name__ == "__main__":
    
        @dataclass
        class Test:
            data: Tuple[Circle, Circle]
            expected: float
    
        tests = [
            Test((Circle(2, 4, 2), Circle(3, 9, 3)), 0),
            Test((Circle(0, 0, 2), Circle(-1, 1, 2)), 7.0297),
            Test((Circle(1, 3, 2), Circle(1, 3, 2.19)), 12.5664),
            Test((Circle(0, 0, 2), Circle(-1, 0, 2)), 8.6084),
            Test((Circle(4, 3, 2), Circle(2.5, 3.5, 1.4)), 3.7536),
            Test((Circle(3, 3, 3), Circle(2, 2, 1)), 3.1416)
        ]
    
        for test in tests:
            result = find_intersection(*test.data)
            assert math.isclose(result, test.expected, rel_tol=1e-4), f"{test=}, {result=}"
    
        print("PASSED!!!")
    
    
    0 讨论(0)
  • 2020-12-08 00:20

    Here is a JavaScript function that does exactly what Chris was after:

    function areaOfIntersection(x0, y0, r0, x1, y1, r1)
    {
        var rr0 = r0 * r0;
        var rr1 = r1 * r1;
        var d = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
        var phi = (Math.acos((rr0 + (d * d) - rr1) / (2 * r0 * d))) * 2;
        var theta = (Math.acos((rr1 + (d * d) - rr0) / (2 * r1 * d))) * 2;
        var area1 = 0.5 * theta * rr1 - 0.5 * rr1 * Math.sin(theta);
        var area2 = 0.5 * phi * rr0 - 0.5 * rr0 * Math.sin(phi);
        return area1 + area2;
    }
    

    However, this method will return NaN if one circle is completely inside the other, or they are not touching at all. A slightly different version that doesn't fail in these conditions is as follows:

    function areaOfIntersection(x0, y0, r0, x1, y1, r1)
    {
        var rr0 = r0 * r0;
        var rr1 = r1 * r1;
        var d = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
    
        // Circles do not overlap
        if (d > r1 + r0)
        {
        return 0;
        }
    
        // Circle1 is completely inside circle0
        else if (d <= Math.abs(r0 - r1) && r0 >= r1)
        {
        // Return area of circle1
        return Math.PI * rr1;
        }
    
        // Circle0 is completely inside circle1
        else if (d <= Math.abs(r0 - r1) && r0 < r1)
        {
        // Return area of circle0
        return Math.PI * rr0;
        }
    
        // Circles partially overlap
        else
        {
        var phi = (Math.acos((rr0 + (d * d) - rr1) / (2 * r0 * d))) * 2;
        var theta = (Math.acos((rr1 + (d * d) - rr0) / (2 * r1 * d))) * 2;
        var area1 = 0.5 * theta * rr1 - 0.5 * rr1 * Math.sin(theta);
        var area2 = 0.5 * phi * rr0 - 0.5 * rr0 * Math.sin(phi);
    
        // Return area of intersection
        return area1 + area2;
        }
    }
    

    I wrote this function by reading the information found at the Math Forum. I found this clearer than the Wolfram MathWorld explanation.

    0 讨论(0)
提交回复
热议问题