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}
440