algorithms_edu/algo/
geometry.rs

1pub mod angle_between_vectors;
2pub mod geographical_coordinate;
3pub mod tangent;
4
5use std::ops::Sub;
6
7pub const EPS: f64 = 1e-6;
8
9pub struct Vec2D {
10    x: f64,
11    y: f64,
12}
13
14pub struct Vec3D {
15    x: f64,
16    y: f64,
17    z: f64,
18}
19
20impl Vec2D {
21    pub fn new(x: f64, y: f64) -> Self {
22        Self { x, y }
23    }
24    pub fn magnitude(&self) -> f64 {
25        (self.x * self.x + self.y * self.y).sqrt()
26    }
27    /// Computes the dot product with another 2D vector.
28    pub fn dot(&self, other: &Self) -> f64 {
29        (self.x * other.x) + (self.y * other.y)
30    }
31}
32
33impl Vec3D {
34    pub fn new(x: f64, y: f64, z: f64) -> Self {
35        Self { x, y, z }
36    }
37    pub fn magnitude(&self) -> f64 {
38        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
39    }
40    /// Computes the dot product with another 3D vector.
41    pub fn dot(&self, other: &Self) -> f64 {
42        self.x * other.x + self.y * other.y + self.z * other.z
43    }
44}
45
46#[derive(Copy, Clone)]
47pub struct Point2D {
48    pub x: f64,
49    pub y: f64,
50}
51
52impl Sub<&Self> for Point2D {
53    type Output = Vec2D;
54    fn sub(self, rhs: &Self) -> Self::Output {
55        Vec2D {
56            x: self.x - rhs.x,
57            y: self.y - rhs.y,
58        }
59    }
60}
61
62pub struct Point3D {
63    x: f64,
64    y: f64,
65    z: f64,
66}
67
68impl Point2D {
69    pub fn new(x: f64, y: f64) -> Self {
70        Self { x, y }
71    }
72    pub fn distance_to_point(&self, other: &Self) -> f64 {
73        Vec2D::new(self.x - other.x, self.y - other.y).magnitude()
74    }
75}
76
77impl Point3D {
78    pub fn new(x: f64, y: f64, z: f64) -> Self {
79        Self { x, y, z }
80    }
81    pub fn distance_to_point(&self, other: &Self) -> f64 {
82        Vec3D::new(self.x - other.x, self.y - other.y, self.z - other.z).magnitude()
83    }
84}
85
86pub struct Circle {
87    center: Point2D,
88    radius: f64,
89}
90
91impl Circle {
92    pub fn new(x: f64, y: f64, radius: f64) -> Self {
93        Self {
94            center: Point2D { x, y },
95            radius,
96        }
97    }
98}
99
100use num_traits::Float;
101pub trait SafeArcSinCos: Float {
102    // Due to double rounding precision the value passed into the asin
103    // function may be outside its domain of [-1, +1] which would return
104    // the value NaN which we do not want.
105    fn asin_safe(self) -> Self;
106    // Due to double rounding precision the value passed into the acos
107    // function may be outside its domain of [-1, +1] which would return
108    // the value NaN which we do not want.
109    fn acos_safe(self) -> Self;
110}
111
112impl SafeArcSinCos for f64 {
113    fn asin_safe(self) -> Self {
114        if self <= -1.0 {
115            -std::f64::consts::FRAC_PI_2
116        } else if self >= 1.0 {
117            std::f64::consts::FRAC_PI_2
118        } else {
119            self.asin()
120        }
121    }
122    fn acos_safe(self) -> Self {
123        if self <= -1.0 {
124            std::f64::consts::PI
125        } else if self >= 1.0 {
126            0.
127        } else {
128            self.acos()
129        }
130    }
131}