rust/landgen/src/wavefront_collapse/transform.rs
branchtransitional_engine
changeset 15916 e82de0410da5
child 15918 9bd828451d77
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/landgen/src/wavefront_collapse/transform.rs	Fri Feb 03 14:44:33 2023 +0100
@@ -0,0 +1,213 @@
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum SymmetryTransform {
+    Id,
+    Flip,
+    Mirror,
+    FlipMirror,
+}
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum RotationTransform {
+    Rotate0(SymmetryTransform),
+    Rotate90(SymmetryTransform),
+    Rotate180(SymmetryTransform),
+    Rotate270(SymmetryTransform),
+}
+
+impl Default for RotationTransform {
+    fn default() -> Self {
+        RotationTransform::Rotate0(SymmetryTransform::Id)
+    }
+}
+
+impl SymmetryTransform {
+    pub fn mirror(&self) -> Self {
+        use SymmetryTransform::*;
+        match self {
+            Id => Mirror,
+            Flip => FlipMirror,
+            Mirror => Id,
+            FlipMirror => Flip,
+        }
+    }
+
+    pub fn flip(&self) -> Self {
+        use SymmetryTransform::*;
+        match self {
+            Id => Flip,
+            Flip => Id,
+            Mirror => FlipMirror,
+            FlipMirror => Mirror,
+        }
+    }
+}
+
+impl RotationTransform {
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    pub fn mirror(self) -> RotationTransform {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate0(s.mirror()),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate270(s.mirror()).simplified(),
+            RotationTransform::Rotate180(s) => {
+                RotationTransform::Rotate180(s.mirror()).simplified()
+            }
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate90(s.mirror()),
+        }
+    }
+
+    pub fn flip(self) -> RotationTransform {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate0(s.flip()),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate90(s.flip()),
+            RotationTransform::Rotate180(s) => RotationTransform::Rotate180(s.flip()).simplified(),
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate270(s.flip()).simplified(),
+        }
+    }
+
+    pub fn rotate90(self) -> RotationTransform {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate90(s),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate180(s).simplified(),
+            RotationTransform::Rotate180(s) => RotationTransform::Rotate270(s).simplified(),
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate0(s),
+        }
+    }
+
+    pub fn rotate180(self) -> RotationTransform {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate180(s).simplified(),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate270(s).simplified(),
+            RotationTransform::Rotate180(s) => RotationTransform::Rotate0(s),
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate90(s),
+        }
+    }
+
+    pub fn rotate270(self) -> RotationTransform {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate270(s).simplified(),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate0(s),
+            RotationTransform::Rotate180(s) => RotationTransform::Rotate90(s),
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate180(s).simplified(),
+        }
+    }
+
+    fn simplified(self) -> Self {
+        match self {
+            RotationTransform::Rotate0(s) => RotationTransform::Rotate0(s),
+            RotationTransform::Rotate90(s) => RotationTransform::Rotate90(s),
+            RotationTransform::Rotate180(s) => RotationTransform::Rotate0(s.flip().mirror()),
+            RotationTransform::Rotate270(s) => RotationTransform::Rotate90(s.flip().mirror()),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{RotationTransform::*, SymmetryTransform::*, *};
+
+    // I totally wrote all of this myself and didn't use ChatGPT
+    #[test]
+    fn test_default() {
+        let rt = RotationTransform::new();
+        assert_eq!(rt, Rotate0(Id));
+    }
+
+    #[test]
+    fn test_mirror() {
+        let rt = Rotate90(Flip);
+        let mirrored = rt.mirror();
+        assert_eq!(mirrored, Rotate90(Id));
+    }
+
+    #[test]
+    fn test_flip() {
+        let rt = Rotate180(Mirror);
+        let flipped = rt.flip();
+        assert_eq!(flipped, Rotate0(Id));
+    }
+
+    #[test]
+    fn test_rotate90() {
+        let rt = Rotate0(Id);
+        let rotated = rt.rotate90();
+        assert_eq!(rotated, Rotate90(Id));
+    }
+
+    #[test]
+    fn test_rotate180() {
+        let rt = Rotate90(Mirror);
+        let rotated = rt.rotate180();
+        assert_eq!(rotated, Rotate90(Flip));
+    }
+
+    #[test]
+    fn test_rotate270() {
+        let rt = Rotate180(Flip);
+        let rotated = rt.rotate270();
+        assert_eq!(rotated, Rotate90(Flip));
+    }
+
+    #[test]
+    fn test_simplified() {
+        let rt = Rotate180(Id);
+        let simplified = rt.simplified();
+        assert_eq!(simplified, Rotate0(FlipMirror));
+    }
+
+    #[test]
+    fn test_rotation_chain() {
+        assert_eq!(
+            RotationTransform::default(),
+            RotationTransform::default()
+                .rotate90()
+                .rotate90()
+                .rotate90()
+                .rotate90()
+        );
+        assert_eq!(
+            RotationTransform::default().rotate90(),
+            RotationTransform::default()
+                .rotate180()
+                .rotate90()
+                .rotate180()
+        );
+        assert_eq!(
+            RotationTransform::default().rotate180(),
+            RotationTransform::default()
+                .rotate180()
+                .rotate270()
+                .rotate90()
+        );
+    }
+
+    #[test]
+    fn test_combinations_chain() {
+        assert_eq!(
+            RotationTransform::default(),
+            RotationTransform::default()
+                .flip()
+                .rotate180()
+                .flip()
+                .rotate180()
+        );
+        assert_eq!(
+            RotationTransform::default(),
+            RotationTransform::default()
+                .mirror()
+                .rotate180()
+                .mirror()
+                .rotate180()
+        );
+        assert_eq!(
+            RotationTransform::default(),
+            RotationTransform::default()
+                .rotate90()
+                .flip()
+                .rotate90()
+                .mirror()
+        );
+    }
+}