iron_shapes/
isotropy.rs

1// SPDX-FileCopyrightText: 2022 Thomas Kramer
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5//! Describe alignment and orientation along coordinate axes.
6
7use num_traits::Signed;
8
9/// Direction in one dimension.
10#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub enum Direction1D {
13    /// Towards negative coordinates.
14    Low,
15    /// Towards positive coordinates.
16    High,
17}
18
19impl Direction1D {
20    /// Return the opposite direction.
21    pub fn reversed(self) -> Self {
22        match self {
23            Direction1D::Low => Direction1D::High,
24            Direction1D::High => Direction1D::Low,
25        }
26    }
27
28    /// Map `Low` to `-1` and `High` to `+1`.
29    pub fn sign<N>(&self) -> N
30    where
31        N: Signed,
32    {
33        match self {
34            Direction1D::Low => N::one().neg(),
35            Direction1D::High => N::one(),
36        }
37    }
38}
39
40impl From<Direction2D> for Direction1D {
41    /// Downcast 2D direction to 1D direction by preserving the sign.
42    fn from(d2: Direction2D) -> Self {
43        match d2 {
44            Direction2D::Right | Direction2D::Up => Direction1D::High,
45            Direction2D::Left | Direction2D::Down => Direction1D::Low,
46        }
47    }
48}
49
50/// Orientation in two dimensions along one of the axes.
51#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
52#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53pub enum Orientation2D {
54    /// Oriented parallel to the x axis.
55    Horizontal,
56    /// Oriented parallel to the y axis.
57    Vertical,
58}
59
60impl Orientation2D {
61    /// Get the orthogonal orientation.
62    pub fn other(self) -> Self {
63        match self {
64            Orientation2D::Horizontal => Self::Vertical,
65            Orientation2D::Vertical => Self::Horizontal,
66        }
67    }
68
69    /// Get the positive or negative direction aligned with this orientation.
70    pub fn direction(self, d1: Direction1D) -> Direction2D {
71        use Direction1D::*;
72        use Direction2D::*;
73        use Orientation2D::*;
74        match (self, d1) {
75            (Horizontal, Low) => Right,
76            (Horizontal, High) => Left,
77            (Vertical, Low) => Down,
78            (Vertical, High) => Up,
79        }
80    }
81
82    /// Check if orientation is vertical.
83    pub fn is_vertical(&self) -> bool {
84        self == &Self::Vertical
85    }
86
87    /// Check if orientation is horizontal.
88    pub fn is_horizontal(&self) -> bool {
89        self == &Self::Horizontal
90    }
91}
92
93/// Directions along the coordinate axes in two dimensions.
94#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
95#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96pub enum Direction2D {
97    /// Positive x direction.
98    Left,
99    /// Positive y direction.
100    Up,
101    /// Negative x direction.
102    Right,
103    /// Negative y direction.
104    Down,
105}
106
107impl Direction2D {
108    /// Get the opposite direction.
109    pub fn reversed(self) -> Self {
110        match self {
111            Direction2D::Left => Self::Right,
112            Direction2D::Up => Self::Down,
113            Direction2D::Right => Self::Left,
114            Direction2D::Down => Self::Up,
115        }
116    }
117
118    /// Get the orientation of this direction.
119    pub fn orientation(&self) -> Orientation2D {
120        match self {
121            Direction2D::Left | Direction2D::Right => Orientation2D::Horizontal,
122            Direction2D::Up | Direction2D::Down => Orientation2D::Vertical,
123        }
124    }
125
126    /// Get the sign of the direction.
127    pub fn sign<N>(self) -> N
128    where
129        N: Signed,
130    {
131        let d1: Direction1D = self.into();
132        d1.sign()
133    }
134}