rscad_csg_bsp/
rotation.rs1use crate::Number;
4use nalgebra::Matrix3;
5
6pub fn euler_rotation_matrix<T: Number>(angles_deg: nalgebra::Vector3<T>) -> Matrix3<T> {
22 use num_traits::Float;
23 let xr = Float::to_radians(angles_deg[0]);
24 let yr = Float::to_radians(angles_deg[1]);
25 let zr = Float::to_radians(angles_deg[2]);
26 let (sx, cx) = (Float::sin(xr), Float::cos(xr));
27 let (sy, cy) = (Float::sin(yr), Float::cos(yr));
28 let (sz, cz) = (Float::sin(zr), Float::cos(zr));
29
30 Matrix3::new(
32 cy * cz,
33 cz * sx * sy - cx * sz,
34 sx * sz + cx * cz * sy,
35 cy * sz,
36 cx * cz + sx * sy * sz,
37 cx * sy * sz - cz * sx,
38 -sy,
39 cy * sx,
40 cx * cy,
41 )
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use nalgebra::Vector3;
48
49 fn approx_eq(a: &Matrix3<f64>, b: &Matrix3<f64>, eps: f64) -> bool {
50 (a - b).iter().all(|x| x.abs() < eps)
51 }
52
53 #[test]
54 fn identity_for_zero_angles() {
55 let m = euler_rotation_matrix(Vector3::new(0.0_f64, 0.0, 0.0));
56 assert!(approx_eq(&m, &Matrix3::identity(), 1e-12));
57 }
58
59 #[test]
60 fn rotate_90_around_z() {
61 let m = euler_rotation_matrix(Vector3::new(0.0_f64, 0.0, 90.0));
62 let v = m * Vector3::new(1.0, 0.0, 0.0);
63 assert!((v[0]).abs() < 1e-12);
64 assert!((v[1] - 1.0).abs() < 1e-12);
65 assert!((v[2]).abs() < 1e-12);
66 }
67
68 #[test]
69 fn rotate_90_around_x() {
70 let m = euler_rotation_matrix(Vector3::new(90.0_f64, 0.0, 0.0));
71 let v = m * Vector3::new(0.0, 1.0, 0.0);
72 assert!((v[0]).abs() < 1e-12);
73 assert!((v[1]).abs() < 1e-12);
74 assert!((v[2] - 1.0).abs() < 1e-12);
75 }
76
77 #[test]
78 fn rotate_90_around_y() {
79 let m = euler_rotation_matrix(Vector3::new(0.0_f64, 90.0, 0.0));
80 let v = m * Vector3::new(1.0, 0.0, 0.0);
81 assert!((v[0]).abs() < 1e-12);
82 assert!((v[1]).abs() < 1e-12);
83 assert!((v[2] + 1.0).abs() < 1e-12);
84 }
85
86 #[test]
87 fn composed_rotation_is_orthogonal() {
88 let m = euler_rotation_matrix(Vector3::new(30.0_f64, 45.0, 60.0));
89 let mmt = m * m.transpose();
90 assert!(approx_eq(&mmt, &Matrix3::identity(), 1e-12));
91 }
92}