haar_lib/geom/
intersect_circle_line.rs

1//! 円と直線の位置関係
2
3use crate::geom::{dist_line_point::*, *};
4
5/// 円と直線の位置関係
6#[derive(Clone, Copy, Debug, PartialEq)]
7#[allow(non_camel_case_types)]
8pub enum IntersectCircleLine {
9    /// 直線が円の外側にある
10    OUTSIDE,
11    /// 直線が円に接している
12    TANGENT,
13    /// 直線と円が交わっている
14    CROSSED,
15}
16
17impl IntersectCircleLine {
18    /// `OUTSIDE`かを判定
19    pub fn outside(self) -> bool {
20        self == Self::OUTSIDE
21    }
22    /// `TANGENT`かを判定
23    pub fn tangent(self) -> bool {
24        self == Self::TANGENT
25    }
26    /// `CROSSED`かを判定
27    pub fn crossed(self) -> bool {
28        self == Self::CROSSED
29    }
30}
31
32/// 円と直線の位置関係と交点を求める
33pub fn intersect_circle_line(c: Circle, l: Line, eps: Eps) -> (IntersectCircleLine, Vec<Vector>) {
34    use self::IntersectCircleLine::*;
35
36    let d = dist_line_point(l, c.center);
37
38    if eps.gt(d, c.radius) {
39        return (OUTSIDE, vec![]);
40    }
41
42    let n = l.normal();
43    let b = l.from + l.diff() * n.cross(c.center + n - l.from) / n.cross(l.diff());
44
45    if eps.eq(d, c.radius) {
46        (TANGENT, vec![b])
47    } else {
48        let a = (c.radius * c.radius - d * d).sqrt();
49        (CROSSED, vec![b + l.unit() * a, b - l.unit() * a])
50    }
51}