1mod point;
2
3use std::marker::PhantomData;
4
5use num::{cast, Float};
6
7pub use self::point::Point;
8
9#[derive(Default)]
11pub struct Math<T>(PhantomData<T>);
12
13impl<T: Float> Math<T> {
14 pub fn circumcircle(p1: Point<T>, p2: Point<T>, p3: Point<T>) -> (Point<T>, T) {
16 let (x1, y1) = (p1.x, p1.y);
17 let (x2, y2) = (p2.x, p2.y);
18 let (x3, y3) = (p3.x, p3.y);
19
20 let two = num::cast::<_, T>(2.0).unwrap();
21 let d = two.mul_add(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2), T::zero());
22 let ux = ((x1 * x1 + y1 * y1) * (y2 - y3)
23 + (x2 * x2 + y2 * y2) * (y3 - y1)
24 + (x3 * x3 + y3 * y3) * (y1 - y2))
25 / d;
26 let uy = ((x1 * x1 + y1 * y1) * (x3 - x2)
27 + (x2 * x2 + y2 * y2) * (x1 - x3)
28 + (x3 * x3 + y3 * y3) * (x2 - x1))
29 / d;
30
31 let center = Point::new(ux, uy);
32 (center, center.distance(p1))
33 }
34
35 #[allow(clippy::many_single_char_names)]
37 pub fn point_on_line(a: Point<T>, b: Point<T>, len: T) -> Point<T> {
38 let full = a.distance(b);
39 let n = full - len;
40 let x = (n * a.x + len * b.x) / full;
41 let y = (n * a.y + len * b.y) / full;
42 Point::new(x, y)
43 }
44
45 pub fn is_line(a: Point<T>, b: Point<T>, c: Point<T>) -> bool {
47 ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)).abs() < cast(0.001).unwrap()
48 }
49
50 pub fn catmull_find_point(
55 val1: Point<T>,
56 val2: Point<T>,
57 val3: Point<T>,
58 val4: Point<T>,
59 t: T,
60 ) -> Point<T> {
61 let t2 = t * t;
62 let t3 = t * t2;
63
64 let half = num::cast::<_, T>(0.5).expect("can cast correctly.");
65 let two = num::cast::<_, T>(2.0).expect("can cast correctly.");
66 let three = num::cast::<_, T>(3.0).expect("can cast correctly.");
67 let four = num::cast::<_, T>(4.0).expect("can cast correctly.");
68 let five = num::cast::<_, T>(5.0).expect("can cast correctly.");
69
70 return (val2 * (-val1 + val3) * two * t
71 + (val1 * two - val2 * five + val3 * four - val4) * t2
72 + (-val1 + val2 * three - val3 * three + val4) * t3)
73 * half;
74 }
75}