1 extern crate integral_geometry; |
1 extern crate integral_geometry; |
2 extern crate vec2d; |
2 extern crate vec2d; |
3 |
3 |
4 use std::cmp; |
4 use std::cmp; |
5 |
5 |
6 use integral_geometry::{ |
6 use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, Rect, Size, SizeMask}; |
7 ArcPoints, EquidistantPoints, |
|
8 Point, Size, SizeMask, Line |
|
9 }; |
|
10 |
7 |
11 pub struct Land2D<T> { |
8 pub struct Land2D<T> { |
12 pixels: vec2d::Vec2D<T>, |
9 pixels: vec2d::Vec2D<T>, |
13 play_size: Size, |
10 play_size: Size, |
14 mask: SizeMask |
11 play_box: Rect, |
|
12 |
|
13 mask: SizeMask, |
15 } |
14 } |
16 |
15 |
17 impl<T: Copy + PartialEq> Land2D<T> { |
16 impl<T: Copy + PartialEq> Land2D<T> { |
18 pub fn new(play_size: Size, fill_value: T) -> Self { |
17 pub fn new(play_size: Size, fill_value: T) -> Self { |
19 let real_size = play_size.next_power_of_two(); |
18 let real_size = play_size.next_power_of_two(); |
|
19 let top_left = Point::new( |
|
20 (real_size.width - play_size.width / 2) as i32, |
|
21 (real_size.height - play_size.height) as i32, |
|
22 ); |
|
23 let play_box = Rect::from_size(top_left, play_size); |
20 Self { |
24 Self { |
21 play_size, |
25 play_size, |
|
26 play_box, |
22 pixels: vec2d::Vec2D::new(real_size, fill_value), |
27 pixels: vec2d::Vec2D::new(real_size, fill_value), |
23 mask: real_size.to_mask() |
28 mask: real_size.to_mask(), |
24 } |
29 } |
25 } |
30 } |
26 |
31 |
27 #[inline] |
32 #[inline] |
28 pub fn width(&self) -> usize { |
33 pub fn width(&self) -> usize { |
243 let row_index = center.y + offset.y; |
253 let row_index = center.y + offset.y; |
244 if self.is_valid_y(row_index) { |
254 if self.is_valid_y(row_index) { |
245 let from_x = cmp::max(0, center.x - offset.x) as usize; |
255 let from_x = cmp::max(0, center.x - offset.x) as usize; |
246 let to_x = cmp::min(self.width() - 1, (center.x + offset.x) as usize); |
256 let to_x = cmp::min(self.width() - 1, (center.x + offset.x) as usize); |
247 self.pixels[row_index as usize][from_x..=to_x] |
257 self.pixels[row_index as usize][from_x..=to_x] |
248 .iter_mut().for_each(|v| *v = value); |
258 .iter_mut() |
|
259 .for_each(|v| *v = value); |
249 to_x - from_x + 1 |
260 to_x - from_x + 1 |
250 } else { |
261 } else { |
251 0 |
262 0 |
252 } |
263 } |
253 } |
264 } |
254 |
265 |
255 pub fn fill_circle(&mut self, center: Point, radius: i32, value: T) -> usize { |
266 pub fn fill_circle(&mut self, center: Point, radius: i32, value: T) -> usize { |
256 let transforms = |
267 let transforms = [[0, 1, 1, 0], [0, 1, -1, 0], [1, 0, 0, 1], [1, 0, 0, -1]]; |
257 [[0, 1, 1, 0], [0, 1, -1, 0], |
268 ArcPoints::new(radius) |
258 [1, 0, 0, 1], [1, 0, 0, -1]]; |
269 .map(|vector| { |
259 ArcPoints::new(radius).map(|vector| { |
270 transforms |
260 transforms.iter().map(|m| |
271 .iter() |
261 self.fill_row(center, vector.transform(m), value) |
272 .map(|m| self.fill_row(center, vector.transform(m), value)) |
262 ).sum::<usize>() |
273 .sum::<usize>() |
263 }).sum() |
274 }).sum() |
264 } |
275 } |
265 |
276 |
266 pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize { |
277 pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize { |
267 let mut result = 0; |
278 let mut result = 0; |
268 |
279 |