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