1 | //! Specific path types for polygons. |
2 | |
3 | use crate::math::Point; |
4 | use crate::{ |
5 | ControlPointId, EndpointId, Event, EventId, IdEvent, PathEvent, Position, PositionStore, |
6 | }; |
7 | |
8 | /// A view over a sequence of endpoints forming a polygon. |
9 | /// |
10 | /// ## Example |
11 | /// |
12 | /// ``` |
13 | /// use lyon_path::polygon::Polygon; |
14 | /// use lyon_path::geom::point; |
15 | /// |
16 | /// let path = Polygon { |
17 | /// points: &[ |
18 | /// point(0.0, 0.0), |
19 | /// point(10.0, 10.0), |
20 | /// point(0.0, 10.0), |
21 | /// ], |
22 | /// closed: true, |
23 | /// }; |
24 | /// |
25 | /// for event in path.path_events() { |
26 | /// // same as iterating a regular `Path` object. |
27 | /// } |
28 | /// ``` |
29 | #[derive (Clone)] |
30 | pub struct Polygon<'l, T> { |
31 | pub points: &'l [T], |
32 | pub closed: bool, |
33 | } |
34 | |
35 | impl<'l, T> Polygon<'l, T> { |
36 | /// Returns an iterator of `Event<&T>`. |
37 | pub fn iter(&self) -> PolygonIter<'l, T> { |
38 | PolygonIter { |
39 | points: self.points.iter(), |
40 | prev: None, |
41 | first: None, |
42 | closed: self.closed, |
43 | } |
44 | } |
45 | |
46 | /// Returns an iterator of `IdEvent`. |
47 | pub fn id_iter(&self) -> PolygonIdIter { |
48 | PolygonIdIter::new(0..(self.points.len() as u32), self.closed) |
49 | } |
50 | |
51 | /// Returns an iterator of `PathEvent`. |
52 | pub fn path_events(&self) -> PathEvents<T> |
53 | where |
54 | T: Position, |
55 | { |
56 | PathEvents { |
57 | points: self.points.iter(), |
58 | first: None, |
59 | prev: None, |
60 | closed: self.closed, |
61 | } |
62 | } |
63 | |
64 | /// Returns the event for a given event ID. |
65 | pub fn event(&self, id: EventId) -> Event<&T, ()> { |
66 | let idx = id.0 as usize; |
67 | if idx == 0 { |
68 | Event::Begin { |
69 | at: &self.points[0], |
70 | } |
71 | } else if idx == self.points.len() - 1 { |
72 | Event::End { |
73 | last: &self.points[self.points.len() - 1], |
74 | first: &self.points[0], |
75 | close: self.closed, |
76 | } |
77 | } else { |
78 | Event::Line { |
79 | from: &self.points[idx - 1], |
80 | to: &self.points[idx], |
81 | } |
82 | } |
83 | } |
84 | } |
85 | |
86 | impl<'l, T> core::ops::Index<EndpointId> for Polygon<'l, T> { |
87 | type Output = T; |
88 | fn index(&self, id: EndpointId) -> &T { |
89 | &self.points[id.to_usize()] |
90 | } |
91 | } |
92 | |
93 | /// A view over a sequence of endpoint IDs forming a polygon. |
94 | #[derive (Clone)] |
95 | pub struct IdPolygon<'l> { |
96 | pub points: &'l [EndpointId], |
97 | pub closed: bool, |
98 | } |
99 | |
100 | impl<'l> IdPolygon<'l> { |
101 | // Returns an iterator over the endpoint IDs of the polygon. |
102 | pub fn iter(&self) -> IdPolygonIter<'l> { |
103 | IdPolygonIter { |
104 | points: self.points.iter(), |
105 | idx: 0, |
106 | prev: None, |
107 | first: EndpointId(0), |
108 | closed: self.closed, |
109 | } |
110 | } |
111 | |
112 | /// Returns the event for a given event ID. |
113 | pub fn event(&self, id: EventId) -> IdEvent { |
114 | let idx = id.0 as usize; |
115 | if idx == 0 { |
116 | IdEvent::Begin { at: self.points[0] } |
117 | } else if idx == self.points.len() { |
118 | IdEvent::End { |
119 | last: self.points[self.points.len() - 1], |
120 | first: self.points[0], |
121 | close: self.closed, |
122 | } |
123 | } else { |
124 | IdEvent::Line { |
125 | from: self.points[idx - 1], |
126 | to: self.points[idx], |
127 | } |
128 | } |
129 | } |
130 | } |
131 | |
132 | /// An iterator of `Event<EndpointId, ()>`. |
133 | #[derive (Clone)] |
134 | pub struct IdPolygonIter<'l> { |
135 | points: core::slice::Iter<'l, EndpointId>, |
136 | idx: u32, |
137 | prev: Option<EndpointId>, |
138 | first: EndpointId, |
139 | closed: bool, |
140 | } |
141 | |
142 | impl<'l> Iterator for IdPolygonIter<'l> { |
143 | type Item = IdEvent; |
144 | fn next(&mut self) -> Option<IdEvent> { |
145 | match (self.prev, self.points.next()) { |
146 | (Some(from), Some(to)) => { |
147 | self.prev = Some(*to); |
148 | self.idx += 1; |
149 | Some(IdEvent::Line { from, to: *to }) |
150 | } |
151 | (None, Some(at)) => { |
152 | self.prev = Some(*at); |
153 | self.first = *at; |
154 | self.idx += 1; |
155 | Some(IdEvent::Begin { at: *at }) |
156 | } |
157 | (Some(last), None) => { |
158 | self.prev = None; |
159 | Some(IdEvent::End { |
160 | last, |
161 | first: self.first, |
162 | close: self.closed, |
163 | }) |
164 | } |
165 | (None, None) => None, |
166 | } |
167 | } |
168 | } |
169 | |
170 | /// An iterator of `Event<&Endpoint, ()>`. |
171 | #[derive (Clone)] |
172 | pub struct PolygonIter<'l, T> { |
173 | points: core::slice::Iter<'l, T>, |
174 | prev: Option<&'l T>, |
175 | first: Option<&'l T>, |
176 | closed: bool, |
177 | } |
178 | |
179 | impl<'l, T> Iterator for PolygonIter<'l, T> { |
180 | type Item = Event<&'l T, ()>; |
181 | fn next(&mut self) -> Option<Event<&'l T, ()>> { |
182 | match (self.prev, self.points.next()) { |
183 | (Some(from), Some(to)) => { |
184 | self.prev = Some(to); |
185 | Some(Event::Line { from, to }) |
186 | } |
187 | (None, Some(at)) => { |
188 | self.prev = Some(at); |
189 | self.first = Some(at); |
190 | Some(Event::Begin { at }) |
191 | } |
192 | (Some(last), None) => { |
193 | self.prev = None; |
194 | Some(Event::End { |
195 | last, |
196 | first: self.first.unwrap(), |
197 | close: self.closed, |
198 | }) |
199 | } |
200 | (None, None) => None, |
201 | } |
202 | } |
203 | } |
204 | |
205 | /// An iterator of `PathEvent`. |
206 | #[derive (Clone)] |
207 | pub struct PathEvents<'l, T> { |
208 | points: core::slice::Iter<'l, T>, |
209 | prev: Option<Point>, |
210 | first: Option<Point>, |
211 | closed: bool, |
212 | } |
213 | |
214 | impl<'l, T: Position> Iterator for PathEvents<'l, T> { |
215 | type Item = PathEvent; |
216 | fn next(&mut self) -> Option<PathEvent> { |
217 | match (self.prev, self.points.next()) { |
218 | (Some(from), Some(to)) => { |
219 | let to = to.position(); |
220 | self.prev = Some(to); |
221 | Some(Event::Line { from, to }) |
222 | } |
223 | (None, Some(at)) => { |
224 | let at = at.position(); |
225 | self.prev = Some(at); |
226 | self.first = Some(at); |
227 | Some(Event::Begin { at }) |
228 | } |
229 | (Some(last), None) => { |
230 | self.prev = None; |
231 | Some(Event::End { |
232 | last, |
233 | first: self.first.unwrap(), |
234 | close: self.closed, |
235 | }) |
236 | } |
237 | (None, None) => None, |
238 | } |
239 | } |
240 | } |
241 | |
242 | /// An iterator of `IdEvent` for `Polygon`. |
243 | #[derive (Clone)] |
244 | pub struct PolygonIdIter { |
245 | idx: u32, |
246 | start: u32, |
247 | end: u32, |
248 | closed: bool, |
249 | } |
250 | |
251 | impl PolygonIdIter { |
252 | #[inline ] |
253 | pub fn new(range: core::ops::Range<u32>, closed: bool) -> Self { |
254 | PolygonIdIter { |
255 | idx: range.start, |
256 | start: range.start, |
257 | end: range.end, |
258 | closed, |
259 | } |
260 | } |
261 | } |
262 | |
263 | impl Iterator for PolygonIdIter { |
264 | type Item = IdEvent; |
265 | fn next(&mut self) -> Option<IdEvent> { |
266 | let idx = self.idx; |
267 | self.idx += 1; |
268 | |
269 | if idx == self.start { |
270 | Some(IdEvent::Begin { |
271 | at: EndpointId(self.start), |
272 | }) |
273 | } else if idx < self.end { |
274 | Some(IdEvent::Line { |
275 | from: EndpointId(idx - 1), |
276 | to: EndpointId(idx), |
277 | }) |
278 | } else if idx == self.end { |
279 | Some(IdEvent::End { |
280 | last: EndpointId(self.end - 1), |
281 | first: EndpointId(self.start), |
282 | close: self.closed, |
283 | }) |
284 | } else { |
285 | None |
286 | } |
287 | } |
288 | } |
289 | |
290 | impl<'l, Endpoint> PositionStore for Polygon<'l, Endpoint> |
291 | where |
292 | Endpoint: Position, |
293 | { |
294 | fn get_endpoint(&self, id: EndpointId) -> Point { |
295 | self.points[id.to_usize()].position() |
296 | } |
297 | |
298 | fn get_control_point(&self, _: ControlPointId) -> Point { |
299 | panic!("Polygons do not have control points." ); |
300 | } |
301 | } |
302 | |
303 | #[test ] |
304 | fn event_ids() { |
305 | let poly = IdPolygon { |
306 | points: &[EndpointId(0), EndpointId(1), EndpointId(2), EndpointId(3)], |
307 | closed: true, |
308 | }; |
309 | |
310 | assert_eq!(poly.event(EventId(0)), IdEvent::Begin { at: EndpointId(0) }); |
311 | assert_eq!( |
312 | poly.event(EventId(1)), |
313 | IdEvent::Line { |
314 | from: EndpointId(0), |
315 | to: EndpointId(1) |
316 | } |
317 | ); |
318 | assert_eq!( |
319 | poly.event(EventId(2)), |
320 | IdEvent::Line { |
321 | from: EndpointId(1), |
322 | to: EndpointId(2) |
323 | } |
324 | ); |
325 | assert_eq!( |
326 | poly.event(EventId(3)), |
327 | IdEvent::Line { |
328 | from: EndpointId(2), |
329 | to: EndpointId(3) |
330 | } |
331 | ); |
332 | assert_eq!( |
333 | poly.event(EventId(4)), |
334 | IdEvent::End { |
335 | last: EndpointId(3), |
336 | first: EndpointId(0), |
337 | close: true |
338 | } |
339 | ); |
340 | |
341 | let mut iter = poly.iter(); |
342 | assert_eq!(iter.next(), Some(IdEvent::Begin { at: EndpointId(0) })); |
343 | assert_eq!( |
344 | iter.next(), |
345 | Some(IdEvent::Line { |
346 | from: EndpointId(0), |
347 | to: EndpointId(1) |
348 | }) |
349 | ); |
350 | assert_eq!( |
351 | iter.next(), |
352 | Some(IdEvent::Line { |
353 | from: EndpointId(1), |
354 | to: EndpointId(2) |
355 | }) |
356 | ); |
357 | assert_eq!( |
358 | iter.next(), |
359 | Some(IdEvent::Line { |
360 | from: EndpointId(2), |
361 | to: EndpointId(3) |
362 | }) |
363 | ); |
364 | assert_eq!( |
365 | iter.next(), |
366 | Some(IdEvent::End { |
367 | last: EndpointId(3), |
368 | first: EndpointId(0), |
369 | close: true |
370 | }) |
371 | ); |
372 | assert_eq!(iter.next(), None); |
373 | assert_eq!(iter.next(), None); |
374 | } |
375 | |
376 | #[test ] |
377 | fn polygon_slice_id_ite() { |
378 | let points: &[u32] = &[0, 1, 2, 3, 4, 5, 6]; |
379 | let polygon = Polygon { |
380 | points, |
381 | closed: true, |
382 | }; |
383 | |
384 | let mut it = polygon.id_iter(); |
385 | assert_eq!(it.next(), Some(IdEvent::Begin { at: EndpointId(0) })); |
386 | assert_eq!( |
387 | it.next(), |
388 | Some(IdEvent::Line { |
389 | from: EndpointId(0), |
390 | to: EndpointId(1) |
391 | }) |
392 | ); |
393 | assert_eq!( |
394 | it.next(), |
395 | Some(IdEvent::Line { |
396 | from: EndpointId(1), |
397 | to: EndpointId(2) |
398 | }) |
399 | ); |
400 | assert_eq!( |
401 | it.next(), |
402 | Some(IdEvent::Line { |
403 | from: EndpointId(2), |
404 | to: EndpointId(3) |
405 | }) |
406 | ); |
407 | assert_eq!( |
408 | it.next(), |
409 | Some(IdEvent::Line { |
410 | from: EndpointId(3), |
411 | to: EndpointId(4) |
412 | }) |
413 | ); |
414 | assert_eq!( |
415 | it.next(), |
416 | Some(IdEvent::Line { |
417 | from: EndpointId(4), |
418 | to: EndpointId(5) |
419 | }) |
420 | ); |
421 | assert_eq!( |
422 | it.next(), |
423 | Some(IdEvent::Line { |
424 | from: EndpointId(5), |
425 | to: EndpointId(6) |
426 | }) |
427 | ); |
428 | assert_eq!( |
429 | it.next(), |
430 | Some(IdEvent::End { |
431 | last: EndpointId(6), |
432 | first: EndpointId(0), |
433 | close: true |
434 | }) |
435 | ); |
436 | assert_eq!(it.next(), None); |
437 | assert_eq!(it.next(), None); |
438 | assert_eq!(it.next(), None); |
439 | } |
440 | |