haar_lib/geom/
common_tangent_circles.rs

1//! 2つの円の共通接線
2
3use crate::geom::*;
4
5/// 2つの円の共通接線を求める
6pub fn common_tangent_circles(a: Circle, b: Circle, eps: Eps) -> Vec<Vector> {
7    let cc = b.center - a.center;
8    let d = cc.abs();
9    let n = cc.unit();
10    let r_diff = a.radius - b.radius;
11    let r_sum = a.radius + b.radius;
12
13    if eps.eq(r_sum, d) {
14        let t = cc.normal() * (cc.abs_sq() - r_diff * r_diff).sqrt();
15        vec![
16            a.center + (cc * r_diff + t) * a.radius / cc.abs_sq(),
17            a.center + (cc * r_diff - t) * a.radius / cc.abs_sq(),
18            a.center + n * a.radius,
19        ]
20    } else if eps.lt(r_sum, d) {
21        let t_diff = cc.normal() * (cc.abs_sq() - r_diff * r_diff).sqrt();
22        let t_sum = cc.normal() * (cc.abs_sq() - r_sum * r_sum).sqrt();
23
24        vec![
25            a.center + (cc * r_diff + t_diff) * a.radius / cc.abs_sq(),
26            a.center + (cc * r_diff - t_diff) * a.radius / cc.abs_sq(),
27            a.center + (cc * r_sum + t_sum) * a.radius / cc.abs_sq(),
28            a.center + (cc * r_sum - t_sum) * a.radius / cc.abs_sq(),
29        ]
30    } else if eps.gt(r_sum, d) && eps.gt(d, (a.radius - b.radius).abs()) {
31        let t = cc.normal() * (cc.abs_sq() - r_diff * r_diff).sqrt();
32        vec![
33            a.center + (cc * r_diff + t) * a.radius / cc.abs_sq(),
34            a.center + (cc * r_diff - t) * a.radius / cc.abs_sq(),
35        ]
36    } else if eps.eq((a.radius - b.radius).abs(), d) {
37        vec![if eps.gt(a.radius, b.radius) {
38            a.center + n * a.radius
39        } else {
40            b.center - n * b.radius
41        }]
42    } else {
43        vec![]
44    }
45}