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