1use crate::{Vect, Rect, Ray, IntersectionPoints};
2use crate::math::Intersection;
3
4#[derive(Copy, Clone, Debug)]
7pub struct Circ {
8 pub c: Vect,
9 pub r: f32,
10}
11
12impl Circ {
13 #[inline]
14 pub fn new(x: f32, y: f32, r:f32) -> Self {
15 Self { r, c: Vect { x, y } }
16 }
17
18 #[inline]
20 pub fn contains(&self, pos: Vect) -> bool {
21 self.c.dist(pos) <= self.r
22 }
23
24 #[inline]
28 pub fn prj_x(&self, x: f32) -> f32 {
29 (self.r * self.r - (x - self.c.x).powi(2)).sqrt() - self.c.y
30 }
31
32 #[inline]
34 pub fn prj_y(&self, y: f32) -> f32 {
35 (self.r * self.r - (y - self.c.y).powi(2)).sqrt() - self.c.y
36 }
37
38 #[inline]
40 pub fn formula_x(&self, x: f32) -> (f32, f32) {
41 (2.0 * self.c.y, self.c.y * self.c.y - self.r * self.r + (x - self.c.x).powi(2))
42 }
43
44 #[inline]
46 pub fn formula_y(&self, y: f32) -> (f32, f32) {
47 (2.0 * self.c.x, self.c.x * self.c.x - self.r * self.r + (y - self.c.y).powi(2))
48 }
49
50 #[inline]
52 pub fn precise_prj(&self, arg: f32, formula: fn(&Self, f32) -> (f32, f32)) -> [Option<f32>; 2] {
53 let (b, c) = formula(self, arg);
54
55 let mut dis = b * b - 4.0 * c;
56 if dis < 0.0 {
57 return [None, None];
58 } else if dis == 0.0 {
59 return [Some(-b/2.0), None]
60 }
61
62 dis = dis.sqrt();
63 [Some((-b - dis)/2.0), Some((-b + dis)/2.0)]
64 }
65
66 #[inline]
69 pub fn precise_prj_x(&self, x: f32) -> [Option<f32>; 2] {
70 self.precise_prj(x, Self::formula_x)
71 }
72
73 #[inline]
75 pub fn precise_prj_y(&self, y: f32) -> [Option<f32>; 2] {
76 self.precise_prj(y, Self::formula_y)
77 }
78}
79
80impl Intersection<Circ> for Circ {
81 #[inline]
82 fn intersects(&self, o: &Circ) -> bool {
83 self.c.dist(o.c) < self.r + o.r
84 }
85}
86
87impl Intersection<Rect> for Circ {
88 #[inline]
89 fn intersects(&self, o: &Rect) -> bool {
90 o.intersects(self)
91 }
92}
93
94impl Intersection<Ray> for Circ {
95 #[inline]
96 fn intersects(&self, o: &Ray) -> bool {
97 o.intersects(self)
98 }
99}
100
101impl IntersectionPoints<Ray> for Circ {
102 #[inline]
103 fn intersects_points(&self, o: &Ray) -> [Option<Vect>; 2] {
104 o.intersects_points(self)
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::Circ;
111 use crate::Vect;
112 #[test]
113 fn prj_test() {
114 let base = circ!(0, 0; 10);
115 assert_eq!(0.0 ,base.prj_y(10.0));
116 assert_eq!(0.0 ,base.prj_x(10.0));
117 assert_eq!(10.0 ,base.prj_y(0.0));
118 assert_eq!(10.0 ,base.prj_x(0.0));
119 }
120
121 #[test]
122 fn precise_pre_test() {
123 let base = circ!(0, 0; 10);
124 assert_eq!([Some(0.0), None] ,base.precise_prj_y(10.0));
125 assert_eq!([Some(0.0), None] ,base.precise_prj_x(10.0));
126 assert_eq!([Some(-8.0), Some(8.0)] ,base.precise_prj_y(6.0));
127 assert_eq!([Some(-8.0), Some(8.0)] ,base.precise_prj_x(6.0));
128 }
129}