46 pub fn is_valid_coordinate(&self, x: i32, y: i32) -> bool { |
48 pub fn is_valid_coordinate(&self, x: i32, y: i32) -> bool { |
47 self.is_valid_x(x) && self.is_valid_y(y) |
49 self.is_valid_x(x) && self.is_valid_y(y) |
48 } |
50 } |
49 |
51 |
50 #[inline] |
52 #[inline] |
51 pub fn map<U: Default, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) -> U { |
53 pub fn get_mut(&mut self, y: i32, x: i32) -> Option<&mut T> { |
52 if self.is_valid_coordinate(x, y) { |
54 if self.is_valid_coordinate(x, y) { |
53 unsafe { |
55 unsafe { |
54 // hey, I just checked that coordinates are valid! |
56 // hey, I just checked that coordinates are valid! |
55 f(self.pixels.get_unchecked_mut(y as usize, x as usize)) |
57 Some(self.pixels.get_unchecked_mut(y as usize, x as usize)) |
56 } |
58 } |
57 } else { |
59 } else { |
58 U::default() |
60 None |
59 } |
61 } |
|
62 } |
|
63 |
|
64 #[inline] |
|
65 pub fn map<U: Default, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) -> U { |
|
66 self.get_mut(y, x).map(f).unwrap_or_default() |
60 } |
67 } |
61 |
68 |
62 fn apply_along_line<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>( |
69 fn apply_along_line<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>( |
63 x1: i32, |
70 x1: i32, |
64 y1: i32, |
71 y1: i32, |
144 } |
151 } |
145 |
152 |
146 result |
153 result |
147 } |
154 } |
148 |
155 |
149 pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, value: T) -> usize { |
156 pub fn fill_from_iter<I>(&mut self, i: I, value: T) -> usize |
150 integral_geometry::LinePoints::new(x1, y1, x2, y2) |
157 where I: std::iter::Iterator<Item = Point> |
151 .filter_map(|(x, y)| { |
158 { |
152 self.map(y, x, |p| { |
159 i.map(|p| self.get_mut(p.y, p.x).map(|v| *v = value)).count() |
153 *p = value; |
160 } |
154 Some(1) |
161 |
155 }) |
162 pub fn draw_line(&mut self, from: Point, to: Point, value: T) -> usize { |
156 }).count() |
163 self.fill_from_iter(LinePoints::new(from, to), value) |
157 } |
164 } |
158 |
165 |
159 pub fn fill(&mut self, start_x: i32, start_y: i32, border_value: T, fill_value: T) { |
166 pub fn fill(&mut self, start_x: i32, start_y: i32, border_value: T, fill_value: T) { |
160 debug_assert!(self.is_valid_coordinate(start_x - 1, start_y)); |
167 debug_assert!(self.is_valid_coordinate(start_x - 1, start_y)); |
161 debug_assert!(self.is_valid_coordinate(start_x, start_y)); |
168 debug_assert!(self.is_valid_coordinate(start_x, start_y)); |
347 |
354 |
348 #[test] |
355 #[test] |
349 fn fill() { |
356 fn fill() { |
350 let mut l: Land2D<u8> = Land2D::new(128, 128, 0); |
357 let mut l: Land2D<u8> = Land2D::new(128, 128, 0); |
351 |
358 |
352 l.draw_line(0, 0, 32, 96, 1); |
359 l.draw_line(Point::new(0, 0), Point::new(32, 96), 1); |
353 l.draw_line(32, 96, 64, 32, 1); |
360 l.draw_line(Point::new(32, 96), Point::new(64, 32), 1); |
354 l.draw_line(64, 32, 96, 80, 1); |
361 l.draw_line(Point::new(64, 32), Point::new(96, 80), 1); |
355 l.draw_line(96, 80, 128, 0, 1); |
362 l.draw_line(Point::new(96, 80), Point::new(128, 0), 1); |
356 |
363 |
357 l.draw_line(0, 128, 64, 96, 1); |
364 l.draw_line(Point::new(0, 128), Point::new(64, 96), 1); |
358 l.draw_line(128, 128, 64, 96, 1); |
365 l.draw_line(Point::new(128, 128), Point::new(64, 96), 1); |
359 |
366 |
360 l.fill(32, 32, 1, 2); |
367 l.fill(32, 32, 1, 2); |
361 l.fill(16, 96, 1, 3); |
368 l.fill(16, 96, 1, 3); |
362 l.fill(60, 100, 1, 4); |
369 l.fill(60, 100, 1, 4); |
363 |
370 |