78 } |
88 } |
79 |
89 |
80 self.map(y, x, |p| *p = value); |
90 self.map(y, x, |p| *p = value); |
81 } |
91 } |
82 } |
92 } |
|
93 |
|
94 pub fn fill(&mut self, start_x: i32, start_y: i32, border_value: T, fill_value: T) { |
|
95 debug_assert!(self.is_valid_coordinate(start_x - 1, start_y)); |
|
96 debug_assert!(self.is_valid_coordinate(start_x, start_y)); |
|
97 |
|
98 let mut stack: Vec<(usize, usize, usize, isize)> = Vec::new(); |
|
99 fn push<T: Default + Copy + PartialEq>( |
|
100 land: &Land2D<T>, |
|
101 stack: &mut Vec<(usize, usize, usize, isize)>, |
|
102 xl: usize, |
|
103 xr: usize, |
|
104 y: usize, |
|
105 dir: isize, |
|
106 ) { |
|
107 let yd = y as isize + dir; |
|
108 |
|
109 if land.is_valid_coordinate(0, yd as i32) { |
|
110 stack.push((xl, xr, yd as usize, dir)); |
|
111 } |
|
112 }; |
|
113 |
|
114 let start_x_l = (start_x - 1) as usize; |
|
115 let start_x_r = start_x as usize; |
|
116 push(self, &mut stack, start_x_l, start_x_r, start_y as usize, -1); |
|
117 push(self, &mut stack, start_x_l, start_x_r, start_y as usize, 1); |
|
118 |
|
119 loop { |
|
120 let a = stack.pop(); |
|
121 match a { |
|
122 None => return, |
|
123 Some(a) => { |
|
124 let (mut xl, mut xr, y, mut dir) = a; |
|
125 |
|
126 while xl > 0 && self |
|
127 .pixels |
|
128 .get(y, xl) |
|
129 .map_or(false, |v| *v != border_value && *v != fill_value) |
|
130 { |
|
131 xl -= 1; |
|
132 } |
|
133 |
|
134 while xr < self.width() - 1 && self |
|
135 .pixels |
|
136 .get(y, xr) |
|
137 .map_or(false, |v| *v != border_value && *v != fill_value) |
|
138 { |
|
139 xr += 1; |
|
140 } |
|
141 |
|
142 while xl < xr { |
|
143 while xl <= xr |
|
144 && (self.pixels[y][xl] == border_value |
|
145 || self.pixels[y][xl] == fill_value) |
|
146 { |
|
147 xl += 1; |
|
148 } |
|
149 |
|
150 let mut x = xl; |
|
151 |
|
152 while xl <= xr |
|
153 && (self.pixels[y][xl] != border_value |
|
154 && self.pixels[y][xl] != fill_value) |
|
155 { |
|
156 self.pixels[y][xl] = fill_value; |
|
157 |
|
158 xl += 1; |
|
159 } |
|
160 |
|
161 if x < xl { |
|
162 push(self, &mut stack, x, xl - 1, y, dir); |
|
163 push(self, &mut stack, x, xl - 1, y, -dir); |
|
164 } |
|
165 } |
|
166 } |
|
167 } |
|
168 } |
|
169 } |
83 } |
170 } |
84 |
171 |
85 #[cfg(test)] |
172 #[cfg(test)] |
86 mod tests { |
173 mod tests { |
87 use super::*; |
174 use super::*; |
88 |
175 |
89 #[test] |
176 #[test] |
90 fn basics() { |
177 fn basics() { |
91 let l:Land2D<u8> = Land2D::new(32, 64); |
178 let l: Land2D<u8> = Land2D::new(32, 64); |
92 |
179 |
93 assert!(l.is_valid_coordinate(0, 0)); |
180 assert!(l.is_valid_coordinate(0, 0)); |
94 assert!(!l.is_valid_coordinate(-1, -1)); |
181 assert!(!l.is_valid_coordinate(-1, -1)); |
95 |
182 |
96 assert!(l.is_valid_coordinate(31, 63)); |
183 assert!(l.is_valid_coordinate(31, 63)); |
97 assert!(!l.is_valid_coordinate(32, 63)); |
184 assert!(!l.is_valid_coordinate(32, 63)); |
98 assert!(!l.is_valid_coordinate(31, 64)); |
185 assert!(!l.is_valid_coordinate(31, 64)); |
99 } |
186 } |
100 |
187 |
|
188 #[test] |
|
189 fn fill() { |
|
190 let mut l: Land2D<u8> = Land2D::new(128, 128); |
|
191 |
|
192 l.draw_line(0, 0, 32, 96, 1); |
|
193 l.draw_line(32, 96, 64, 32, 1); |
|
194 l.draw_line(64, 32, 96, 80, 1); |
|
195 l.draw_line(96, 80, 128, 0, 1); |
|
196 |
|
197 l.draw_line(0, 128, 64, 96, 1); |
|
198 l.draw_line(128, 128, 64, 96, 1); |
|
199 |
|
200 l.fill(32, 32, 1, 2); |
|
201 l.fill(16, 96, 1, 3); |
|
202 l.fill(60, 100, 1, 4); |
|
203 |
|
204 assert_eq!(l.pixels[0][0], 1); |
|
205 assert_eq!(l.pixels[96][64], 1); |
|
206 |
|
207 assert_eq!(l.pixels[40][32], 2); |
|
208 assert_eq!(l.pixels[40][96], 2); |
|
209 assert_eq!(l.pixels[5][0], 3); |
|
210 assert_eq!(l.pixels[120][0], 3); |
|
211 assert_eq!(l.pixels[5][127], 3); |
|
212 assert_eq!(l.pixels[120][127], 3); |
|
213 assert_eq!(l.pixels[35][64], 3); |
|
214 assert_eq!(l.pixels[120][20], 4); |
|
215 assert_eq!(l.pixels[120][100], 4); |
|
216 assert_eq!(l.pixels[100][64], 4); |
|
217 } |
101 } |
218 } |