Skip to main content

glow_effects/transform/
geometry.rs

1use std::f64::consts::PI;
2
3use nalgebra::{Rotation3, Vector3};
4use thiserror::Error;
5
6use crate::util::point::PointContainer;
7
8// Ensure this is correctly defined as shown above
9
10#[derive(Debug, Clone, Copy)]
11pub enum Transformation {
12    FlipAcrossXAxis,
13    FlipAcrossYAxis,
14    FlipAcrossZAxis,
15    RotateAroundAxis { axis: Axis, angle_degrees: f64 },
16}
17
18#[derive(Debug, Clone, Copy)]
19pub enum Axis {
20    X,
21    Y,
22    Z,
23}
24
25#[derive(Error, Debug)]
26pub enum TransformationError {
27    #[error("Invalid rotation axis or angle")]
28    InvalidRotation,
29}
30
31pub trait Transform<T: PointContainer>: Sized {
32    fn apply_transformation(
33        points: Self,
34        transformation: Transformation,
35    ) -> Result<Self, TransformationError>;
36}
37
38// implement the Transformer trait for Vec<T>
39impl<T: PointContainer> Transform<T> for Vec<T> {
40    fn apply_transformation(
41        points: Vec<T>,
42        transformation: Transformation,
43    ) -> Result<Vec<T>, TransformationError> {
44        apply_transformation_helper(points, transformation)
45    }
46}
47
48fn apply_transformation_helper<T: PointContainer>(
49    points: Vec<T>,
50    transformation: Transformation,
51) -> Result<Vec<T>, TransformationError> {
52    let transform_matrix = match transformation {
53        Transformation::FlipAcrossXAxis => Rotation3::from_axis_angle(&Vector3::x_axis(), PI),
54        Transformation::FlipAcrossYAxis => Rotation3::from_axis_angle(&Vector3::y_axis(), PI),
55        Transformation::FlipAcrossZAxis => Rotation3::from_axis_angle(&Vector3::z_axis(), PI),
56        Transformation::RotateAroundAxis {
57            axis,
58            angle_degrees,
59        } => {
60            let rad = angle_degrees.to_radians();
61            match axis {
62                Axis::X => Rotation3::from_axis_angle(&Vector3::x_axis(), rad),
63                Axis::Y => Rotation3::from_axis_angle(&Vector3::y_axis(), rad),
64                Axis::Z => Rotation3::from_axis_angle(&Vector3::z_axis(), rad),
65            }
66        }
67    };
68
69    let transformed_points: Vec<T> = points
70        .iter()
71        .map(|point| {
72            let original_point = point.get_nalgebra_point();
73            let new_point = transform_matrix * original_point;
74            point.copy_with_new_coordinates(new_point.x, new_point.y, new_point.z)
75        })
76        .collect();
77
78    Ok(transformed_points)
79}