lyon_path/
polygon.rs

1//! Specific path types for polygons.
2
3use crate::math::Point;
4use 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)]
30pub struct Polygon<'l, T> {
31    pub points: &'l [T],
32    pub closed: bool,
33}
34
35impl<'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
86impl<'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)]
95pub struct IdPolygon<'l> {
96    pub points: &'l [EndpointId],
97    pub closed: bool,
98}
99
100impl<'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)]
134pub 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
142impl<'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)]
172pub 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
179impl<'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)]
207pub struct PathEvents<'l, T> {
208    points: core::slice::Iter<'l, T>,
209    prev: Option<Point>,
210    first: Option<Point>,
211    closed: bool,
212}
213
214impl<'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)]
244pub struct PolygonIdIter {
245    idx: u32,
246    start: u32,
247    end: u32,
248    closed: bool,
249}
250
251impl 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
263impl 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
290impl<'l, Endpoint> PositionStore for Polygon<'l, Endpoint>
291where
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]
304fn 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]
377fn 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}