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
6/**
7An area series is similar to a line series but uses a filled polygon.
8It takes an iterator of data points in guest coordinate system
9and creates appropriate lines and points with the given style.
10
11# Example
12
13```
14use plotters::prelude::*;
15let x_values = [0.0f64, 1., 2., 3., 4.];
16let drawing_area = SVGBackend::new("area_series.svg", (300, 200)).into_drawing_area();
17drawing_area.fill(&WHITE).unwrap();
18let mut chart_builder = ChartBuilder::on(&drawing_area);
19chart_builder.margin(10).set_left_and_bottom_label_area_size(20);
20let mut chart_context = chart_builder.build_cartesian_2d(0.0..4.0, 0.0..3.0).unwrap();
21chart_context.configure_mesh().draw().unwrap();
22chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 0.3 * x)), 0., BLACK.mix(0.2))).unwrap();
23chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 2.5 - 0.05 * x * x)), 0., RED.mix(0.2))).unwrap();
24chart_context.draw_series(AreaSeries::new(x_values.map(|x| (x, 2. - 0.1 * x * x)), 0., BLUE.mix(0.2)).border_style(BLUE)).unwrap();
25```
26
27The result is a chart with three line series; one of them has a highlighted blue border:
28
29![](https://cdn.jsdelivr.net/gh/facorread/plotters-doc-data@b6703f7/apidoc/area_series.svg)
30*/
31pub struct AreaSeries<DB: DrawingBackend, X: Clone, Y: Clone> {
32    area_style: ShapeStyle,
33    border_style: ShapeStyle,
34    baseline: Y,
35    data: Vec<(X, Y)>,
36    state: u32,
37    _p: std::marker::PhantomData<DB>,
38}
39
40impl<DB: DrawingBackend, X: Clone, Y: Clone> AreaSeries<DB, X, Y> {
41    /**
42    Creates an area series with transparent border.
43
44    See [`AreaSeries`] for more information and examples.
45    */
46    pub fn new<S: Into<ShapeStyle>, I: IntoIterator<Item = (X, Y)>>(
47        iter: I,
48        baseline: Y,
49        area_style: S,
50    ) -> Self {
51        Self {
52            area_style: area_style.into(),
53            baseline,
54            data: iter.into_iter().collect(),
55            state: 0,
56            border_style: (&TRANSPARENT).into(),
57            _p: std::marker::PhantomData,
58        }
59    }
60
61    /**
62    Sets the border style of the area series.
63
64    See [`AreaSeries`] for more information and examples.
65    */
66    pub fn border_style<S: Into<ShapeStyle>>(mut self, style: S) -> Self {
67        self.border_style = style.into();
68        self
69    }
70}
71
72impl<DB: DrawingBackend, X: Clone + 'static, Y: Clone + 'static> Iterator for AreaSeries<DB, X, Y> {
73    type Item = DynElement<'static, DB, (X, Y)>;
74    fn next(&mut self) -> Option<Self::Item> {
75        if self.state == 0 {
76            let mut data: Vec<_> = self.data.clone();
77
78            if !data.is_empty() {
79                data.push((data[data.len() - 1].0.clone(), self.baseline.clone()));
80                data.push((data[0].0.clone(), self.baseline.clone()));
81            }
82
83            self.state = 1;
84
85            Some(Polygon::new(data, self.area_style).into_dyn())
86        } else if self.state == 1 {
87            let data: Vec<_> = self.data.clone();
88
89            self.state = 2;
90
91            Some(PathElement::new(data, self.border_style).into_dyn())
92        } else {
93            None
94        }
95    }
96}