Dir2 -> Rotation2d conversions (#13670)
				
					
				
			# Objective
Filling a hole in the API: Previously, there was no particularly
ergonomic way to go from, e.g., a pair of directions to the rotation
that links them.
## Solution
We introduce a small suite of API methods to `Dir2` to address this:
```rust
/// Get the rotation that rotates this direction to `other`.
pub fn rotation_to(self, other: Self) -> Rotation2d { //... }
/// Get the rotation that rotates `other` to this direction.
pub fn rotation_from(self, other: Self) -> Rotation2d { //... }
/// Get the rotation that rotates the X-axis to this direction.
pub fn rotation_from_x(self) -> Rotation2d { //... }
/// Get the rotation that rotates this direction to the X-axis.
pub fn rotation_to_x(self) -> Rotation2d { //... }
/// Get the rotation that rotates this direction to the Y-axis.
pub fn rotation_from_y(self) -> Rotation2d { //... }
/// Get the rotation that rotates the Y-axis to this direction.
pub fn rotation_to_y(self) -> Rotation2d { //... }
```
I also removed some language from the `Rotation2d` docs that is
misleading: the radian and angle conversion functions are already clear
about which angles they spit out, and `Rotation2d` itself doesn't have
any bounds on angles or anything.
			
			
This commit is contained in:
		
							parent
							
								
									49338245ea
								
							
						
					
					
						commit
						39609f1708
					
				| @ -202,6 +202,47 @@ impl Dir2 { | |||||||
|         let angle = self.angle_between(rhs.0); |         let angle = self.angle_between(rhs.0); | ||||||
|         Rotation2d::radians(angle * s) * self |         Rotation2d::radians(angle * s) * self | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates this direction to `other`.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_to(self, other: Self) -> Rotation2d { | ||||||
|  |         // Rotate `self` to X-axis, then X-axis to `other`:
 | ||||||
|  |         other.rotation_from_x() * self.rotation_to_x() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates `other` to this direction.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_from(self, other: Self) -> Rotation2d { | ||||||
|  |         other.rotation_to(self) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates the X-axis to this direction.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_from_x(self) -> Rotation2d { | ||||||
|  |         Rotation2d::from_sin_cos(self.0.y, self.0.x) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates this direction to the X-axis.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_to_x(self) -> Rotation2d { | ||||||
|  |         // (This is cheap, it just negates one component.)
 | ||||||
|  |         self.rotation_from_x().inverse() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates this direction to the Y-axis.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_from_y(self) -> Rotation2d { | ||||||
|  |         // `x <- y`, `y <- -x` correspond to rotating clockwise by pi/2;
 | ||||||
|  |         // this transforms the Y-axis into the X-axis, maintaining the relative position
 | ||||||
|  |         // of our direction. Then we just use the same technique as `rotation_from_x`.
 | ||||||
|  |         Rotation2d::from_sin_cos(-self.0.x, self.0.y) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Get the rotation that rotates the Y-axis to this direction.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub fn rotation_to_y(self) -> Rotation2d { | ||||||
|  |         self.rotation_from_y().inverse() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TryFrom<Vec2> for Dir2 { | impl TryFrom<Vec2> for Dir2 { | ||||||
| @ -764,6 +805,25 @@ mod tests { | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn dir2_to_rotation2d() { | ||||||
|  |         assert_relative_eq!( | ||||||
|  |             Dir2::EAST.rotation_to(Dir2::NORTH_EAST), | ||||||
|  |             Rotation2d::FRAC_PI_4 | ||||||
|  |         ); | ||||||
|  |         assert_relative_eq!( | ||||||
|  |             Dir2::NORTH.rotation_from(Dir2::NORTH_EAST), | ||||||
|  |             Rotation2d::FRAC_PI_4 | ||||||
|  |         ); | ||||||
|  |         assert_relative_eq!(Dir2::SOUTH.rotation_to_x(), Rotation2d::FRAC_PI_2); | ||||||
|  |         assert_relative_eq!(Dir2::SOUTH.rotation_to_y(), Rotation2d::PI); | ||||||
|  |         assert_relative_eq!( | ||||||
|  |             Dir2::NORTH_WEST.rotation_from_x(), | ||||||
|  |             Rotation2d::degrees(135.0) | ||||||
|  |         ); | ||||||
|  |         assert_relative_eq!(Dir2::NORTH_WEST.rotation_from_y(), Rotation2d::FRAC_PI_4); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn dir3_creation() { |     fn dir3_creation() { | ||||||
|         assert_eq!(Dir3::new(Vec3::X * 12.5), Ok(Dir3::X)); |         assert_eq!(Dir3::new(Vec3::X * 12.5), Ok(Dir3::X)); | ||||||
|  | |||||||
| @ -7,9 +7,7 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect}; | |||||||
| #[cfg(all(feature = "serialize", feature = "bevy_reflect"))] | #[cfg(all(feature = "serialize", feature = "bevy_reflect"))] | ||||||
| use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; | use bevy_reflect::{ReflectDeserialize, ReflectSerialize}; | ||||||
| 
 | 
 | ||||||
| /// A counterclockwise 2D rotation in radians.
 | /// A counterclockwise 2D rotation.
 | ||||||
| ///
 |  | ||||||
| /// The rotation angle is wrapped to be within the `(-pi, pi]` range.
 |  | ||||||
| ///
 | ///
 | ||||||
| /// # Example
 | /// # Example
 | ||||||
| ///
 | ///
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Matty
						Matty