Repository: bitshifter/glam-rs
Pull request #432 (2023-09-23 16:33:14)

Add `to_angle` method to 2D vectors


Patch:
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index 63363f1..65d9384 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -1487,6 +1487,14 @@ impl {{ self_t }} {
         }
     }
 
+    /// Returns the angle (in radians) of this vector in the range `[-π, +π]`.
+    ///
+    /// The input does not need to be a unit vector however it must be non-zero.
+    #[inline]
+    pub fn to_angle(self) -> {{ scalar_t }} {
+        math::atan2(self.y, self.x)
+    }
+
     /// Returns the angle (in radians) between `self` and `rhs` in the range `[-π, +π]`.
     ///
     /// The inputs do not need to be unit vectors however they must be non-zero.
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index 7512f38..80a1d35 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -648,6 +648,14 @@ impl Vec2 {
         Self { x: cos, y: sin }
     }
 
+    /// Returns the angle (in radians) of this vector in the range `[-π, +π]`.
+    ///
+    /// The input does not need to be a unit vector however it must be non-zero.
+    #[inline]
+    pub fn to_angle(self) -> f32 {
+        math::atan2(self.y, self.x)
+    }
+
     /// Returns the angle (in radians) between `self` and `rhs` in the range `[-π, +π]`.
     ///
     /// The inputs do not need to be unit vectors however they must be non-zero.
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index 7356627..fa692ba 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -648,6 +648,14 @@ impl DVec2 {
         Self { x: cos, y: sin }
     }
 
+    /// Returns the angle (in radians) of this vector in the range `[-π, +π]`.
+    ///
+    /// The input does not need to be a unit vector however it must be non-zero.
+    #[inline]
+    pub fn to_angle(self) -> f64 {
+        math::atan2(self.y, self.x)
+    }
+
     /// Returns the angle (in radians) between `self` and `rhs` in the range `[-π, +π]`.
     ///
     /// The inputs do not need to be unit vectors however they must be non-zero.


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index a0c215b..7557aae 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -896,20 +896,27 @@ macro_rules! impl_vec2_float_tests {
             );
         });
 
-        glam_test!(test_from_angle, {
-            assert_approx_eq!($vec2::from_angle(0.0), $vec2::new(1.0, 0.0));
-            assert_approx_eq!(
-                $vec2::from_angle(core::$t::consts::FRAC_PI_2),
-                $vec2::new(0.0, 1.0)
-            );
-            assert_approx_eq!(
-                $vec2::from_angle(core::$t::consts::PI),
-                $vec2::new(-1.0, 0.0)
-            );
-            assert_approx_eq!(
-                $vec2::from_angle(-core::$t::consts::FRAC_PI_2),
-                $vec2::new(0.0, -1.0)
-            );
+        glam_test!(test_angle_conversion, {
+            let angle = 0.;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(1.0, 0.0));
+            assert_approx_eq!(vec.to_angle(), angle);
+
+            let angle = core::$t::consts::FRAC_PI_2;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(0.0, 1.0));
+            assert_approx_eq!(vec.to_angle(), angle);
+
+            let angle = core::$t::consts::PI;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(-1.0, 0.0));
+            // The sign of the angle PI gets flipped and is slightly less precise but correct
+            assert_approx_eq!(vec.to_angle().abs(), angle, 1e-6);
+
+            let angle = -core::$t::consts::FRAC_PI_2;
+            let vec = $vec2::from_angle(angle);
+            assert_approx_eq!(vec, $vec2::new(0.0, -1.0));
+            assert_approx_eq!(vec.to_angle(), angle);
         });
     };
 }