1use petgraph::graph::IndexType;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
5pub enum Axis {
6 Horizontal,
7 Vertical,
8}
9
10impl Axis {
11 pub const fn is_horizontal(&self) -> bool {
13 matches!(self, Axis::Horizontal)
14 }
15 pub const fn is_vertical(&self) -> bool {
17 matches!(self, Axis::Vertical)
18 }
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
23pub enum SquareDirection {
24 Foward(Axis),
25 Backward(Axis),
26}
27
28impl SquareDirection {
29 pub const fn up() -> Self {
31 Self::Foward(Axis::Vertical)
32 }
33 pub const fn down() -> Self {
35 Self::Backward(Axis::Vertical)
36 }
37 pub const fn left() -> Self {
39 Self::Backward(Axis::Horizontal)
40 }
41 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#[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 pub fn new(horizontal: Ix, vertical: Ix) -> Self {
86 Self {
87 horizontal,
88 vertical,
89 }
90 }
91
92 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 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#[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}