lk_math/line_iterator.rs
1use super::vector::Vector;
2
3pub struct LineIterator<const B: bool, const C: usize> {
4 step_options: Vec<Vector<C, i32>>,
5 at: Vector<C, i32>,
6 end: Vector<C, i32>,
7}
8
9impl<const B: bool, const C: usize> LineIterator<B, C> {
10 pub fn new(start: Vector<C, i32>, end: Vector<C, i32>) -> Self {
11 LineIterator {
12 at: start,
13 end,
14 step_options: vec![],
15 }
16 }
17}
18impl<const B: bool, const C: usize> Iterator for LineIterator<B, C> {
19 type Item = Vector<C, i32>;
20
21 fn next(&mut self) -> Option<Self::Item> {
22 if self.step_options.is_empty() {
23 if self.at == self.end {
24 self.step_options.push(Vector::all(0));
25 if B {
26 return Some(self.at);
27 } else {
28 return None;
29 }
30 }
31
32 let mut dir = self.end - self.at;
33 for i in 0..C {
34 if dir.values[i] > 0 {
35 dir.values[i] = 1;
36 }
37 if dir.values[i] < 0 {
38 dir.values[i] = -1;
39 }
40 }
41
42 for i in 0..C {
43 if dir.values[i] != 0 {
44 #[allow(clippy::unnecessary_to_owned)]
45 for mut opt in self.step_options.to_vec() {
46 debug_assert_eq!(opt.values[i], 0);
47 opt.values[i] = dir.values[i];
48 self.step_options.push(opt);
49 }
50
51 let mut values = [0; C];
52 values[i] = dir.values[i];
53 self.step_options.push(Vector::new(values));
54 }
55 }
56
57 Some(self.at)
58 } else if self.at != self.end {
59 let delta = self.end - self.at;
60 let best_step = *self
61 .step_options
62 .iter()
63 .max_by_key(|step| delta.inner(**step))
64 .unwrap();
65 self.at += best_step;
66
67 if !B && self.at == self.end {
68 return None;
69 }
70
71 Some(self.at)
72 } else {
73 None
74 }
75 }
76}
77
78// pub type LineIterator2 = LineIterator<2>;
79// pub type LineIterator3 = LineIterator<3>;
80
81// impl<const C: usize> Iterator for LineIterator<C> {
82// type Item = Vector<C, i32>;
83//
84// fn next(&mut self) -> Option<Self::Item> {
85// if self.step_options.is_empty() {
86// let dir = self.end - self.at;
87// match dir.x().cmp(&0) {
88// std::cmp::Ordering::Less => {
89// self.step_options.push(V2::from_xy(-1, 0));
90// match dir.y().cmp(&0) {
91// std::cmp::Ordering::Less => {
92// self.step_options.push(V2::from_xy(0, -1));
93// self.step_options.push(V2::from_xy(-1, -1));
94// }
95// std::cmp::Ordering::Equal => (),
96// std::cmp::Ordering::Greater => {
97// self.step_options.push(V2::from_xy(0, 1));
98// self.step_options.push(V2::from_xy(-1, 1));
99// }
100// };
101// }
102// std::cmp::Ordering::Equal => {
103// match dir.y().cmp(&0) {
104// std::cmp::Ordering::Less => self.step_options.push(V2::from_xy(0, -1)),
105// std::cmp::Ordering::Equal => (),
106// std::cmp::Ordering::Greater => self.step_options.push(V2::from_xy(0, 1)),
107// };
108// }
109// std::cmp::Ordering::Greater => {
110// self.step_options.push(V2::from_xy(1, 0));
111// match dir.y().cmp(&0) {
112// std::cmp::Ordering::Less => {
113// self.step_options.push(V2::from_xy(0, -1));
114// self.step_options.push(V2::from_xy(1, -1));
115// }
116// std::cmp::Ordering::Equal => (),
117// std::cmp::Ordering::Greater => {
118// self.step_options.push(V2::from_xy(0, 1));
119// self.step_options.push(V2::from_xy(1, 1));
120// }
121// };
122// }
123// }
124//
125// Some(self.at)
126// } else if self.at != self.end {
127// let delta = self.end - self.at;
128// let best_step = *self
129// .step_options
130// .iter()
131// .max_by_key(|step| delta.inner(**step))
132// .unwrap();
133// self.at += best_step;
134//
135// Some(self.at)
136// } else {
137// None
138// }
139// }
140// }