1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::{
    geometry::Point,
    primitives::{
        line::{self, Line},
        polyline::Polyline,
        PointsIter,
    },
};

/// An iterator over all pixel positions on the polyline
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Points<'a> {
    vertices: &'a [Point],
    translate: Point,
    segment_iter: line::Points,
}

impl<'a> Points<'a> {
    pub(in crate::primitives) fn new<'b>(polyline: &'b Polyline<'a>) -> Self
    where
        'a: 'b,
    {
        polyline
            .vertices
            .split_first()
            .and_then(|(start, rest)| {
                // Polyline is 2 or more vertices long, return an iterator for it
                rest.get(0).map(|end| Points {
                    vertices: rest,
                    translate: polyline.translate,
                    segment_iter: Line::new(*start + polyline.translate, *end + polyline.translate)
                        .points(),
                })
            })
            .unwrap_or_else(||
                // Polyline is less than 2 vertices long. Return a dummy iterator that will short
                // circuit
                Points {
                    vertices: &[],
                    translate: Point::zero(),
                    segment_iter: line::Points::empty(),
                })
    }
}

impl<'a> Iterator for Points<'a> {
    type Item = Point;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(p) = self.segment_iter.next() {
            Some(p)
        } else {
            let (start, rest) = self.vertices.split_first()?;
            let end = rest.get(0)?;

            self.vertices = rest;

            self.segment_iter = Line::new(*start + self.translate, *end + self.translate).points();

            // Skip first point of next line, otherwise we overlap with the previous line
            self.nth(1)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::primitives::polyline::tests::SMALL;

    // Ensure that consecutive points are always different
    #[test]
    fn no_duplicate_points() {
        let expected: [Point; 14] = [
            Point::new(2, 5),
            Point::new(3, 4),
            Point::new(4, 3),
            Point::new(5, 2),
            Point::new(6, 3),
            Point::new(7, 3),
            Point::new(8, 4),
            Point::new(9, 4),
            Point::new(10, 5),
            Point::new(11, 4),
            Point::new(12, 4),
            Point::new(13, 3),
            Point::new(14, 3),
            Point::new(15, 2),
        ];

        assert!(Polyline::new(&SMALL).points().eq(expected.iter().copied()))
    }

    #[test]
    fn one_point() {
        let points = &[Point::zero()];

        let polyline = Polyline::new(points);

        assert!(polyline.points().eq(core::iter::empty()));
    }

    #[test]
    fn equal_points() {
        let points: [Point; 3] = [Point::new(2, 5), Point::new(2, 5), Point::new(2, 5)];

        assert!(Polyline::new(&points)
            .points()
            .eq(core::iter::once(Point::new(2, 5))));
    }
}