/rust/registry/src/index.crates.io-6f17d22bba15001f/plotters-0.3.7/src/element/points.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use super::*; |
2 | | use super::{Drawable, PointCollection}; |
3 | | use crate::style::{Color, ShapeStyle, SizeDesc}; |
4 | | use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind}; |
5 | | |
6 | | /** |
7 | | A common trait for elements that can be interpreted as points: A cross, a circle, a triangle marker... |
8 | | |
9 | | This is used internally by Plotters and should probably not be included in user code. |
10 | | See [`EmptyElement`] for more information and examples. |
11 | | */ |
12 | | pub trait PointElement<Coord, Size: SizeDesc> { |
13 | | /** |
14 | | Point creator. |
15 | | |
16 | | This is used internally by Plotters and should probably not be included in user code. |
17 | | See [`EmptyElement`] for more information and examples. |
18 | | */ |
19 | | fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self; |
20 | | } |
21 | | |
22 | | /** |
23 | | A cross marker for visualizing data series. |
24 | | |
25 | | See [`EmptyElement`] for more information and examples. |
26 | | */ |
27 | | pub struct Cross<Coord, Size: SizeDesc> { |
28 | | center: Coord, |
29 | | size: Size, |
30 | | style: ShapeStyle, |
31 | | } |
32 | | |
33 | | impl<Coord, Size: SizeDesc> Cross<Coord, Size> { |
34 | | /** |
35 | | Creates a cross marker. |
36 | | |
37 | | See [`EmptyElement`] for more information and examples. |
38 | | */ |
39 | 0 | pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self { |
40 | 0 | Self { |
41 | 0 | center: coord, |
42 | 0 | size, |
43 | 0 | style: style.into(), |
44 | 0 | } |
45 | 0 | } |
46 | | } |
47 | | |
48 | | impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a Cross<Coord, Size> { |
49 | | type Point = &'a Coord; |
50 | | type IntoIter = std::iter::Once<&'a Coord>; |
51 | 0 | fn point_iter(self) -> std::iter::Once<&'a Coord> { |
52 | 0 | std::iter::once(&self.center) |
53 | 0 | } |
54 | | } |
55 | | |
56 | | impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for Cross<Coord, Size> { |
57 | 0 | fn draw<I: Iterator<Item = BackendCoord>>( |
58 | 0 | &self, |
59 | 0 | mut points: I, |
60 | 0 | backend: &mut DB, |
61 | 0 | ps: (u32, u32), |
62 | 0 | ) -> Result<(), DrawingErrorKind<DB::ErrorType>> { |
63 | 0 | if let Some((x, y)) = points.next() { |
64 | 0 | let size = self.size.in_pixels(&ps); |
65 | 0 | let (x0, y0) = (x - size, y - size); |
66 | 0 | let (x1, y1) = (x + size, y + size); |
67 | 0 | backend.draw_line((x0, y0), (x1, y1), &self.style)?; |
68 | 0 | backend.draw_line((x0, y1), (x1, y0), &self.style)?; |
69 | 0 | } |
70 | 0 | Ok(()) |
71 | 0 | } |
72 | | } |
73 | | |
74 | | /** |
75 | | A triangle marker for visualizing data series. |
76 | | |
77 | | See [`EmptyElement`] for more information and examples. |
78 | | */ |
79 | | pub struct TriangleMarker<Coord, Size: SizeDesc> { |
80 | | center: Coord, |
81 | | size: Size, |
82 | | style: ShapeStyle, |
83 | | } |
84 | | |
85 | | impl<Coord, Size: SizeDesc> TriangleMarker<Coord, Size> { |
86 | | /** |
87 | | Creates a triangle marker. |
88 | | |
89 | | See [`EmptyElement`] for more information and examples. |
90 | | */ |
91 | 0 | pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self { |
92 | 0 | Self { |
93 | 0 | center: coord, |
94 | 0 | size, |
95 | 0 | style: style.into(), |
96 | 0 | } |
97 | 0 | } |
98 | | } |
99 | | |
100 | | impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a TriangleMarker<Coord, Size> { |
101 | | type Point = &'a Coord; |
102 | | type IntoIter = std::iter::Once<&'a Coord>; |
103 | 0 | fn point_iter(self) -> std::iter::Once<&'a Coord> { |
104 | 0 | std::iter::once(&self.center) |
105 | 0 | } |
106 | | } |
107 | | |
108 | | impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for TriangleMarker<Coord, Size> { |
109 | 0 | fn draw<I: Iterator<Item = BackendCoord>>( |
110 | 0 | &self, |
111 | 0 | mut points: I, |
112 | 0 | backend: &mut DB, |
113 | 0 | ps: (u32, u32), |
114 | 0 | ) -> Result<(), DrawingErrorKind<DB::ErrorType>> { |
115 | 0 | if let Some((x, y)) = points.next() { |
116 | 0 | let size = self.size.in_pixels(&ps); |
117 | 0 | let points = [-90, -210, -330] |
118 | 0 | .iter() |
119 | 0 | .map(|deg| f64::from(*deg) * std::f64::consts::PI / 180.0) |
120 | 0 | .map(|rad| { |
121 | 0 | ( |
122 | 0 | (rad.cos() * f64::from(size) + f64::from(x)).ceil() as i32, |
123 | 0 | (rad.sin() * f64::from(size) + f64::from(y)).ceil() as i32, |
124 | 0 | ) |
125 | 0 | }); |
126 | 0 | backend.fill_polygon(points, &self.style.color.to_backend_color())?; |
127 | 0 | } |
128 | 0 | Ok(()) |
129 | 0 | } |
130 | | } |
131 | | |
132 | | impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Cross<Coord, Size> { |
133 | 0 | fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self { |
134 | 0 | Self::new(pos, size, style) |
135 | 0 | } |
136 | | } |
137 | | |
138 | | impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for TriangleMarker<Coord, Size> { |
139 | 0 | fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self { |
140 | 0 | Self::new(pos, size, style) |
141 | 0 | } |
142 | | } |
143 | | |
144 | | impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Circle<Coord, Size> { |
145 | 0 | fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self { |
146 | 0 | Self::new(pos, size, style) |
147 | 0 | } |
148 | | } |
149 | | |
150 | | impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Pixel<Coord> { |
151 | 0 | fn make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self { |
152 | 0 | Self::new(pos, style) |
153 | 0 | } |
154 | | } |