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