两圆相交的面积

问题描述 投票:0回答:6

给定两个圆圈:

  • C1 位于 (
    x1
    ,
    y1
    ) 与
    radius1
  • C2 位于 (
    x2
    ,
    y2
    ) 与
    radius2

如何计算它们相交的面积?当然,所有标准数学函数(

sin
cos
等)都可用。

math geometry
6个回答
33
投票

好吧,使用 Wolfram 链接和错误的提示来查看方程 14,我使用我列出的变量和中心之间的距离(可以轻松地从它们导出)导出了以下 Java 解决方案:

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;

26
投票

这是一个 JavaScript 函数,它完全符合 Chris 的要求:

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;
}

但是,如果一个圆完全位于另一个圆内,或者它们根本不接触,则此方法将返回 NaN。在这些条件下不会失败的稍微不同的版本如下:

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;
    }
}

我通过阅读在数学论坛找到的信息编写了这个函数。我发现这比 Wolfram MathWorld 的解释更清楚。


15
投票

您可能想查看此分析解决方案并将公式与您的输入值一起应用。

当半径相等时,这里给出了另一个公式:

Area = r^2*(q - sin(q))  where q = 2*acos(c/2r),
where c = distance between centers and r is the common radius.

2
投票

这里我正在制作基于圆交叉的角色生成工具......你可能会发现它很有用。

动态提供的圆圈:

    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'}
    },

检查完整的小提琴... 小提琴


2
投票

这是一个 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
投票

答案是在java中使用d的中心和测试用例之间的距离“d”。 希望有帮助! 谢谢1

import  java.util.*;
public class FindInDictionary {
public static void main(String[] args){
    System.out.println(areaOfIntersection(5,1,3,5,3,4));


}
static double areaOfIntersection(int x0,int y0,int r0,int x1,int y1,int r1){
    double PI=3.14;
    double d=Math.sqrt(((x1-x0)*(x1-x0))+((y1-y0)*(y1-y0)));//distance between the centers
    if(d>r0+r1)//circle are far away from each other ,ie. no intersection
    {
        return 0;
    }
    if((d<(r0-r1)) &&(r0>r1)){
        return PI*r1*r1;// Smaller circle is completely inside the larger one
    }
    if((d<=r1-r0) && r1>=r0){
        return PI*r0*r0;// Larger circle is completely inside the smaller one
    }
    if(d==r1+r0)
    {
        return 0;//both circle just touches the edge of each other without any overlapping
    }
    double aplha=Math.acos(((r0*r0)+(d*d)-(r1*r1))/(2*r0*d))*2;
    double beta=Math.acos(((r1*r1)+(d*d)-(r0*r0))/(2*r1*d))*2;

    double aLeftSector=(aplha*r0*r0)/2;
    double aLeftTri=0.5*r0*r0*Math.sin(aplha);

    double aRightHalfCircle=aLeftSector-aLeftTri;
    // aRightHalfCircle=(((r0*r0)/2)*(aplha-Math.sin(aplha))); simplify the formula

    double aLeftHalfCircle=(((r1*r1)/2)*(beta-Math.sin(beta)));


    return aRightHalfCircle+aLeftHalfCircle;

}

}

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.