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// }