cell_grid/legacy/
coord.rs1#[allow(missing_docs, clippy::exhaustive_structs)]
3#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash)]
4#[deprecated(since = "0.1.4", note = "Use `DynamicGrid` instead")]
5pub struct Coord {
6 pub x: i32,
7 pub y: i32,
8}
9
10impl Coord {
11 #[must_use]
12 #[allow(missing_docs)]
13 pub const fn new(x: i32, y: i32) -> Self {
14 Self { x, y }
15 }
16
17 #[must_use]
18 pub(crate) fn from_index(grid_width: usize, index: usize) -> Self {
19 Self {
20 x: (index % grid_width).try_into().unwrap(),
21 y: (index / grid_width).try_into().unwrap(),
22 }
23 }
24
25 #[must_use]
26 pub(crate) fn into_index(self, grid_width: usize) -> Option<usize> {
27 let x: usize = self.x.try_into().ok()?;
28 let y: usize = self.y.try_into().ok()?;
29 if x >= grid_width {
30 return None;
31 }
32 Some(y * grid_width + x)
33 }
34}
35
36impl From<[i32; 2]> for Coord {
37 fn from([x, y]: [i32; 2]) -> Self {
38 Self { x, y }
39 }
40}
41
42impl From<[f32; 2]> for Coord {
43 #[allow(clippy::cast_possible_truncation)]
44 fn from([x, y]: [f32; 2]) -> Self {
45 Self {
46 x: x as i32,
47 y: y as i32,
48 }
49 }
50}
51
52#[cfg(feature = "aline")]
53impl From<aline::IVec2> for Coord {
54 fn from(aline::IVec2 { x, y }: aline::IVec2) -> Self {
55 Self { x, y }
56 }
57}
58
59#[cfg(feature = "aline")]
60impl From<aline::Vec2> for Coord {
61 fn from(v: aline::Vec2) -> Self {
62 v.as_i32().into()
63 }
64}
65
66#[cfg(test)]
67mod tests {
68
69 use super::*;
70 use alloc::collections::BTreeSet;
71 use rstest::rstest;
72
73 #[rstest]
74 #[allow(clippy::cast_sign_loss)]
75 fn test_into_index_from_index(#[values([0, 0], [123, 456])] coord: impl Into<Coord>) {
76 const WIDTH: usize = 150;
77 let coord = coord.into();
78 let index = coord.into_index(WIDTH).unwrap();
79 assert_eq!(coord, Coord::from_index(WIDTH, index));
80 }
81
82 #[test]
83 fn ciirds_have_unique_index_in_grid_len() {
84 let coords = [[0, 0], [0, 1], [1, 0], [1, 1]];
85 let indices = coords
86 .into_iter()
87 .map(Coord::from)
88 .filter_map(|c| c.into_index(2))
89 .collect::<BTreeSet<usize>>();
90 assert_eq!(indices.len(), coords.len());
91 for index in indices {
92 assert!(index < 4, "index {index} is out of grid length");
93 }
94 }
95
96 #[rstest]
97 fn into_index_should_return_none_if_out_of_bounds(
98 #[values([-1, 0], [0, -1], [100, 0], [101, 0])] coord: impl Into<Coord>,
99 ) {
100 let coord = coord.into();
101 let index: Option<usize> = coord.into_index(100);
102 assert!(index.is_none(), "{index:?}");
103 }
104}