1 use super::*;
2 use super::{Drawable, PointCollection};
3 use crate::style::{Color, ShapeStyle, SizeDesc};
4 use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
5 
6 /// The element that used to describe a point
7 pub trait PointElement<Coord, Size: SizeDesc> {
make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self8     fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self;
9 }
10 
11 /// Describe a cross
12 pub struct Cross<Coord, Size: SizeDesc> {
13     center: Coord,
14     size: Size,
15     style: ShapeStyle,
16 }
17 
18 impl<Coord, Size: SizeDesc> Cross<Coord, Size> {
new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self19     pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self {
20         Self {
21             center: coord,
22             size,
23             style: style.into(),
24         }
25     }
26 }
27 
28 impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a Cross<Coord, Size> {
29     type Point = &'a Coord;
30     type IntoIter = std::iter::Once<&'a Coord>;
point_iter(self) -> std::iter::Once<&'a Coord>31     fn point_iter(self) -> std::iter::Once<&'a Coord> {
32         std::iter::once(&self.center)
33     }
34 }
35 
36 impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for Cross<Coord, Size> {
draw<I: Iterator<Item = BackendCoord>>( &self, mut points: I, backend: &mut DB, ps: (u32, u32), ) -> Result<(), DrawingErrorKind<DB::ErrorType>>37     fn draw<I: Iterator<Item = BackendCoord>>(
38         &self,
39         mut points: I,
40         backend: &mut DB,
41         ps: (u32, u32),
42     ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
43         if let Some((x, y)) = points.next() {
44             let size = self.size.in_pixels(&ps);
45             let (x0, y0) = (x - size, y - size);
46             let (x1, y1) = (x + size, y + size);
47             backend.draw_line((x0, y0), (x1, y1), &self.style)?;
48             backend.draw_line((x0, y1), (x1, y0), &self.style)?;
49         }
50         Ok(())
51     }
52 }
53 
54 /// Describe a triangle marker
55 pub struct TriangleMarker<Coord, Size: SizeDesc> {
56     center: Coord,
57     size: Size,
58     style: ShapeStyle,
59 }
60 
61 impl<Coord, Size: SizeDesc> TriangleMarker<Coord, Size> {
new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self62     pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self {
63         Self {
64             center: coord,
65             size,
66             style: style.into(),
67         }
68     }
69 }
70 
71 impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a TriangleMarker<Coord, Size> {
72     type Point = &'a Coord;
73     type IntoIter = std::iter::Once<&'a Coord>;
point_iter(self) -> std::iter::Once<&'a Coord>74     fn point_iter(self) -> std::iter::Once<&'a Coord> {
75         std::iter::once(&self.center)
76     }
77 }
78 
79 impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for TriangleMarker<Coord, Size> {
draw<I: Iterator<Item = BackendCoord>>( &self, mut points: I, backend: &mut DB, ps: (u32, u32), ) -> Result<(), DrawingErrorKind<DB::ErrorType>>80     fn draw<I: Iterator<Item = BackendCoord>>(
81         &self,
82         mut points: I,
83         backend: &mut DB,
84         ps: (u32, u32),
85     ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
86         if let Some((x, y)) = points.next() {
87             let size = self.size.in_pixels(&ps);
88             let points = [-90, -210, -330]
89                 .iter()
90                 .map(|deg| f64::from(*deg) * std::f64::consts::PI / 180.0)
91                 .map(|rad| {
92                     (
93                         (rad.cos() * f64::from(size) + f64::from(x)).ceil() as i32,
94                         (rad.sin() * f64::from(size) + f64::from(y)).ceil() as i32,
95                     )
96                 });
97             backend.fill_polygon(points, &self.style.color.to_backend_color())?;
98         }
99         Ok(())
100     }
101 }
102 
103 impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Cross<Coord, Size> {
make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self104     fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
105         Self::new(pos, size, style)
106     }
107 }
108 
109 impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for TriangleMarker<Coord, Size> {
make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self110     fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
111         Self::new(pos, size, style)
112     }
113 }
114 
115 impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Circle<Coord, Size> {
make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self116     fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
117         Self::new(pos, size, style)
118     }
119 }
120 
121 impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Pixel<Coord> {
make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self122     fn make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self {
123         Self::new(pos, style)
124     }
125 }
126