1 use crate::element::{Circle, DynElement, IntoDynElement, PathElement}; 2 use crate::style::ShapeStyle; 3 use plotters_backend::DrawingBackend; 4 use std::marker::PhantomData; 5 6 /// The line series object, which takes an iterator of points in guest coordinate system 7 /// and creates the element rendering the line plot 8 pub struct LineSeries<DB: DrawingBackend, Coord> { 9 style: ShapeStyle, 10 data: Vec<Coord>, 11 point_idx: usize, 12 point_size: u32, 13 phantom: PhantomData<DB>, 14 } 15 16 impl<DB: DrawingBackend, Coord: Clone + 'static> Iterator for LineSeries<DB, Coord> { 17 type Item = DynElement<'static, DB, Coord>; next(&mut self) -> Option<Self::Item>18 fn next(&mut self) -> Option<Self::Item> { 19 if !self.data.is_empty() { 20 if self.point_size > 0 && self.point_idx < self.data.len() { 21 let idx = self.point_idx; 22 self.point_idx += 1; 23 return Some( 24 Circle::new(self.data[idx].clone(), self.point_size, self.style.clone()) 25 .into_dyn(), 26 ); 27 } 28 let mut data = vec![]; 29 std::mem::swap(&mut self.data, &mut data); 30 Some(PathElement::new(data, self.style.clone()).into_dyn()) 31 } else { 32 None 33 } 34 } 35 } 36 37 impl<DB: DrawingBackend, Coord> LineSeries<DB, Coord> { new<I: IntoIterator<Item = Coord>, S: Into<ShapeStyle>>(iter: I, style: S) -> Self38 pub fn new<I: IntoIterator<Item = Coord>, S: Into<ShapeStyle>>(iter: I, style: S) -> Self { 39 Self { 40 style: style.into(), 41 data: iter.into_iter().collect(), 42 point_size: 0, 43 point_idx: 0, 44 phantom: PhantomData, 45 } 46 } 47 point_size(mut self, size: u32) -> Self48 pub fn point_size(mut self, size: u32) -> Self { 49 self.point_size = size; 50 self 51 } 52 } 53 54 #[cfg(test)] 55 mod test { 56 use crate::prelude::*; 57 58 #[test] test_line_series()59 fn test_line_series() { 60 let drawing_area = create_mocked_drawing_area(200, 200, |m| { 61 m.check_draw_path(|c, s, path| { 62 assert_eq!(c, RED.to_rgba()); 63 assert_eq!(s, 3); 64 for i in 0..100 { 65 assert_eq!(path[i], (i as i32 * 2, 200 - i as i32 * 2 - 1)); 66 } 67 }); 68 69 m.drop_check(|b| { 70 assert_eq!(b.num_draw_path_call, 1); 71 assert_eq!(b.draw_count, 1); 72 }); 73 }); 74 75 let mut chart = ChartBuilder::on(&drawing_area) 76 .build_cartesian_2d(0..100, 0..100) 77 .expect("Build chart error"); 78 79 chart 80 .draw_series(LineSeries::new( 81 (0..100).map(|x| (x, x)), 82 Into::<ShapeStyle>::into(&RED).stroke_width(3), 83 )) 84 .expect("Drawing Error"); 85 } 86 } 87