plotters/series/
area_series.rs
1use crate::element::{DynElement, IntoDynElement, PathElement, Polygon};
2use crate::style::colors::TRANSPARENT;
3use crate::style::ShapeStyle;
4use plotters_backend::DrawingBackend;
5
6pub struct AreaSeries<DB: DrawingBackend, X: Clone, Y: Clone> {
8 area_style: ShapeStyle,
9 border_style: ShapeStyle,
10 baseline: Y,
11 data: Vec<(X, Y)>,
12 state: u32,
13 _p: std::marker::PhantomData<DB>,
14}
15
16impl<DB: DrawingBackend, X: Clone, Y: Clone> AreaSeries<DB, X, Y> {
17 pub fn new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>(
18 iter: I,
19 baseline: Y,
20 area_style: S,
21 ) -> Self {
22 Self {
23 area_style: area_style.into(),
24 baseline,
25 data: iter.into_iter().collect(),
26 state: 0,
27 border_style: (&TRANSPARENT).into(),
28 _p: std::marker::PhantomData,
29 }
30 }
31
32 pub fn border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self {
33 self.border_style = style.into();
34 self
35 }
36}
37
38impl<DB: DrawingBackend, X: Clone + 'static, Y: Clone + 'static> Iterator for AreaSeries<DB, X, Y> {
39 type Item = DynElement<'static, DB, (X, Y)>;
40 fn next(&mut self) -> Option<Self::Item> {
41 if self.state == 0 {
42 let mut data: Vec<_> = self.data.clone();
43
44 if !data.is_empty() {
45 data.push((data[data.len() - 1].0.clone(), self.baseline.clone()));
46 data.push((data[0].0.clone(), self.baseline.clone()));
47 }
48
49 self.state = 1;
50
51 Some(Polygon::new(data, self.area_style.clone()).into_dyn())
52 } else if self.state == 1 {
53 let data: Vec<_> = self.data.clone();
54
55 self.state = 2;
56
57 Some(PathElement::new(data, self.border_style.clone()).into_dyn())
58 } else {
59 None
60 }
61 }
62}