lattice_graph/square/
index.rs

1use petgraph::graph::IndexType;
2
3/// Axis of the Square grid.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
5pub enum Axis {
6    Horizontal,
7    Vertical,
8}
9
10impl Axis {
11    /// Check whether axis is horizontal.
12    pub const fn is_horizontal(&self) -> bool {
13        matches!(self, Axis::Horizontal)
14    }
15    /// Check whether axis is vertical.
16    pub const fn is_vertical(&self) -> bool {
17        matches!(self, Axis::Vertical)
18    }
19}
20
21/// Direction of Axis.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
23pub enum SquareDirection {
24    Foward(Axis),
25    Backward(Axis),
26}
27
28impl SquareDirection {
29    /// Foward Horizontal
30    pub const fn up() -> Self {
31        Self::Foward(Axis::Vertical)
32    }
33    /// Backward Horizontal
34    pub const fn down() -> Self {
35        Self::Backward(Axis::Vertical)
36    }
37    /// Backward Vertical
38    pub const fn left() -> Self {
39        Self::Backward(Axis::Horizontal)
40    }
41    /// Foward Vertical
42    pub const fn right() -> Self {
43        Self::Foward(Axis::Horizontal)
44    }
45    pub const fn is_horizontal(&self) -> bool {
46        match self {
47            SquareDirection::Foward(x) | SquareDirection::Backward(x) => x.is_horizontal(),
48        }
49    }
50    pub const fn is_vertical(&self) -> bool {
51        match self {
52            SquareDirection::Foward(x) | SquareDirection::Backward(x) => x.is_vertical(),
53        }
54    }
55}
56
57impl From<(Axis, bool)> for SquareDirection {
58    fn from((axis, dir): (Axis, bool)) -> Self {
59        if dir {
60            SquareDirection::Foward(axis)
61        } else {
62            SquareDirection::Backward(axis)
63        }
64    }
65}
66
67impl From<SquareDirection> for (Axis, bool) {
68    fn from(dir: SquareDirection) -> Self {
69        match dir {
70            SquareDirection::Backward(x) => (x, false),
71            SquareDirection::Foward(x) => (x, true),
72        }
73    }
74}
75
76/// Node index for [`SquareGraph`]
77#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
78pub struct NodeIndex<Ix: IndexType> {
79    pub horizontal: Ix,
80    pub vertical: Ix,
81}
82
83impl<Ix: IndexType> NodeIndex<Ix> {
84    /// Create a Index from horizontal and vertical.
85    pub fn new(horizontal: Ix, vertical: Ix) -> Self {
86        Self {
87            horizontal,
88            vertical,
89        }
90    }
91
92    /// Returns the manhattan distance
93    pub fn distance<T: Into<(usize, usize)>>(&self, target: T) -> usize {
94        let target: (usize, usize) = target.into();
95        (self.horizontal.index() as isize - target.0 as isize).unsigned_abs()
96            + (self.vertical.index() as isize - target.1 as isize).unsigned_abs()
97    }
98
99    /// Get the edge from this node. This does not check whether the node is valid in graph.
100    pub unsafe fn get_edge_id_unchecked(&self, dir: SquareDirection) -> EdgeIndex<Ix> {
101        match dir {
102            SquareDirection::Foward(x) => (*self, x),
103            SquareDirection::Backward(a @ Axis::Vertical) => (
104                Self::new(self.horizontal, Ix::new(self.vertical.index() - 1)),
105                a,
106            ),
107            SquareDirection::Backward(a @ Axis::Horizontal) => (
108                Self::new(Ix::new(self.horizontal.index() - 1), self.vertical),
109                a,
110            ),
111        }
112        .into()
113    }
114
115    #[inline]
116    pub fn up(self) -> Self {
117        Self {
118            vertical: Ix::new(self.vertical.index() + 1),
119            ..self
120        }
121    }
122
123    #[inline]
124    pub fn down(self) -> Self {
125        Self {
126            vertical: Ix::new(self.vertical.index() - 1),
127            ..self
128        }
129    }
130
131    #[inline]
132    pub fn right(self) -> Self {
133        Self {
134            horizontal: Ix::new(self.horizontal.index() + 1),
135            ..self
136        }
137    }
138
139    #[inline]
140    pub fn left(self) -> Self {
141        Self {
142            horizontal: Ix::new(self.horizontal.index() - 1),
143            ..self
144        }
145    }
146}
147
148impl<Ix: IndexType> PartialEq<(usize, usize)> for NodeIndex<Ix> {
149    fn eq(&self, value: &(usize, usize)) -> bool {
150        &(self.horizontal.index(), self.vertical.index()) == value
151    }
152}
153
154impl<Ix: IndexType> From<(usize, usize)> for NodeIndex<Ix> {
155    fn from(value: (usize, usize)) -> Self {
156        NodeIndex::new(Ix::new(value.0), Ix::new(value.1))
157    }
158}
159
160impl<Ix: IndexType> From<NodeIndex<Ix>> for (usize, usize) {
161    fn from(value: NodeIndex<Ix>) -> Self {
162        (value.horizontal.index(), value.vertical.index())
163    }
164}
165
166/// Edge Index of [`SquareGraph`].
167#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
168pub struct EdgeIndex<Ix: IndexType> {
169    pub node: NodeIndex<Ix>,
170    pub axis: Axis,
171}
172
173impl<Ix: IndexType> From<(NodeIndex<Ix>, Axis)> for EdgeIndex<Ix> {
174    fn from((n, a): (NodeIndex<Ix>, Axis)) -> Self {
175        Self { node: n, axis: a }
176    }
177}
178
179impl<Ix: IndexType> From<(NodeIndex<Ix>, SquareDirection)> for EdgeIndex<Ix> {
180    fn from((n, a): (NodeIndex<Ix>, SquareDirection)) -> Self {
181        unsafe { n.get_edge_id_unchecked(a) }
182    }
183}