|
1 extern crate vec2d; |
|
2 |
|
3 use std::cmp; |
|
4 |
|
5 pub struct Land2D<T> { |
|
6 pixels: vec2d::Vec2D<T>, |
|
7 width_mask: usize, |
|
8 height_mask: usize, |
|
9 } |
|
10 |
|
11 impl<T: Default + Copy> Land2D<T> { |
|
12 pub fn new(width: usize, height: usize) -> Self { |
|
13 assert!(width.is_power_of_two()); |
|
14 assert!(height.is_power_of_two()); |
|
15 |
|
16 Self { |
|
17 pixels: vec2d::Vec2D::new(width, height, T::default()), |
|
18 width_mask: !(width - 1), |
|
19 height_mask: !(height - 1), |
|
20 } |
|
21 } |
|
22 |
|
23 #[inline] |
|
24 fn is_valid_coordinate(&self, x: i32, y: i32) -> bool { |
|
25 (x as usize & self.width_mask) == 0 && (y as usize & self.height_mask) == 0 |
|
26 } |
|
27 |
|
28 #[inline] |
|
29 pub fn map<U, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) { |
|
30 if self.is_valid_coordinate(x, y) { |
|
31 self.pixels.get_mut(y as usize, x as usize).map(f); |
|
32 } |
|
33 } |
|
34 |
|
35 pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, value: T) { |
|
36 let mut e_x: i32 = 0; |
|
37 let mut e_y: i32 = 0; |
|
38 let mut d_x: i32 = x2 - x1; |
|
39 let mut d_y: i32 = y2 - y1; |
|
40 |
|
41 let s_x: i32; |
|
42 let s_y: i32; |
|
43 |
|
44 if d_x > 0 { |
|
45 s_x = 1; |
|
46 } else if d_x < 0 { |
|
47 s_x = -1; |
|
48 d_x = -d_x; |
|
49 } else { |
|
50 s_x = d_x; |
|
51 } |
|
52 |
|
53 if d_y > 0 { |
|
54 s_y = 1; |
|
55 } else if d_y < 0 { |
|
56 s_y = -1; |
|
57 d_y = -d_y; |
|
58 } else { |
|
59 s_y = d_y; |
|
60 } |
|
61 |
|
62 let d = cmp::max(d_x, d_y); |
|
63 |
|
64 let mut x = x1; |
|
65 let mut y = y1; |
|
66 |
|
67 for _i in 0..=d { |
|
68 e_x += d_x; |
|
69 e_y += d_y; |
|
70 |
|
71 if e_x > d { |
|
72 e_x -= d; |
|
73 x += s_x; |
|
74 } |
|
75 if e_y > d { |
|
76 e_y -= d; |
|
77 y += s_y; |
|
78 } |
|
79 |
|
80 self.map(y, x, |p| *p = value); |
|
81 } |
|
82 } |
|
83 } |
|
84 |
|
85 #[cfg(test)] |
|
86 mod tests { |
|
87 use super::*; |
|
88 |
|
89 #[test] |
|
90 fn basics() { |
|
91 let l:Land2D<u8> = Land2D::new(32, 64); |
|
92 |
|
93 assert!(l.is_valid_coordinate(0, 0)); |
|
94 assert!(!l.is_valid_coordinate(-1, -1)); |
|
95 |
|
96 assert!(l.is_valid_coordinate(31, 63)); |
|
97 assert!(!l.is_valid_coordinate(32, 63)); |
|
98 assert!(!l.is_valid_coordinate(31, 64)); |
|
99 } |
|
100 |
|
101 } |