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);
|
||||
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 {
|
||||
@ -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]
|
||||
fn dir3_creation() {
|
||||
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"))]
|
||||
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||
|
||||
/// A counterclockwise 2D rotation in radians.
|
||||
///
|
||||
/// The rotation angle is wrapped to be within the `(-pi, pi]` range.
|
||||
/// A counterclockwise 2D rotation.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
||||
Loading…
Reference in New Issue
Block a user