1use super::*;
2use super::{Drawable, PointCollection};
3use crate::style::{Color, ShapeStyle, SizeDesc};
4use plotters_backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
5
6pub trait PointElement<Coord, Size: SizeDesc> {
8 fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self;
9}
10
11pub struct Cross<Coord, Size: SizeDesc> {
13 center: Coord,
14 size: Size,
15 style: ShapeStyle,
16}
17
18impl<Coord, Size: SizeDesc> Cross<Coord, Size> {
19 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
28impl<'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>;
31 fn point_iter(self) -> std::iter::Once<&'a Coord> {
32 std::iter::once(&self.center)
33 }
34}
35
36impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for Cross<Coord, Size> {
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
54pub struct TriangleMarker<Coord, Size: SizeDesc> {
56 center: Coord,
57 size: Size,
58 style: ShapeStyle,
59}
60
61impl<Coord, Size: SizeDesc> TriangleMarker<Coord, Size> {
62 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
71impl<'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>;
74 fn point_iter(self) -> std::iter::Once<&'a Coord> {
75 std::iter::once(&self.center)
76 }
77}
78
79impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for TriangleMarker<Coord, Size> {
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
103impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Cross<Coord, Size> {
104 fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
105 Self::new(pos, size, style)
106 }
107}
108
109impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for TriangleMarker<Coord, Size> {
110 fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
111 Self::new(pos, size, style)
112 }
113}
114
115impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Circle<Coord, Size> {
116 fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
117 Self::new(pos, size, style)
118 }
119}
120
121impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Pixel<Coord> {
122 fn make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self {
123 Self::new(pos, style)
124 }
125}