1use super::{
15 axial_based::{shapes::AxialCoord, HexAxialShape},
16 shapes::{AxisDQ, AxisDR, OddR},
17};
18use crate::{
19 lattice_abstract::{shapes::Axis, LatticeGraph},
20 unreachable_debug_checked,
21};
22#[cfg(feature = "const-generic-wrap")]
23use const_generic_wrap::WrapUSIZE;
24use hex2d::Integer;
25
26impl<I: Integer> crate::lattice_abstract::shapes::Coordinate for hex2d::Coordinate<I> {}
27impl<I: Integer> AxialCoord for hex2d::Coordinate<I> {
28 fn new(r: isize, q: isize) -> Self {
29 Self::new(
30 I::from_isize(r).unwrap_or_else(|| unsafe { unreachable_debug_checked() }),
31 I::from_isize(q).unwrap_or_else(|| unsafe { unreachable_debug_checked() }),
32 )
33 }
34
35 fn r(&self) -> isize {
36 self.x
37 .to_isize()
38 .unwrap_or_else(|| unsafe { unreachable_debug_checked() })
39 }
40
41 fn q(&self) -> isize {
42 self.y
43 .to_isize()
44 .unwrap_or_else(|| unsafe { unreachable_debug_checked() })
45 }
46}
47
48pub type HexShape<B, L, I = i32, H = usize, V = usize> =
50 HexAxialShape<B, L, H, V, hex2d::Coordinate<I>>;
51pub type HexGraph<N, E, B = OddR, L = (), I = i32, H = usize, V = usize> =
53 LatticeGraph<N, E, HexShape<B, L, I, H, V>>;
54
55#[cfg(feature = "const-generic-wrap")]
56pub type HexShapeConst<B, L, I, const H: usize, const V: usize> =
58 HexShape<B, L, I, WrapUSIZE<H>, WrapUSIZE<V>>;
59impl<B, L, I: hex2d::Integer, const H: usize, const V: usize> Default
60 for HexShapeConst<B, L, I, H, V>
61{
62 fn default() -> Self {
63 Self::new(WrapUSIZE::<H>, WrapUSIZE::<V>)
64 }
65}
66
67#[cfg(feature = "const-generic-wrap")]
68pub type HexGraphConst<N, E, B, L, I, const H: usize, const V: usize> =
70 LatticeGraph<N, E, HexShapeConst<B, L, I, H, V>>;
71
72impl From<hex2d::Direction> for AxisDR {
73 fn from(d: hex2d::Direction) -> Self {
74 let i = d.to_int::<isize>() as usize;
75 let i = if i == 5 { 0 } else { i + 1 };
76 debug_assert!(i <= 5);
77 unsafe { Self::from_index_unchecked(i) }
78 }
87}
88
89impl From<hex2d::Direction> for AxisDQ {
90 fn from(d: hex2d::Direction) -> Self {
91 let i = d.to_int::<isize>() as usize;
92 debug_assert!(i <= 5);
93 unsafe { Self::from_index_unchecked(i) }
94 }
95}
96
97impl From<AxisDR> for hex2d::Direction {
98 fn from(d: AxisDR) -> Self {
99 let i = d.to_index();
100 let i = if i == 0 { 5 } else { i - 1 } as isize;
101 debug_assert!(i <= 5);
102 Self::from_int(i)
103 }
104}
105
106impl From<AxisDQ> for hex2d::Direction {
107 fn from(d: AxisDQ) -> Self {
108 let i = d.to_index() as isize;
109 Self::from_int(i)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 type C = hex2d::Coordinate;
116 use super::*;
117 use crate::hex::shapes::{AxisR, OddR};
118 use petgraph::{data::DataMap, visit::*};
119 use rstest::*;
120 type Hex5x5 = HexGraphConst<C, (C, AxisR), OddR, (), i32, 5, 5>;
121
122 #[fixture]
123 fn hexgraph_oddr55() -> Hex5x5 {
124 Hex5x5::new_with_s(|x| (x), |n, d| (n, d))
125 }
126 #[rstest]
127 fn gen_oddr(hexgraph_oddr55: Hex5x5) {
128 let graph = hexgraph_oddr55;
129 for i in 0..graph.node_count() {
130 let x = graph.from_index(i);
131 assert_eq!(Some(&x), graph.node_weight(x));
132 }
133 assert_eq!(0, std::mem::size_of_val(graph.shape()))
134 }
135
136 #[rstest]
137 #[case(C::new(0, 0),[C::new(0, 1), C::new(1, 0)] )]
138 #[case(C::new(4, 0),[C::new(4, 1), C::new(3, 0), C::new(3, 1)] )]
139 #[case(C::new(1, 1),[
140 C::new(1, 2),
141 C::new(2, 1),
142 C::new(2, 0),
143 C::new(1, 0),
144 C::new(0, 1),
145 C::new(0, 2),
146 ]) ]
147 #[case(C::new(1, 2),[
148 C::new(1, 3),
149 C::new(2, 2),
150 C::new(2, 1),
151 C::new(1, 1),
152 C::new(0, 2),
153 C::new(0, 3),
154 ]) ]
155 fn neighbors_oddr(
156 hexgraph_oddr55: Hex5x5,
157 #[case] target: C,
158 #[case] neighbors: impl IntoIterator<Item = C>,
159 ) {
160 let graph = hexgraph_oddr55;
161 let e = graph.neighbors(target);
162 debug_assert!(e.eq(neighbors));
163 let e = graph.neighbors(target);
164 for neighbor in e {
165 assert_eq!(neighbor.distance(target), 1);
166 }
167 }
168}