Skip to main content

cmtool_core/coordinates/
mod.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3mod points;
4mod vec3;
5pub use points::*;
6pub use vec3::*;
7
8pub const NUMBER_OF_AXIS: usize = 3;
9pub type Coords3 = [f64; NUMBER_OF_AXIS];
10
11pub fn orthonormal_basis(normal: &CartesianVec3) -> (CartesianVec3, CartesianVec3) {
12    let n = normal.normalized();
13    let temp = if n.0[0].abs() < 0.9 {
14        CartesianVec3([1.0, 0.0, 0.0])
15    } else {
16        CartesianVec3([0.0, 1.0, 0.0])
17    };
18
19    let u = n.cross(&temp).normalized();
20    let v = n.cross(&u).normalized();
21    (u, v)
22}
23
24pub struct Plane {
25    pub normal: CartesianVec3,
26    pub point: CartesianCoordinates,
27}
28
29pub struct BoundedPlane {
30    pub normal: CartesianVec3,
31    pub origin: CartesianCoordinates,
32    pub extent_u: [f64; 2],
33    pub extent_v: [f64; 2],
34    pub axis: usize, // 0 = r, 1 = theta, 2 = z
35}
36
37impl BoundedPlane {
38    pub fn is_point_inside(&self, CartesianCoordinates(point): CartesianCoordinates) -> bool {
39        let r = (point[0].powi(2) + point[1].powi(2)).sqrt();
40        let theta_raw = point[1].atan2(point[0]);
41        let z = point[2];
42        const TOL: f64 = 1e-10;
43
44        let (u, v) = match self.axis {
45            0 => {
46                let pi2 = 2.0 * std::f64::consts::PI;
47                let mid = 0.5 * (self.extent_u[0] + self.extent_u[1]);
48                let mut theta = theta_raw;
49                while theta - mid > std::f64::consts::PI {
50                    theta -= pi2;
51                }
52                while mid - theta > std::f64::consts::PI {
53                    theta += pi2;
54                }
55                (theta, z)
56            }
57            1 => (r, z),
58            2 => {
59                let pi2 = 2.0 * std::f64::consts::PI;
60                let mid = 0.5 * (self.extent_v[0] + self.extent_v[1]);
61                let mut theta = theta_raw;
62                while theta - mid > std::f64::consts::PI {
63                    theta -= pi2;
64                }
65                while mid - theta > std::f64::consts::PI {
66                    theta += pi2;
67                }
68                (r, theta)
69            }
70            _ => unreachable!(),
71        };
72
73        (u >= self.extent_u[0] - TOL && u <= self.extent_u[1] + TOL)
74            && (v >= self.extent_v[0] - TOL && v <= self.extent_v[1] + TOL)
75    }
76}
77
78impl From<BoundedPlane> for Plane {
79    fn from(value: BoundedPlane) -> Self {
80        Self {
81            normal: value.normal,
82            point: value.origin,
83        }
84    }
85}
86
87pub fn get_normal(axis: usize, negative: bool) -> Coords3 {
88    let sign = if negative { -1. } else { 1. };
89    match axis {
90        0 => [sign, 0.0, 0.0],
91        1 => [0.0, sign, 0.0],
92        2 => [0.0, 0.0, sign],
93        _ => unreachable!("Axis must be 0, 1, or 2"),
94    }
95}
96
97// pub trait AsCoords3 {
98//     fn as_coords(&self) -> &Coords3;
99// }
100
101// impl AsCoords3 for CylindricalCoordinates {
102//     fn as_coords(&self) -> &Coords3 {
103//         &self.0
104//     }
105// }
106
107// impl AsCoords3 for CartesianCoordinates {
108//     fn as_coords(&self) -> &Coords3 {
109//         &self.0
110//     }
111// }
112
113// impl AsCoords3 for Coords3 {
114//     fn as_coords(&self) -> &Coords3 {
115//         self
116//     }
117// }