haar_lib/geom/
intersect_circle_segment.rs1use crate::geom::{dist_segment_point::*, *};
4
5#[derive(Clone, Copy, Debug, PartialEq)]
7#[allow(non_camel_case_types)]
8pub enum IntersectCircleSegment {
9 INSIDE,
11 OUTSIDE,
13 TANGENT,
15 ONE_CROSSPOINT,
17 TWO_CROSSPOINTS,
19}
20
21impl IntersectCircleSegment {
22 pub fn inside(self) -> bool {
24 self == Self::INSIDE
25 }
26 pub fn outside(self) -> bool {
28 self == Self::OUTSIDE
29 }
30 pub fn tangent(self) -> bool {
32 self == Self::TANGENT
33 }
34 pub fn one_crosspoint(self) -> bool {
36 self == Self::ONE_CROSSPOINT
37 }
38 pub fn two_crosspoints(self) -> bool {
40 self == Self::TWO_CROSSPOINTS
41 }
42}
43
44pub fn intersect_circle_segment(
46 c: Circle,
47 s: Line,
48 eps: Eps,
49) -> (IntersectCircleSegment, Vec<Vector>) {
50 use self::IntersectCircleSegment::*;
51
52 let Circle {
53 center: c,
54 radius: r,
55 } = c;
56 let d1 = (c - s.from).abs();
57 let d2 = (c - s.to).abs();
58 let v = dist_segment_point(s, c);
59 let m = (r * r - v * v).sqrt();
60 let n = s.normal();
61 let k = s.from + s.diff() * n.cross(c + n - s.from) / n.cross(s.diff());
62
63 if eps.lt(d1, r) && eps.lt(d2, r) {
64 (INSIDE, vec![])
65 } else if eps.eq(v, r) {
66 (TANGENT, vec![k])
67 } else if eps.gt(v, r) {
68 (OUTSIDE, vec![])
69 } else if eps.ge(d1, r) && eps.ge(d2, r) {
70 (TWO_CROSSPOINTS, vec![k - s.unit() * m, k + s.unit() * m])
71 } else {
72 let b = s.unit().dot(s.from - c);
73 let a = (s.from - c).abs_sq() - r * r;
74 let x = (b * b - a).sqrt();
75
76 (
77 ONE_CROSSPOINT,
78 vec![s.from + s.unit() * (if eps.ge(-b, x) { -b - x } else { -b + x })],
79 )
80 }
81}