glow_effects/transform/
geometry.rs1use std::f64::consts::PI;
2
3use nalgebra::{Rotation3, Vector3};
4use thiserror::Error;
5
6use crate::util::point::PointContainer;
7
8#[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
38impl<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}