bracket_algorithm_traits/
algorithm3d.rs1use crate::prelude::BaseMap;
17use bracket_geometry::prelude::Point3;
18
19pub trait Algorithm3D: BaseMap {
22 #[allow(clippy::cast_sign_loss)]
24 fn point3d_to_index(&self, pt: Point3) -> usize {
25 let bounds = self.dimensions();
26 ((pt.z * (bounds.x * bounds.y)) + (pt.y * bounds.x) + pt.x) as usize
27 }
28
29 #[allow(clippy::cast_possible_wrap)]
31 #[allow(clippy::cast_possible_truncation)]
32 fn index_to_point3d(&self, idx: usize) -> Point3 {
33 let mut my_idx = idx as i32;
34 let bounds = self.dimensions();
35 let z = my_idx / (bounds.x * bounds.y);
36 my_idx -= z * bounds.x * bounds.y;
37
38 let y = my_idx / bounds.x;
39 my_idx -= y * bounds.x;
40
41 let x = my_idx;
42 Point3::new(x, y, z)
43 }
44
45 fn dimensions(&self) -> Point3 {
47 panic!("You must either define the dimensions function (trait Algorithm3D) on your map, or define the various point3d_to_index and index_to_point3d functions.");
48 }
49
50 fn in_bounds(&self, pos: Point3) -> bool {
54 let bounds = self.dimensions();
55 pos.x >= 0
56 && pos.x < bounds.x
57 && pos.y >= 0
58 && pos.y < bounds.y
59 && pos.z >= 0
60 && pos.z < bounds.z
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use crate::prelude::{Algorithm3D, BaseMap};
67 use bracket_geometry::prelude::Point3;
68
69 #[test]
70 #[should_panic]
72 fn test_unimplemented_dimensions() {
73 struct TestMap {}
74 impl BaseMap for TestMap {}
75 impl Algorithm3D for TestMap {}
76
77 let map = TestMap {};
78 assert!(map.in_bounds(Point3::new(1, 1, 1)));
79 }
80
81 #[test]
82 fn test_in_bounds() {
83 struct TestMap {}
84 impl BaseMap for TestMap {}
85 impl Algorithm3D for TestMap {
86 fn dimensions(&self) -> Point3 {
87 Point3::new(2, 2, 2)
88 }
89 }
90
91 let map = TestMap {};
92 assert!(map.in_bounds(Point3::new(0, 0, 0)));
93 assert!(map.in_bounds(Point3::new(1, 1, 1)));
94 assert!(!map.in_bounds(Point3::new(3, 3, 3)));
95 }
96
97 #[test]
98 fn test_point3d_to_index() {
99 struct TestMap {}
100 impl BaseMap for TestMap {}
101 impl Algorithm3D for TestMap {
102 fn dimensions(&self) -> Point3 {
103 Point3::new(10, 10, 10)
104 }
105 }
106
107 let map = TestMap {};
108 assert!(map.point3d_to_index(Point3::new(0, 0, 0)) == 0);
109 assert!(map.point3d_to_index(Point3::new(1, 0, 0)) == 1);
110 assert!(map.point3d_to_index(Point3::new(0, 1, 0)) == 10);
111 assert!(map.point3d_to_index(Point3::new(9, 9, 0)) == 99);
112 assert!(map.point3d_to_index(Point3::new(9, 9, 9)) == 999);
113 }
114
115 #[test]
116 fn test_index_to_point3d() {
117 struct TestMap {}
118 impl BaseMap for TestMap {}
119 impl Algorithm3D for TestMap {
120 fn dimensions(&self) -> Point3 {
121 Point3::new(10, 10, 10)
122 }
123 }
124
125 let map = TestMap {};
126 let mut x = 0;
127 let mut y = 0;
128 let mut z: i32 = 0;
129 for i in 0..1000 {
130 assert!(map.index_to_point3d(i) == Point3::new(x, y, z));
131
132 x += 1;
133 if x > 9 {
134 x = 0;
135 y += 1;
136 }
137 if y > 9 {
138 y = 0;
139 z += 1;
140 }
141 }
142 }
143}