diff -r 8f093b1b18bc -r e82de0410da5 rust/landgen/src/wavefront_collapse/transform.rs --- /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() + ); + } +}