changeset 14097 | e5904ead4864 |
parent 14080 | c6745a1c827a |
child 14098 | 5ade484f3351 |
14096:df0e86b2630f | 14097:e5904ead4864 |
---|---|
1 use std::cmp; |
|
2 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; |
1 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; |
3 |
2 |
4 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
3 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
5 pub struct Point { |
4 pub struct Point { |
6 pub x: i32, |
5 pub x: i32, |
38 std::cmp::max(self.x.abs(), self.y.abs()) |
37 std::cmp::max(self.x.abs(), self.y.abs()) |
39 } |
38 } |
40 |
39 |
41 #[inline] |
40 #[inline] |
42 pub fn transform(self, matrix: &[i32; 4]) -> Self { |
41 pub fn transform(self, matrix: &[i32; 4]) -> Self { |
43 Point::new(matrix[0] * self.x + matrix[1] * self.y, |
42 Point::new( |
44 matrix[2] * self.x + matrix[3] * self.y) |
43 matrix[0] * self.x + matrix[1] * self.y, |
44 matrix[2] * self.x + matrix[3] * self.y, |
|
45 ) |
|
45 } |
46 } |
46 } |
47 } |
47 |
48 |
48 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
49 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
49 pub struct Size { |
50 pub struct Size { |
57 Size { width, height } |
58 Size { width, height } |
58 } |
59 } |
59 |
60 |
60 #[inline] |
61 #[inline] |
61 pub fn square(size: usize) -> Self { |
62 pub fn square(size: usize) -> Self { |
62 Size { width: size, height: size } |
63 Size { |
64 width: size, |
|
65 height: size, |
|
66 } |
|
63 } |
67 } |
64 |
68 |
65 #[inline] |
69 #[inline] |
66 pub fn area(&self) -> usize { |
70 pub fn area(&self) -> usize { |
67 self.width * self.height |
71 self.width * self.height |
79 |
83 |
80 #[inline] |
84 #[inline] |
81 pub fn next_power_of_two(&self) -> Self { |
85 pub fn next_power_of_two(&self) -> Self { |
82 Self { |
86 Self { |
83 width: self.width.next_power_of_two(), |
87 width: self.width.next_power_of_two(), |
84 height: self.height.next_power_of_two() |
88 height: self.height.next_power_of_two(), |
85 } |
89 } |
86 } |
90 } |
87 |
91 |
88 #[inline] |
92 #[inline] |
89 pub fn to_mask(&self) -> SizeMask { |
93 pub fn to_mask(&self) -> SizeMask { |
93 pub fn to_grid_index(&self) -> GridIndex { |
97 pub fn to_grid_index(&self) -> GridIndex { |
94 GridIndex::new(*self) |
98 GridIndex::new(*self) |
95 } |
99 } |
96 } |
100 } |
97 |
101 |
98 pub struct SizeMask{ size: Size } |
102 pub struct SizeMask { |
103 size: Size, |
|
104 } |
|
99 |
105 |
100 impl SizeMask { |
106 impl SizeMask { |
101 #[inline] |
107 #[inline] |
102 pub fn new(size: Size) -> Self { |
108 pub fn new(size: Size) -> Self { |
103 assert!(size.is_power_of_two()); |
109 assert!(size.is_power_of_two()); |
104 let size = Size { |
110 let size = Size { |
105 width: !(size.width - 1), |
111 width: !(size.width - 1), |
106 height: !(size.height - 1) |
112 height: !(size.height - 1), |
107 }; |
113 }; |
108 Self { size } |
114 Self { size } |
109 } |
115 } |
110 |
116 |
111 #[inline] |
117 #[inline] |
122 pub fn contains(&self, point: Point) -> bool { |
128 pub fn contains(&self, point: Point) -> bool { |
123 self.contains_x(point.x as usize) && self.contains_y(point.y as usize) |
129 self.contains_x(point.x as usize) && self.contains_y(point.y as usize) |
124 } |
130 } |
125 } |
131 } |
126 |
132 |
127 pub struct GridIndex{ shift: Point } |
133 pub struct GridIndex { |
134 shift: Point, |
|
135 } |
|
128 |
136 |
129 impl GridIndex { |
137 impl GridIndex { |
130 pub fn new(size: Size) -> Self { |
138 pub fn new(size: Size) -> Self { |
131 assert!(size.is_power_of_two()); |
139 assert!(size.is_power_of_two()); |
132 let shift = Point::new(size.width.trailing_zeros() as i32, |
140 let shift = Point::new( |
133 size.height.trailing_zeros() as i32); |
141 size.width.trailing_zeros() as i32, |
142 size.height.trailing_zeros() as i32, |
|
143 ); |
|
134 Self { shift } |
144 Self { shift } |
135 } |
145 } |
136 |
146 |
137 pub fn map(&self, position: Point) -> Point { |
147 pub fn map(&self, position: Point) -> Point { |
138 Point::new(position.x >> self.shift.x, |
148 Point::new(position.x >> self.shift.x, position.y >> self.shift.y) |
139 position.y >> self.shift.y) |
|
140 } |
149 } |
141 } |
150 } |
142 |
151 |
143 macro_rules! bin_op_impl { |
152 macro_rules! bin_op_impl { |
144 ($op: ty, $name: tt) => { |
153 ($op: ty, $name: tt) => { |
183 } |
192 } |
184 |
193 |
185 impl Rect { |
194 impl Rect { |
186 #[inline] |
195 #[inline] |
187 pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self { |
196 pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self { |
188 Self { x, y, width, height } |
197 Self { |
198 x, |
|
199 y, |
|
200 width, |
|
201 height, |
|
202 } |
|
189 } |
203 } |
190 |
204 |
191 #[inline] |
205 #[inline] |
192 pub fn size(&self) -> Size { |
206 pub fn size(&self) -> Size { |
193 Size::new(self.width as usize, self.height as usize) |
207 Size::new(self.width as usize, self.height as usize) |
197 pub fn area(&self) -> usize { |
211 pub fn area(&self) -> usize { |
198 self.size().area() |
212 self.size().area() |
199 } |
213 } |
200 } |
214 } |
201 |
215 |
216 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
217 pub struct Line { |
|
218 pub start: Point, |
|
219 pub end: Point, |
|
220 } |
|
221 |
|
222 impl Line { |
|
223 #[inline] |
|
224 pub fn new(start: Point, end: Point) -> Self { |
|
225 Self { start, end } |
|
226 } |
|
227 |
|
228 #[inline] |
|
229 pub fn zero() -> Self { |
|
230 Self::new(Point::zero(), Point::zero()) |
|
231 } |
|
232 } |
|
233 |
|
234 impl IntoIterator for Line { |
|
235 type Item = Point; |
|
236 type IntoIter = LinePoints; |
|
237 |
|
238 fn into_iter(self) -> Self::IntoIter { |
|
239 LinePoints::new(self) |
|
240 } |
|
241 } |
|
202 |
242 |
203 pub struct LinePoints { |
243 pub struct LinePoints { |
204 accumulator: Point, |
244 accumulator: Point, |
205 direction: Point, |
245 direction: Point, |
206 sign: Point, |
246 sign: Point, |
208 total_steps: i32, |
248 total_steps: i32, |
209 step: i32, |
249 step: i32, |
210 } |
250 } |
211 |
251 |
212 impl LinePoints { |
252 impl LinePoints { |
213 pub fn new(from: Point, to: Point) -> Self { |
253 pub fn new(line: Line) -> Self { |
214 let dir = to - from; |
254 let dir = line.end - line.start; |
215 |
255 |
216 Self { |
256 Self { |
217 accumulator: Point::zero(), |
257 accumulator: Point::zero(), |
218 direction: dir.abs(), |
258 direction: dir.abs(), |
219 sign: dir.signum(), |
259 sign: dir.signum(), |
220 current: from, |
260 current: line.start, |
221 total_steps: dir.max_norm(), |
261 total_steps: dir.max_norm(), |
222 step: 0, |
262 step: 0, |
223 } |
263 } |
224 } |
264 } |
225 } |
265 } |
335 coords.iter().map(|(x, y)| Point::new(*x, *y)).collect() |
375 coords.iter().map(|(x, y)| Point::new(*x, *y)).collect() |
336 } |
376 } |
337 |
377 |
338 #[test] |
378 #[test] |
339 fn line_basic() { |
379 fn line_basic() { |
340 let line = LinePoints::new(Point::new(0, 0), Point::new(3, 3)); |
380 let line = Line::new(Point::new(0, 0), Point::new(3, 3)).into_iter(); |
341 let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]); |
381 let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]); |
342 |
382 |
343 for (&a, b) in v.iter().zip(line) { |
383 for (&a, b) in v.iter().zip(line) { |
344 assert_eq!(a, b); |
384 assert_eq!(a, b); |
345 } |
385 } |
346 } |
386 } |
347 |
387 |
348 #[test] |
388 #[test] |
349 fn line_skewed() { |
389 fn line_skewed() { |
350 let line = LinePoints::new(Point::new(0, 0), Point::new(5, -7)); |
390 let line = Line::new(Point::new(0, 0), Point::new(5, -7)).into_iter(); |
351 let v = get_points(&[ |
391 let v = get_points(&[ |
352 (0, 0), |
392 (0, 0), |
353 (1, -1), |
393 (1, -1), |
354 (2, -2), |
394 (2, -2), |
355 (2, -3), |
395 (2, -3), |