mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
# Objective Implements #13647 ## Solution Created two enums, CompassQuadrant and CompassOctant inside compass.rs with impls To and From Dir2. Used dir.to_angle().to_degrees() and matched against the resulting value. I could have skipped to_degrees() and matched against the radian value, but I thought this was more readable. I'm probably wrong lol. ## Testing Tested various dirs to compass variations. --- --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
6038d1599e
commit
0db9fc92cd
2 changed files with 403 additions and 0 deletions
401
crates/bevy_math/src/compass.rs
Normal file
401
crates/bevy_math/src/compass.rs
Normal file
|
@ -0,0 +1,401 @@
|
|||
use crate::Dir2;
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
|
||||
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||
|
||||
/// A compass enum with 4 directions.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
|
||||
#[cfg_attr(
|
||||
all(feature = "serialize", feature = "bevy_reflect"),
|
||||
reflect(Deserialize, Serialize)
|
||||
)]
|
||||
pub enum CompassQuadrant {
|
||||
/// Corresponds to [`Dir2::Y`] and [`Dir2::NORTH`]
|
||||
North,
|
||||
/// Corresponds to [`Dir2::X`] and [`Dir2::EAST`]
|
||||
East,
|
||||
/// Corresponds to [`Dir2::NEG_X`] and [`Dir2::SOUTH`]
|
||||
South,
|
||||
/// Corresponds to [`Dir2::NEG_Y`] and [`Dir2::WEST`]
|
||||
West,
|
||||
}
|
||||
|
||||
/// A compass enum with 8 directions.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
|
||||
#[cfg_attr(
|
||||
all(feature = "serialize", feature = "bevy_reflect"),
|
||||
reflect(Deserialize, Serialize)
|
||||
)]
|
||||
pub enum CompassOctant {
|
||||
/// Corresponds to [`Dir2::Y`] and [`Dir2::NORTH`]
|
||||
North,
|
||||
/// Corresponds to [`Dir2::NORTH_EAST`]
|
||||
NorthEast,
|
||||
/// Corresponds to [`Dir2::X`] and [`Dir2::EAST`]
|
||||
East,
|
||||
/// Corresponds to [`Dir2::SOUTH_EAST`]
|
||||
SouthEast,
|
||||
/// Corresponds to [`Dir2::NEG_X`] and [`Dir2::SOUTH`]
|
||||
South,
|
||||
/// Corresponds to [`Dir2::SOUTH_WEST`]
|
||||
SouthWest,
|
||||
/// Corresponds to [`Dir2::NEG_Y`] and [`Dir2::WEST`]
|
||||
West,
|
||||
/// Corresponds to [`Dir2::NORTH_WEST`]
|
||||
NorthWest,
|
||||
}
|
||||
|
||||
impl From<CompassQuadrant> for Dir2 {
|
||||
fn from(q: CompassQuadrant) -> Self {
|
||||
match q {
|
||||
CompassQuadrant::North => Dir2::NORTH,
|
||||
CompassQuadrant::East => Dir2::EAST,
|
||||
CompassQuadrant::South => Dir2::SOUTH,
|
||||
CompassQuadrant::West => Dir2::WEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dir2> for CompassQuadrant {
|
||||
/// Converts a [`Dir2`] to a [`CompassQuadrant`] in a lossy manner.
|
||||
/// Converting back to a [`Dir2`] is not guaranteed to yield the same value.
|
||||
fn from(dir: Dir2) -> Self {
|
||||
let angle = dir.to_angle().to_degrees();
|
||||
|
||||
match angle {
|
||||
-135.0..=-45.0 => Self::South,
|
||||
-45.0..=45.0 => Self::East,
|
||||
45.0..=135.0 => Self::North,
|
||||
135.0..=180.0 | -180.0..=-135.0 => Self::West,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompassOctant> for Dir2 {
|
||||
fn from(o: CompassOctant) -> Self {
|
||||
match o {
|
||||
CompassOctant::North => Dir2::NORTH,
|
||||
CompassOctant::NorthEast => Dir2::NORTH_EAST,
|
||||
CompassOctant::East => Dir2::EAST,
|
||||
CompassOctant::SouthEast => Dir2::SOUTH_EAST,
|
||||
CompassOctant::South => Dir2::SOUTH,
|
||||
CompassOctant::SouthWest => Dir2::SOUTH_WEST,
|
||||
CompassOctant::West => Dir2::WEST,
|
||||
CompassOctant::NorthWest => Dir2::NORTH_WEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dir2> for CompassOctant {
|
||||
/// Converts a [`Dir2`] to a [`CompassOctant`] in a lossy manner.
|
||||
/// Converting back to a [`Dir2`] is not guaranteed to yield the same value.
|
||||
fn from(dir: Dir2) -> Self {
|
||||
let angle = dir.to_angle().to_degrees();
|
||||
|
||||
match angle {
|
||||
-112.5..=-67.5 => Self::South,
|
||||
-67.5..=-22.5 => Self::SouthEast,
|
||||
-22.5..=22.5 => Self::East,
|
||||
22.5..=67.5 => Self::NorthEast,
|
||||
67.5..=112.5 => Self::North,
|
||||
112.5..=157.5 => Self::NorthWest,
|
||||
157.5..=180.0 | -180.0..=-157.5 => Self::West,
|
||||
-157.5..=-112.5 => Self::SouthWest,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_compass_quadrant {
|
||||
use crate::{CompassQuadrant, Dir2, Vec2};
|
||||
|
||||
#[test]
|
||||
fn test_cardinal_directions() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(1.0, 0.0)).unwrap(),
|
||||
CompassQuadrant::East,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.0, 1.0)).unwrap(),
|
||||
CompassQuadrant::North,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-1.0, 0.0)).unwrap(),
|
||||
CompassQuadrant::West,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.0, -1.0)).unwrap(),
|
||||
CompassQuadrant::South,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassQuadrant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_north_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.1, 0.9)).unwrap(),
|
||||
CompassQuadrant::North,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.1, 0.9)).unwrap(),
|
||||
CompassQuadrant::North,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassQuadrant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_east_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(0.9, 0.1)).unwrap(),
|
||||
CompassQuadrant::East,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.9, -0.1)).unwrap(),
|
||||
CompassQuadrant::East,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassQuadrant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_south_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.1, -0.9)).unwrap(),
|
||||
CompassQuadrant::South,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.1, -0.9)).unwrap(),
|
||||
CompassQuadrant::South,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassQuadrant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_west_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.9, -0.1)).unwrap(),
|
||||
CompassQuadrant::West,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.9, 0.1)).unwrap(),
|
||||
CompassQuadrant::West,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassQuadrant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_compass_octant {
|
||||
use crate::{CompassOctant, Dir2, Vec2};
|
||||
|
||||
#[test]
|
||||
fn test_cardinal_directions() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.5, 0.5)).unwrap(),
|
||||
CompassOctant::NorthWest,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.0, 1.0)).unwrap(),
|
||||
CompassOctant::North,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.5, 0.5)).unwrap(),
|
||||
CompassOctant::NorthEast,
|
||||
),
|
||||
(Dir2::new(Vec2::new(1.0, 0.0)).unwrap(), CompassOctant::East),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.5, -0.5)).unwrap(),
|
||||
CompassOctant::SouthEast,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.0, -1.0)).unwrap(),
|
||||
CompassOctant::South,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.5, -0.5)).unwrap(),
|
||||
CompassOctant::SouthWest,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-1.0, 0.0)).unwrap(),
|
||||
CompassOctant::West,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_north_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.1, 0.9)).unwrap(),
|
||||
CompassOctant::North,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.1, 0.9)).unwrap(),
|
||||
CompassOctant::North,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_north_east_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(0.4, 0.6)).unwrap(),
|
||||
CompassOctant::NorthEast,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.6, 0.4)).unwrap(),
|
||||
CompassOctant::NorthEast,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_east_pie_slice() {
|
||||
let tests = vec![
|
||||
(Dir2::new(Vec2::new(0.9, 0.1)).unwrap(), CompassOctant::East),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.9, -0.1)).unwrap(),
|
||||
CompassOctant::East,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_south_east_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(0.4, -0.6)).unwrap(),
|
||||
CompassOctant::SouthEast,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.6, -0.4)).unwrap(),
|
||||
CompassOctant::SouthEast,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_south_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.1, -0.9)).unwrap(),
|
||||
CompassOctant::South,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(0.1, -0.9)).unwrap(),
|
||||
CompassOctant::South,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_south_west_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.4, -0.6)).unwrap(),
|
||||
CompassOctant::SouthWest,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.6, -0.4)).unwrap(),
|
||||
CompassOctant::SouthWest,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_west_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.9, -0.1)).unwrap(),
|
||||
CompassOctant::West,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.9, 0.1)).unwrap(),
|
||||
CompassOctant::West,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_north_west_pie_slice() {
|
||||
let tests = vec![
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.4, 0.6)).unwrap(),
|
||||
CompassOctant::NorthWest,
|
||||
),
|
||||
(
|
||||
Dir2::new(Vec2::new(-0.6, 0.4)).unwrap(),
|
||||
CompassOctant::NorthWest,
|
||||
),
|
||||
];
|
||||
|
||||
for (dir, expected) in tests {
|
||||
assert_eq!(CompassOctant::from(dir), expected);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ mod affine3;
|
|||
mod aspect_ratio;
|
||||
pub mod bounding;
|
||||
mod common_traits;
|
||||
mod compass;
|
||||
pub mod cubic_splines;
|
||||
mod direction;
|
||||
mod float_ord;
|
||||
|
@ -24,6 +25,7 @@ mod rects;
|
|||
mod rotation2d;
|
||||
#[cfg(feature = "rand")]
|
||||
pub mod sampling;
|
||||
pub use compass::{CompassOctant, CompassQuadrant};
|
||||
|
||||
pub use affine3::*;
|
||||
pub use aspect_ratio::AspectRatio;
|
||||
|
|
Loading…
Reference in a new issue