The intersection area of two circles

概要

中心 \(p_1 = (x_1, y_1)\), 半径 \(r_1\) の円1 と 中心 \(p_2 = (x_2, y_2)\), 半径 \(r_2\) の円2 の共通部分の面積 \(S\) を求める。

ここでは2つの円における扇形の面積から、 点\(p_1, p_2\) と 2つの円の交点 \(c_1, c_2\) から成る四角形の面積を引くことで共通部分の面積を求める。

2つの円の中心同士の距離を \(d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\) とする。

2つの円同士の交点のうちの1点 \(c_1\) に対し、 線分\(p_1 - p_2\) と 線分\(p_1 - c_1\) のなす角を \(\theta_1\), 線分\(p_2 - p_1\) と 線分\(p_2 - c_1\) のなす角を \(\theta_2\) とする。

このとき \(\displaystyle \cos \theta_1 = \frac{r_1^2 - r_2^2 + d^2}{2 r_1 d}\), \(\displaystyle \cos \theta_2 = \frac{r_2^2 - r_1^2 + d^2}{2 r_2 d}\) となる。

扇形の面積は、円1側は \(\displaystyle \frac{1}{2} r_1^2 (2 \theta_1)\), 円2側は \(\displaystyle \frac{1}{2} r_2^2 (2 \theta_2)\) となる。

また、四角形の面積は \(\displaystyle r_1 d \sin \theta_1 = \frac{\sqrt{4 r_1^2 d^2 - (r_1^2 - r_2^2 + d^2)^2}}{2}\) で求められる。

よって、共通部分の面積 \(S\) は \(\displaystyle r_1^2 \theta_1 + r_2^2 \theta_2 - \frac{\sqrt{4 r_1^2 d^2 - (r_1^2 - r_2^2 + d^2)^2}}{2}\) で計算できる。

実装

from math import pi, atan2

def circles_intersection_area(P1, r1, P2, r2):
    x1, y1 = P1; x2, y2 = P2

    dd = (x1 - x2)**2 + (y1 - y2)**2

    if (r1 + r2)**2 <= dd:
        return 0.0

    if dd <= (r1 - r2)**2:
        return pi*min(r1, r2)**2

    p1 = (r1**2 - r2**2 + dd)
    p2 = (r2**2 - r1**2 + dd)

    S1 = r1**2 * atan2((4*dd*r1**2 - p1**2)**.5, p1)
    S2 = r2**2 * atan2((4*dd*r2**2 - p2**2)**.5, p2)
    S0 = (4*dd*r1**2 - p1**2)**.5 / 2

    return S1 + S2 - S0

print(circles_intersection_area((0, 1), 1, (1, 0), 1))
# => "0.5707963267948966"

Verified

  • AOJ: "CGL_7_I: Area of Intersection between Two Circles": source (Python3, 0.03sec)