Repository: ManevilleF/hexx
Pull request #30 (2023-02-10 16:43:19)

Improved rotation
Improves `Hex` rotation methods:

* (**BREAKING**) renamed `Hex::rotate_left` to `Hex::left` and made it `const`
* (**BREAKING**) renamed `Hex::rotate_right` to `Hex::right` and made it `const`
* (**BREAKING**) renamed `Hex::rotate_left_around` to `Hex::left_around` and made it `const`
* (**BREAKING**) renamed `Hex::rotate_right_around` to `Hex::right_around` and made it `const`
* Added `Hex::rotate_left` to rotate counter clockwise by a custom amount
* Added `Hex::rotate_left_around` to rotate counter clockwise by a custom amount and center
* Added `Hex::rotate_right` to rotate clockwise by a custom amount
* Added `Hex::rotate_right_around` to rotate clockwise by a custom amount and center


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cf7a2b..4267e1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,14 @@
 * Added `rounding_div` method to `Hex` to perform floating point division rounded to the closest coordinate
 * Added `rounding_mul` method to `Hex` to perform floating point multiplication rounded to the closest coordinate
 * Added `cached_rings` and `cached_custom_rings` to `Hex` for rings pre-computation
+* (**BREAKING**) renamed `Hex::rotate_left` to `Hex::left` and made it `const`
+* (**BREAKING**) renamed `Hex::rotate_right` to `Hex::right` and made it `const`
+* (**BREAKING**) renamed `Hex::rotate_left_around` to `Hex::left_around` and made it `const`
+* (**BREAKING**) renamed `Hex::rotate_right_around` to `Hex::right_around` and made it `const`
+* Added `Hex::rotate_left` to rotate counter clockwise by a custom amount
+* Added `Hex::rotate_left_around` to rotate counter clockwise by a custom amount and center
+* Added `Hex::rotate_right` to rotate clockwise by a custom amount
+* Added `Hex::rotate_right_around` to rotate clockwise by a custom amount and center
 
 ### Iterator extensions
 
diff --git a/src/hex/mod.rs b/src/hex/mod.rs
index 330215b..a7bb7d0 100644
--- a/src/hex/mod.rs
+++ b/src/hex/mod.rs
@@ -372,29 +372,71 @@ impl Hex {
     #[inline]
     #[must_use]
     /// Rotates `self` around [`Hex::ZERO`] counter clockwise (by -60 degrees)
-    pub const fn rotate_left(self) -> Self {
+    pub const fn left(self) -> Self {
         Self::new(-self.z(), -self.x)
     }
 
     #[inline]
     #[must_use]
-    /// Rotates `self` around `center`  counter clockwise (by -60 degrees)
-    pub fn rotate_left_around(self, center: Self) -> Self {
-        (self - center).rotate_left() + center
+    /// Rotates `self` around `center` counter clockwise (by -60 degrees)
+    pub const fn left_around(self, center: Self) -> Self {
+        self.const_sub(center).left().const_add(center)
+    }
+
+    #[inline]
+    #[must_use]
+    /// Rotates `self` around [`Hex::ZERO`] counter clockwise by `m` (by `-60 * m` degrees)
+    pub const fn rotate_left(self, m: u32) -> Self {
+        match m % 6 {
+            1 => self.left(),
+            2 => self.left().left(),
+            3 => self.const_neg(),
+            4 => self.right().right(),
+            5 => self.right(),
+            _ => self,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    /// Rotates `self` around `center` counter clockwise by `m` (by `-60 * m` degrees)
+    pub const fn rotate_left_around(self, center: Self, m: u32) -> Self {
+        self.const_sub(center).rotate_left(m).const_add(center)
     }
 
     #[inline]
     #[must_use]
     /// Rotates `self` around [`Hex::ZERO`] clockwise (by 60 degrees)
-    pub const fn rotate_right(self) -> Self {
+    pub const fn right(self) -> Self {
         Self::new(-self.y, -self.z())
     }
 
     #[inline]
     #[must_use]
     /// Rotates `self` around `center` clockwise (by 60 degrees)
-    pub fn rotate_right_around(self, center: Self) -> Self {
-        (self - center).rotate_right() + center
+    pub const fn right_around(self, center: Self) -> Self {
+        self.const_sub(center).right().const_add(center)
+    }
+
+    #[inline]
+    #[must_use]
+    /// Rotates `self` around [`Hex::ZERO`] clockwise by `m` (by `60 * m` degrees)
+    pub const fn rotate_right(self, m: u32) -> Self {
+        match m % 6 {
+            1 => self.right(),
+            2 => self.right().right(),
+            3 => self.const_neg(),
+            4 => self.left().left(),
+            5 => self.left(),
+            _ => self,
+        }
+    }
+
+    #[inline]
+    #[must_use]
+    /// Rotates `self` around `center` clockwise by `m` (by `60 * m` degrees)
+    pub const fn rotate_right_around(self, center: Self, m: u32) -> Self {
+        self.const_sub(center).rotate_right(m).const_add(center)
     }
 
     #[inline]
@@ -681,7 +723,7 @@ impl Hex {
     pub const fn wraparound_mirrors(radius: u32) -> [Self; 6] {
         let radius = radius as i32;
         let mirror = Self::new(2 * radius + 1, -radius);
-        let [center, left, right] = [mirror, mirror.rotate_left(), mirror.rotate_right()];
+        let [center, left, right] = [mirror, mirror.left(), mirror.right()];
         [
             left,
             center,


Test patch:
diff --git a/src/hex/tests.rs b/src/hex/tests.rs
index 0a98260..4bd1ce8 100644
--- a/src/hex/tests.rs
+++ b/src/hex/tests.rs
@@ -184,35 +184,51 @@ fn distance_to() {
 #[test]
 fn rotate_right() {
     let hex = Hex::new(5, 0);
-    let new = hex.rotate_right();
+    let new = hex.right();
     assert_eq!(new, Hex::new(0, 5));
-    let new = new.rotate_right();
+    assert_eq!(hex.rotate_right(1), new);
+    let new = new.right();
     assert_eq!(new, Hex::new(-5, 5));
-    let new = new.rotate_right();
+    assert_eq!(hex.rotate_right(2), new);
+    let new = new.right();
     assert_eq!(new, Hex::new(-5, 0));
-    let new = new.rotate_right();
+    assert_eq!(hex.rotate_right(3), new);
+    let new = new.right();
     assert_eq!(new, Hex::new(0, -5));
-    let new = new.rotate_right();
+    assert_eq!(hex.rotate_right(4), new);
+    let new = new.right();
     assert_eq!(new, Hex::new(5, -5));
-    let new = new.rotate_right();
+    assert_eq!(hex.rotate_right(5), new);
+    let new = new.right();
     assert_eq!(new, hex);
+    assert_eq!(hex.rotate_right(6), new);
+    assert_eq!(hex.rotate_right(7), hex.rotate_right(1));
+    assert_eq!(hex.rotate_right(10), hex.rotate_right(4));
 }
 
 #[test]
 fn rotate_left() {
     let hex = Hex::new(5, 0);
-    let new = hex.rotate_left();
+    let new = hex.left();
     assert_eq!(new, Hex::new(5, -5));
-    let new = new.rotate_left();
+    assert_eq!(hex.rotate_left(1), new);
+    let new = new.left();
     assert_eq!(new, Hex::new(0, -5));
-    let new = new.rotate_left();
+    assert_eq!(hex.rotate_left(2), new);
+    let new = new.left();
     assert_eq!(new, Hex::new(-5, 0));
-    let new = new.rotate_left();
+    assert_eq!(hex.rotate_left(3), new);
+    let new = new.left();
     assert_eq!(new, Hex::new(-5, 5));
-    let new = new.rotate_left();
+    assert_eq!(hex.rotate_left(4), new);
+    let new = new.left();
     assert_eq!(new, Hex::new(0, 5));
-    let new = new.rotate_left();
+    assert_eq!(hex.rotate_left(5), new);
+    let new = new.left();
     assert_eq!(new, hex);
+    assert_eq!(hex.rotate_left(6), new);
+    assert_eq!(hex.rotate_left(7), hex.rotate_left(1));
+    assert_eq!(hex.rotate_left(10), hex.rotate_left(4));
 }
 
 #[test]