Skip to main content

grid_map/loc/
neighbor_square.rs

1use crate::{Dim, Dir, Loc, Scale};
2
3impl Loc {
4    //! Neighbors
5
6    /// Gets the neighbor in the `dir`, or `None` if outside the `dims`.
7    pub fn neighbor(self, dir: Dir, dims: Dim) -> Option<Loc> {
8        match dir {
9            Dir::North => {
10                if self.y > 0 {
11                    Some(Loc::new(self.x, self.y - 1))
12                } else {
13                    None
14                }
15            }
16            Dir::East => {
17                let x: Scale = self.x + 1;
18                if x < dims.w {
19                    Some(Loc::new(x, self.y))
20                } else {
21                    None
22                }
23            }
24            Dir::South => {
25                let y: Scale = self.y + 1;
26                if y < dims.h {
27                    Some(Loc::new(self.x, y))
28                } else {
29                    None
30                }
31            }
32            Dir::West => {
33                if self.x > 0 {
34                    Some(Loc::new(self.x - 1, self.y))
35                } else {
36                    None
37                }
38            }
39        }
40    }
41
42    /// Gets the neighbor in the `dir`.
43    pub fn neighbor_unchecked(self, dir: Dir) -> Loc {
44        match dir {
45            Dir::North => Loc::new(self.x, self.y - 1),
46            Dir::East => Loc::new(self.x + 1, self.y),
47            Dir::South => Loc::new(self.x, self.y + 1),
48            Dir::West => Loc::new(self.x - 1, self.y),
49        }
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use crate::{Dim, Dir, Loc};
56
57    #[test]
58    fn neighbor_center() {
59        let dims: Dim = Dim::new(3, 3);
60        let loc: Loc = Loc::new(1, 1);
61        assert_eq!(loc.neighbor(Dir::North, dims), Some(Loc::new(1, 0)));
62        assert_eq!(loc.neighbor(Dir::East, dims), Some(Loc::new(2, 1)));
63        assert_eq!(loc.neighbor(Dir::South, dims), Some(Loc::new(1, 2)));
64        assert_eq!(loc.neighbor(Dir::West, dims), Some(Loc::new(0, 1)));
65    }
66
67    #[test]
68    fn neighbor_top_left_corner() {
69        let dims: Dim = Dim::new(3, 3);
70        let loc: Loc = Loc::new(0, 0);
71        assert_eq!(loc.neighbor(Dir::North, dims), None);
72        assert_eq!(loc.neighbor(Dir::West, dims), None);
73        assert_eq!(loc.neighbor(Dir::East, dims), Some(Loc::new(1, 0)));
74        assert_eq!(loc.neighbor(Dir::South, dims), Some(Loc::new(0, 1)));
75    }
76
77    #[test]
78    fn neighbor_bottom_right_corner() {
79        let dims: Dim = Dim::new(3, 3);
80        let loc: Loc = Loc::new(2, 2);
81        assert_eq!(loc.neighbor(Dir::East, dims), None);
82        assert_eq!(loc.neighbor(Dir::South, dims), None);
83        assert_eq!(loc.neighbor(Dir::North, dims), Some(Loc::new(2, 1)));
84        assert_eq!(loc.neighbor(Dir::West, dims), Some(Loc::new(1, 2)));
85    }
86
87    #[test]
88    fn neighbor_unchecked_matches_neighbor() {
89        let dims: Dim = Dim::new(5, 5);
90        let loc: Loc = Loc::new(2, 2);
91        for dir in Dir::ALL {
92            assert_eq!(
93                loc.neighbor(dir, dims).unwrap(),
94                loc.neighbor_unchecked(dir),
95            );
96        }
97    }
98
99    #[test]
100    fn neighbor_opposite_roundtrip() {
101        let loc: Loc = Loc::new(2, 2);
102        for dir in Dir::ALL {
103            let n: Loc = loc.neighbor_unchecked(dir);
104            assert_eq!(n.neighbor_unchecked(dir.opposite()), loc);
105        }
106    }
107}