1 | use crate::{ |
2 | geometry::Point, |
3 | primitives::{ |
4 | common::{DistanceIterator, PlaneSector}, |
5 | sector::Sector, |
6 | }, |
7 | }; |
8 | |
9 | /// Iterator over all points inside the sector. |
10 | #[derive (Clone, PartialEq, Debug)] |
11 | #[cfg_attr (feature = "defmt" , derive(::defmt::Format))] |
12 | pub struct Points { |
13 | iter: DistanceIterator, |
14 | |
15 | plane_sector: PlaneSector, |
16 | |
17 | threshold: u32, |
18 | } |
19 | |
20 | impl Points { |
21 | pub(in crate::primitives) fn new(sector: &Sector) -> Self { |
22 | let circle: Circle = sector.to_circle(); |
23 | |
24 | let plane_sector: PlaneSector = PlaneSector::new(sector.angle_start, sector.angle_sweep); |
25 | |
26 | Self { |
27 | // PERF: The distance iterator should use the smaller sector bounding box |
28 | iter: circle.distances(), |
29 | plane_sector, |
30 | threshold: circle.threshold(), |
31 | } |
32 | } |
33 | } |
34 | |
35 | impl Iterator for Points { |
36 | type Item = Point; |
37 | |
38 | fn next(&mut self) -> Option<Self::Item> { |
39 | let threshold: u32 = self.threshold; |
40 | let plane_sector: PlaneSector = self.plane_sector; |
41 | |
42 | self.iter |
43 | .find(|(_, delta: &Point, distance: &u32)| *distance < threshold && plane_sector.contains(*delta)) |
44 | .map(|(point: Point, ..)| point) |
45 | } |
46 | } |
47 | |
48 | #[cfg (test)] |
49 | mod tests { |
50 | use super::*; |
51 | use crate::{ |
52 | geometry::AngleUnit, |
53 | pixelcolor::BinaryColor, |
54 | primitives::{PointsIter, Primitive, PrimitiveStyle}, |
55 | Pixel, |
56 | }; |
57 | |
58 | #[test ] |
59 | fn points_equals_filled() { |
60 | let sector = Sector::with_center(Point::new(10, 10), 5, 0.0.deg(), 90.0.deg()); |
61 | |
62 | let styled_points = sector |
63 | .clone() |
64 | .into_styled(PrimitiveStyle::with_fill(BinaryColor::On)) |
65 | .pixels() |
66 | .map(|Pixel(p, _)| p); |
67 | |
68 | assert!(sector.points().eq(styled_points)); |
69 | } |
70 | } |
71 | |