Skip to content

Commit

Permalink
Directions from angle (#92)
Browse files Browse the repository at this point in the history
> Closes #84 

# Work done

* Added conversion from angles for both `Direction` and
`DiagonalDirection` (#92):
  * `Direction::from_angle`
  * `Direction::from_pointy_angle`
  * `Direction::from_flat_angle`
  * `Direction::from_angle_degrees`
  * `Direction::from_pointy_angle_degrees`
  * `Direction::from_flat_angle_degrees`
  * `DiagonalDirection::from_angle`
  * `DiagonalDirection::from_pointy_angle`
  * `DiagonalDirection::from_flat_angle`
  * `DiagonalDirection::from_angle_degrees`
  * `DiagonalDirection::from_pointy_angle_degrees`
  * `DiagonalDirection::from_flat_angle_degrees`
  
# Extra work
  
* Added missing `Direction::angle_degrees` method (#92)
* Added missing `DiagonalDirection::angle_degrees` method (#92)
  • Loading branch information
ManevilleF committed Jun 15, 2023
1 parent 78fb97c commit 18e05bd
Show file tree
Hide file tree
Showing 8 changed files with 427 additions and 12 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@
* The inner data (matrices and rotation) are now retrievable through either:
* `orientation_data()` method
* `Deref` implementation
* Added conversion from angles for both `Direction` and `DiagonalDirection` (#92):
* `Direction::from_angle`
* `Direction::from_pointy_angle`
* `Direction::from_flat_angle`
* `Direction::from_angle_degrees`
* `Direction::from_pointy_angle_degrees`
* `Direction::from_flat_angle_degrees`
* `DiagonalDirection::from_angle`
* `DiagonalDirection::from_pointy_angle`
* `DiagonalDirection::from_flat_angle`
* `DiagonalDirection::from_angle_degrees`
* `DiagonalDirection::from_pointy_angle_degrees`
* `DiagonalDirection::from_flat_angle_degrees`
* Added missing `Direction::angle_degrees` method (#92)
* Added missing `DiagonalDirection::angle_degrees` method (#92)

## 0.6.0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
// Define your layout
let layout = HexLayout {
hex_size: Vec2::new(1.0, 1.0),
orientation: HexOrientation::flat(),
orientation: HexOrientation::Flat,
..Default::default()
};
// Get the hex coordinate at the world position `world_pos`.
Expand Down
136 changes: 134 additions & 2 deletions src/direction/diagonal_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub enum DiagonalDirection {
/// |orientation |radians|degrees|
/// |------------|-------|-------|
/// | Flat Top | π/3 | 60 |
/// | Flat Top | π/6 | 30 |
/// | Pointy Top | π/6 | 30 |
///
/// ```txt
/// x Axis
Expand Down Expand Up @@ -383,7 +383,7 @@ impl DiagonalDirection {
///
/// See [`Self::angle_flat`] for *flat* hexagons
pub fn angle_pointy(self) -> f32 {
self.angle_flat() - DIRECTION_ANGLE_OFFSET
self.angle_flat() - DIRECTION_ANGLE_OFFSET_RAD
}

#[inline]
Expand Down Expand Up @@ -411,6 +411,138 @@ impl DiagonalDirection {
self.angle_pointy() - orientation.angle_offset
}

#[inline]
#[must_use]
/// Returns the angle in degrees of the given direction according to its `orientation`
///
/// See [`Self::angle`] for radians angles
pub fn angle_degrees(self, orientation: &HexOrientation) -> f32 {
match orientation {
HexOrientation::Pointy => self.angle_pointy_degrees(),
HexOrientation::Flat => self.angle_flat_degrees(),
}
}

#[must_use]
/// Returns the direction from the given `angle` in degrees
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = DiagonalDirection::from_flat_angle_degrees(15.0);
/// assert_eq!(direction, DiagonalDirection::Right);
/// ```
pub fn from_flat_angle_degrees(angle: f32) -> Self {
Self::from_pointy_angle_degrees(angle - DIRECTION_ANGLE_OFFSET_DEGREES)
}

#[must_use]
#[allow(clippy::cast_possible_truncation)]
/// Returns the direction from the given `angle` in degrees
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = DiagonalDirection::from_pointy_angle_degrees(15.0);
/// assert_eq!(direction, DiagonalDirection::TopRight);
/// ```
pub fn from_pointy_angle_degrees(angle: f32) -> Self {
let angle = angle.rem_euclid(360.0);
let sector = (angle / DIRECTION_ANGLE_DEGREES).trunc() as i32;
println!("{angle} - {sector}");
match sector {
0 => Self::TopRight,
1 => Self::TopLeft,
2 => Self::Left,
3 => Self::BottomLeft,
4 => Self::BottomRight,
_ => Self::Right,
}
}

#[must_use]
/// Returns the direction from the given `angle` in radians
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = DiagonalDirection::from_flat_angle(0.26);
/// assert_eq!(direction, DiagonalDirection::Right);
/// ```
pub fn from_flat_angle(angle: f32) -> Self {
Self::from_pointy_angle(angle - DIRECTION_ANGLE_OFFSET_RAD)
}

#[must_use]
#[allow(clippy::cast_possible_truncation)]
/// Returns the direction from the given `angle` in radians
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = DiagonalDirection::from_pointy_angle(0.26);
/// assert_eq!(direction, DiagonalDirection::TopRight);
/// ```
pub fn from_pointy_angle(angle: f32) -> Self {
let angle = angle.rem_euclid(PI_2);
let sector = (angle / DIRECTION_ANGLE_RAD) as i32;
println!("{angle} - {sector}");
match sector {
0 => Self::TopRight,
1 => Self::TopLeft,
2 => Self::Left,
3 => Self::BottomLeft,
4 => Self::BottomRight,
_ => Self::Right,
}
}

#[must_use]
/// Returns the direction from the given `angle` in degrees according the `orientation`
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let angle = 15.0;
/// assert_eq!(DiagonalDirection::from_angle_degrees(angle, &HexOrientation::Flat), DiagonalDirection::Right);
/// assert_eq!(DiagonalDirection::from_angle_degrees(angle, &HexOrientation::Pointy), DiagonalDirection::TopRight);
/// ```
pub fn from_angle_degrees(angle: f32, orientation: &HexOrientation) -> Self {
match orientation {
HexOrientation::Pointy => Self::from_pointy_angle_degrees(angle),
HexOrientation::Flat => Self::from_flat_angle_degrees(angle),
}
}

#[must_use]
/// Returns the direction from the given `angle` in radians according the `orientation`
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let angle = 0.26;
/// assert_eq!(DiagonalDirection::from_angle(angle, &HexOrientation::Flat), DiagonalDirection::Right);
/// assert_eq!(DiagonalDirection::from_angle(angle, &HexOrientation::Pointy), DiagonalDirection::TopRight);
/// ```
pub fn from_angle(angle: f32, orientation: &HexOrientation) -> Self {
match orientation {
HexOrientation::Pointy => Self::from_pointy_angle(angle),
HexOrientation::Flat => Self::from_flat_angle(angle),
}
}

#[deprecated(since = "0.6.0", note = "Use DiagonalDirection::direction_ccw")]
#[inline]
#[must_use]
Expand Down
138 changes: 134 additions & 4 deletions src/direction/hex_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ impl Direction {
///
/// See [`Self::angle_pointy`] for *pointy* hexagons
pub fn angle_flat(self) -> f32 {
self.angle_pointy() + DIRECTION_ANGLE_OFFSET
self.angle_pointy() + DIRECTION_ANGLE_OFFSET_RAD
}

#[inline]
Expand All @@ -389,6 +389,13 @@ impl Direction {
Self::POINTY_ANGLES[self as usize]
}

#[inline]
#[must_use]
/// Returns the angle in radians of the given direction in the given `orientation`
pub fn angle(self, orientation: &HexOrientation) -> f32 {
self.angle_pointy() - orientation.angle_offset
}

#[inline]
#[must_use]
/// Returns the angle in degrees of the given direction for *pointy* hexagons
Expand All @@ -409,9 +416,132 @@ impl Direction {

#[inline]
#[must_use]
/// Returns the angle in radians of the given direction in the given `orientation`
pub fn angle(self, orientation: &HexOrientation) -> f32 {
self.angle_pointy() - orientation.angle_offset
/// Returns the angle in degrees of the given direction according to its `orientation`
///
/// See [`Self::angle`] for radians angles
pub fn angle_degrees(self, orientation: &HexOrientation) -> f32 {
match orientation {
HexOrientation::Pointy => self.angle_pointy_degrees(),
HexOrientation::Flat => self.angle_flat_degrees(),
}
}

#[must_use]
/// Returns the direction from the given `angle` in degrees
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = Direction::from_pointy_angle_degrees(35.0);
/// assert_eq!(direction, Direction::Top);
/// ```
pub fn from_pointy_angle_degrees(angle: f32) -> Self {
Self::from_flat_angle_degrees(angle + DIRECTION_ANGLE_OFFSET_DEGREES)
}

#[must_use]
#[allow(clippy::cast_possible_truncation)]
/// Returns the direction from the given `angle` in degrees
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = Direction::from_flat_angle_degrees(35.0);
/// assert_eq!(direction, Direction::TopRight);
/// ```
pub fn from_flat_angle_degrees(angle: f32) -> Self {
let angle = angle.rem_euclid(360.0);
let sector = (angle / DIRECTION_ANGLE_DEGREES).trunc() as i32;
match sector {
0 => Self::TopRight,
1 => Self::Top,
2 => Self::TopLeft,
3 => Self::BottomLeft,
4 => Self::Bottom,
_ => Self::BottomRight,
}
}

#[must_use]
/// Returns the direction from the given `angle` in radians
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = Direction::from_pointy_angle(0.6);
/// assert_eq!(direction, Direction::Top);
/// ```
pub fn from_pointy_angle(angle: f32) -> Self {
Self::from_flat_angle(angle + DIRECTION_ANGLE_OFFSET_RAD)
}

#[must_use]
#[allow(clippy::cast_possible_truncation)]
/// Returns the direction from the given `angle` in radians
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let direction = Direction::from_flat_angle(0.6);
/// assert_eq!(direction, Direction::TopRight);
/// ```
pub fn from_flat_angle(angle: f32) -> Self {
let angle = angle.rem_euclid(PI_2);
let sector = (angle / DIRECTION_ANGLE_RAD) as i32;
match sector {
0 => Self::TopRight,
1 => Self::Top,
2 => Self::TopLeft,
3 => Self::BottomLeft,
4 => Self::Bottom,
_ => Self::BottomRight,
}
}

#[must_use]
/// Returns the direction from the given `angle` in degrees according the `orientation`
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let angle = 35.0;
/// assert_eq!(Direction::from_angle_degrees(angle, &HexOrientation::Flat), Direction::TopRight);
/// assert_eq!(Direction::from_angle_degrees(angle, &HexOrientation::Pointy), Direction::Top);
/// ```
pub fn from_angle_degrees(angle: f32, orientation: &HexOrientation) -> Self {
match orientation {
HexOrientation::Pointy => Self::from_pointy_angle_degrees(angle),
HexOrientation::Flat => Self::from_flat_angle_degrees(angle),
}
}

#[must_use]
/// Returns the direction from the given `angle` in radians according the `orientation`
///
/// # Example
///
/// ```rust
/// # use hexx::*;
///
/// let angle = 0.6;
/// assert_eq!(Direction::from_angle(angle, &HexOrientation::Flat), Direction::TopRight);
/// assert_eq!(Direction::from_angle(angle, &HexOrientation::Pointy), Direction::Top);
/// ```
pub fn from_angle(angle: f32, orientation: &HexOrientation) -> Self {
match orientation {
HexOrientation::Pointy => Self::from_pointy_angle(angle),
HexOrientation::Flat => Self::from_flat_angle(angle),
}
}

#[deprecated(since = "0.6.0", note = "Use Direction::diagonal_ccw")]
Expand Down
4 changes: 3 additions & 1 deletion src/direction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod angles {
use std::f32::consts::PI;
/// Angle in radian between *flat* and *pointy* top orientations.
/// Equivalent to 30 degrees
pub const DIRECTION_ANGLE_OFFSET: f32 = PI / 6.0;
pub const DIRECTION_ANGLE_OFFSET_RAD: f32 = PI / 6.0;
/// Angle in radian between *flat* and *pointy* top orientations.
/// Equivalent to π / 6 in radians
pub const DIRECTION_ANGLE_OFFSET_DEGREES: f32 = 30.0;
Expand All @@ -33,4 +33,6 @@ pub mod angles {
/// Angle in degrees between two adjacent directions counter clockwise.
/// Equivalent to π / 3 in radians
pub const DIRECTION_ANGLE_DEGREES: f32 = 60.0;
/// π * 2
pub const PI_2: f32 = PI * 2.0;
}
Loading

0 comments on commit 18e05bd

Please sign in to comment.