33 pub fn is_compatible(&self, other: &Self) -> bool { |
33 pub fn is_compatible(&self, other: &Self) -> bool { |
34 self.id == other.id && ((self.reverse != other.reverse) || self.symmetrical) |
34 self.id == other.id && ((self.reverse != other.reverse) || self.symmetrical) |
35 } |
35 } |
36 } |
36 } |
37 |
37 |
|
38 impl Edge<String> { |
|
39 pub fn name(&self) -> String { |
|
40 if self.reverse { |
|
41 self.id.chars().rev().collect() |
|
42 } else { |
|
43 self.id.clone() |
|
44 } |
|
45 } |
|
46 } |
|
47 |
|
48 #[derive(PartialEq, Clone, Debug)] |
|
49 pub struct EdgeSet<I: PartialEq + Clone>([Edge<I>; 4]); |
|
50 |
|
51 impl<I: PartialEq + Clone> EdgeSet<I> { |
|
52 pub fn new(edge_set: [Edge<I>; 4]) -> Self { |
|
53 Self(edge_set) |
|
54 } |
|
55 |
|
56 pub fn top(&self) -> &Edge<I> { |
|
57 &self.0[0] |
|
58 } |
|
59 |
|
60 pub fn right(&self) -> &Edge<I> { |
|
61 &self.0[1] |
|
62 } |
|
63 |
|
64 pub fn bottom(&self) -> &Edge<I> { |
|
65 &self.0[2] |
|
66 } |
|
67 |
|
68 pub fn left(&self) -> &Edge<I> { |
|
69 &self.0[3] |
|
70 } |
|
71 |
|
72 pub fn mirrored(&self) -> Self { |
|
73 Self([ |
|
74 self.0[0].reversed(), |
|
75 self.0[3].reversed(), |
|
76 self.0[2].reversed(), |
|
77 self.0[1].reversed(), |
|
78 ]) |
|
79 } |
|
80 |
|
81 pub fn flipped(&self) -> Self { |
|
82 Self([ |
|
83 self.0[2].reversed(), |
|
84 self.0[1].reversed(), |
|
85 self.0[0].reversed(), |
|
86 self.0[3].reversed(), |
|
87 ]) |
|
88 } |
|
89 |
|
90 pub fn rotated90(&self) -> Self { |
|
91 Self([ |
|
92 self.0[3].clone(), |
|
93 self.0[0].clone(), |
|
94 self.0[1].clone(), |
|
95 self.0[2].clone(), |
|
96 ]) |
|
97 } |
|
98 |
|
99 pub fn rotated180(&self) -> Self { |
|
100 Self([ |
|
101 self.0[2].clone(), |
|
102 self.0[3].clone(), |
|
103 self.0[0].clone(), |
|
104 self.0[1].clone(), |
|
105 ]) |
|
106 } |
|
107 |
|
108 pub fn rotated270(&self) -> Self { |
|
109 Self([ |
|
110 self.0[1].clone(), |
|
111 self.0[2].clone(), |
|
112 self.0[3].clone(), |
|
113 self.0[0].clone(), |
|
114 ]) |
|
115 } |
|
116 } |
|
117 |
|
118 #[derive(PartialEq, Clone, Debug)] |
|
119 pub enum MatchSide { |
|
120 OnTop, |
|
121 OnRight, |
|
122 OnBottom, |
|
123 OnLeft, |
|
124 } |
38 #[derive(Clone)] |
125 #[derive(Clone)] |
39 pub struct TileImage<T, I: PartialEq + Clone> { |
126 pub struct TileImage<T, I: PartialEq + Clone> { |
40 image: Rc<Vec2D<T>>, |
127 image: Rc<Vec2D<T>>, |
41 pub weight: u8, |
128 pub weight: u8, |
42 pub transform: Transform, |
129 pub transform: Transform, |
43 top: Edge<I>, |
130 edges: EdgeSet<I>, |
44 right: Edge<I>, |
131 anti_match: [u64; 4], |
45 bottom: Edge<I>, |
|
46 left: Edge<I>, |
|
47 } |
132 } |
48 |
133 |
49 impl<T: Copy, I: PartialEq + Clone> TileImage<T, I> { |
134 impl<T: Copy, I: PartialEq + Clone> TileImage<T, I> { |
50 pub fn new( |
135 pub fn new(image: Vec2D<T>, weight: u8, edges: EdgeSet<I>, anti_match: [u64; 4]) -> Self { |
51 image: Vec2D<T>, |
|
52 weight: u8, |
|
53 top: Edge<I>, |
|
54 right: Edge<I>, |
|
55 bottom: Edge<I>, |
|
56 left: Edge<I>, |
|
57 ) -> Self { |
|
58 Self { |
136 Self { |
59 image: Rc::new(image), |
137 image: Rc::new(image), |
60 weight, |
138 weight, |
61 transform: Transform::default(), |
139 transform: Transform::default(), |
62 top, |
140 edges, |
63 right, |
141 anti_match, |
64 bottom, |
142 } |
65 left, |
143 } |
|
144 |
|
145 pub fn is_compatible(&self, other: &Self, direction: MatchSide) -> bool { |
|
146 match direction { |
|
147 MatchSide::OnTop => { |
|
148 self.anti_match[0] & other.anti_match[2] == 0 |
|
149 && self |
|
150 .edge_set() |
|
151 .top() |
|
152 .is_compatible(other.edge_set().bottom()) |
|
153 } |
|
154 MatchSide::OnRight => { |
|
155 self.anti_match[1] & other.anti_match[3] == 0 |
|
156 && self |
|
157 .edge_set() |
|
158 .right() |
|
159 .is_compatible(other.edge_set().left()) |
|
160 } |
|
161 MatchSide::OnBottom => { |
|
162 self.anti_match[2] & other.anti_match[0] == 0 |
|
163 && self |
|
164 .edge_set() |
|
165 .bottom() |
|
166 .is_compatible(other.edge_set().top()) |
|
167 } |
|
168 MatchSide::OnLeft => { |
|
169 self.anti_match[3] & other.anti_match[1] == 0 |
|
170 && self |
|
171 .edge_set() |
|
172 .left() |
|
173 .is_compatible(other.edge_set().right()) |
|
174 } |
66 } |
175 } |
67 } |
176 } |
68 |
177 |
69 pub fn mirrored(&self) -> Self { |
178 pub fn mirrored(&self) -> Self { |
70 Self { |
179 Self { |
71 image: self.image.clone(), |
180 image: self.image.clone(), |
72 weight: self.weight, |
181 weight: self.weight, |
73 transform: self.transform.mirror(), |
182 transform: self.transform.mirror(), |
74 top: self.top.reversed(), |
183 edges: self.edges.mirrored(), |
75 right: self.left.reversed(), |
184 anti_match: [ |
76 bottom: self.bottom.reversed(), |
185 self.anti_match[0], |
77 left: self.right.reversed(), |
186 self.anti_match[3], |
|
187 self.anti_match[2], |
|
188 self.anti_match[1], |
|
189 ], |
78 } |
190 } |
79 } |
191 } |
80 |
192 |
81 pub fn flipped(&self) -> Self { |
193 pub fn flipped(&self) -> Self { |
82 Self { |
194 Self { |
83 image: self.image.clone(), |
195 image: self.image.clone(), |
84 weight: self.weight, |
196 weight: self.weight, |
85 transform: self.transform.flip(), |
197 transform: self.transform.flip(), |
86 top: self.bottom.reversed(), |
198 edges: self.edges.flipped(), |
87 right: self.right.reversed(), |
199 anti_match: [ |
88 bottom: self.top.reversed(), |
200 self.anti_match[2], |
89 left: self.left.reversed(), |
201 self.anti_match[1], |
|
202 self.anti_match[0], |
|
203 self.anti_match[3], |
|
204 ], |
90 } |
205 } |
91 } |
206 } |
92 |
207 |
93 pub fn rotated90(&self) -> Self { |
208 pub fn rotated90(&self) -> Self { |
94 Self { |
209 Self { |
95 image: self.image.clone(), |
210 image: self.image.clone(), |
96 weight: self.weight, |
211 weight: self.weight, |
97 transform: self.transform.rotate90(), |
212 transform: self.transform.rotate90(), |
98 top: self.left.clone(), |
213 edges: self.edges.rotated90(), |
99 right: self.top.clone(), |
214 anti_match: [ |
100 bottom: self.right.clone(), |
215 self.anti_match[3], |
101 left: self.bottom.clone(), |
216 self.anti_match[0], |
|
217 self.anti_match[1], |
|
218 self.anti_match[2], |
|
219 ], |
102 } |
220 } |
103 } |
221 } |
104 |
222 |
105 pub fn rotated180(&self) -> Self { |
223 pub fn rotated180(&self) -> Self { |
106 Self { |
224 Self { |
107 image: self.image.clone(), |
225 image: self.image.clone(), |
108 weight: self.weight, |
226 weight: self.weight, |
109 transform: self.transform.rotate180(), |
227 transform: self.transform.rotate180(), |
110 top: self.bottom.clone(), |
228 edges: self.edges.rotated180(), |
111 right: self.left.clone(), |
229 anti_match: [ |
112 bottom: self.top.clone(), |
230 self.anti_match[2], |
113 left: self.right.clone(), |
231 self.anti_match[3], |
|
232 self.anti_match[0], |
|
233 self.anti_match[1], |
|
234 ], |
114 } |
235 } |
115 } |
236 } |
116 |
237 |
117 pub fn rotated270(&self) -> Self { |
238 pub fn rotated270(&self) -> Self { |
118 Self { |
239 Self { |
119 image: self.image.clone(), |
240 image: self.image.clone(), |
120 weight: self.weight, |
241 weight: self.weight, |
121 transform: self.transform.rotate270(), |
242 transform: self.transform.rotate270(), |
122 top: self.right.clone(), |
243 edges: self.edges.rotated270(), |
123 right: self.bottom.clone(), |
244 anti_match: [ |
124 bottom: self.left.clone(), |
245 self.anti_match[1], |
125 left: self.top.clone(), |
246 self.anti_match[2], |
126 } |
247 self.anti_match[3], |
127 } |
248 self.anti_match[0], |
128 |
249 ], |
129 #[inline] |
250 } |
130 pub fn right_edge(&self) -> &Edge<I> { |
251 } |
131 &self.right |
252 |
132 } |
253 #[inline] |
133 |
254 pub fn edge_set(&self) -> &EdgeSet<I> { |
134 #[inline] |
255 &self.edges |
135 pub fn bottom_edge(&self) -> &Edge<I> { |
|
136 &self.bottom |
|
137 } |
|
138 |
|
139 #[inline] |
|
140 pub fn left_edge(&self) -> &Edge<I> { |
|
141 &self.left |
|
142 } |
|
143 |
|
144 #[inline] |
|
145 pub fn top_edge(&self) -> &Edge<I> { |
|
146 &self.top |
|
147 } |
256 } |
148 |
257 |
149 #[inline] |
258 #[inline] |
150 pub fn size(&self) -> Size { |
259 pub fn size(&self) -> Size { |
151 match self.transform { |
260 match self.transform { |