|
1 use super::transform::RotationTransform; |
|
2 use std::rc::Rc; |
1 use vec2d::Vec2D; |
3 use vec2d::Vec2D; |
2 use std::rc::Rc; |
|
3 use integral_geometry::Size; |
|
4 |
4 |
5 pub struct TileImage<T> { |
5 #[derive(PartialEq, Clone)] |
6 image: Rc<Vec2D<T>>, |
6 pub struct Edge<I: PartialEq + Clone> { |
7 flip: bool, |
7 id: I, |
8 mirror: bool, |
8 symmetrical: bool, |
|
9 reverse: bool, |
9 } |
10 } |
10 |
11 |
11 impl<T: Copy> TileImage<T> { |
12 impl<I: PartialEq + Clone> Edge<I> { |
12 pub fn new(image: Vec2D<T>) -> Self { |
13 pub fn new(id: I, symmetrical: bool) -> Self { |
|
14 Self { |
|
15 id, |
|
16 symmetrical, |
|
17 reverse: false, |
|
18 } |
|
19 } |
|
20 |
|
21 pub fn reversed(&self) -> Self { |
|
22 Self { |
|
23 id: self.id.clone(), |
|
24 symmetrical: self.symmetrical, |
|
25 reverse: !self.symmetrical && !self.reverse, |
|
26 } |
|
27 } |
|
28 } |
|
29 |
|
30 #[derive(Clone)] |
|
31 pub struct TileImage<T, I: PartialEq + Clone> { |
|
32 image: Rc<Vec2D<T>>, |
|
33 transform: RotationTransform, |
|
34 top: Edge<I>, |
|
35 right: Edge<I>, |
|
36 bottom: Edge<I>, |
|
37 left: Edge<I>, |
|
38 } |
|
39 |
|
40 impl<T: Copy, I: PartialEq + Clone> TileImage<T, I> { |
|
41 pub fn new( |
|
42 image: Vec2D<T>, |
|
43 top: Edge<I>, |
|
44 right: Edge<I>, |
|
45 bottom: Edge<I>, |
|
46 left: Edge<I>, |
|
47 ) -> Self { |
13 Self { |
48 Self { |
14 image: Rc::new(image), |
49 image: Rc::new(image), |
15 flip: false, |
50 transform: RotationTransform::default(), |
16 mirror: false, |
51 top, |
|
52 right, |
|
53 bottom, |
|
54 left, |
17 } |
55 } |
18 } |
56 } |
19 |
57 |
20 pub fn mirrored(&self) -> Self { |
58 pub fn mirrored(&self) -> Self { |
21 Self { |
59 Self { |
22 image: self.image.clone(), |
60 image: self.image.clone(), |
23 flip: self.flip, |
61 transform: self.transform.mirror(), |
24 mirror: !self.mirror, |
62 top: self.top.reversed(), |
|
63 right: self.left.reversed(), |
|
64 bottom: self.bottom.reversed(), |
|
65 left: self.right.reversed(), |
25 } |
66 } |
26 } |
67 } |
27 |
68 |
28 pub fn flipped(&self) -> Self { |
69 pub fn flipped(&self) -> Self { |
29 Self { |
70 Self { |
30 image: self.image.clone(), |
71 image: self.image.clone(), |
31 flip: !self.flip, |
72 transform: self.transform.flip(), |
32 mirror: self.mirror, |
73 top: self.bottom.reversed(), |
|
74 right: self.right.reversed(), |
|
75 bottom: self.top.reversed(), |
|
76 left: self.left.reversed(), |
33 } |
77 } |
34 } |
78 } |
35 |
79 |
36 pub fn split(&self, rows: usize, columns: usize) -> Vec<TileImage<T>> { |
80 pub fn rotated90(&self) -> Self { |
37 let mut result = Vec::new(); |
81 Self { |
38 let self_image = self.image.as_ref(); |
82 image: self.image.clone(), |
39 let (result_width, result_height) = (self_image.width() / columns, self.image.height() / rows); |
83 transform: self.transform.rotate90(), |
|
84 top: self.left.clone(), |
|
85 right: self.top.clone(), |
|
86 bottom: self.right.clone(), |
|
87 left: self.bottom.clone(), |
|
88 } |
|
89 } |
40 |
90 |
41 for row in 0..rows { |
91 pub fn rotated180(&self) -> Self { |
42 for column in 0..columns { |
92 Self { |
43 let mut tile_pixels = Vec::new(); |
93 image: self.image.clone(), |
|
94 transform: self.transform.rotate90(), |
|
95 top: self.bottom.clone(), |
|
96 right: self.left.clone(), |
|
97 bottom: self.top.clone(), |
|
98 left: self.right.clone(), |
|
99 } |
|
100 } |
44 |
101 |
45 for out_row in 0..result_height { |
102 pub fn rotated270(&self) -> Self { |
46 tile_pixels.push(self_image[row * result_height + out_row][column*result_width..(column+1)*result_width].iter()); |
103 Self { |
47 } |
104 image: self.image.clone(), |
48 |
105 transform: self.transform.rotate90(), |
49 let tile_image = Vec2D::from_iter(tile_pixels.into_iter().flatten().map(|p| *p), &Size::new(result_width, result_height)); |
106 top: self.left.clone(), |
50 |
107 right: self.top.clone(), |
51 result.push(TileImage::new(tile_image.expect("correct calculation of tile dimensions"))); |
108 bottom: self.right.clone(), |
52 } |
109 left: self.bottom.clone(), |
53 } |
110 } |
54 |
|
55 result |
|
56 } |
111 } |
57 } |
112 } |
58 |
113 |
59 #[cfg(test)] |
114 #[cfg(test)] |
60 mod tests { |
115 mod tests {} |
61 use super::TileImage; |
|
62 use integral_geometry::Size; |
|
63 use vec2d::Vec2D; |
|
64 |
|
65 #[test] |
|
66 fn test_split() { |
|
67 let size = Size::new(6, 4); |
|
68 let sample_data = Vec2D::from_iter((0..24).into_iter(), &size); |
|
69 |
|
70 assert!(sample_data.is_some()); |
|
71 |
|
72 let sample_data = sample_data.unwrap(); |
|
73 let big_tile = TileImage::new(sample_data); |
|
74 let subtiles = big_tile.split(2, 2); |
|
75 |
|
76 assert_eq!(subtiles.len(), 4); |
|
77 } |
|
78 } |
|