1use crate::aes::Aesthetic;
2use crate::coord::Coord;
3use crate::data::DataFrame;
4use crate::position::identity::PositionIdentity;
5use crate::position::Position;
6use crate::render::backend::{DrawBackend, RectStyle};
7use crate::render::RenderError;
8use crate::scale::ScaleSet;
9use crate::stat::identity::StatIdentity;
10use crate::stat::Stat;
11use crate::theme::Theme;
12
13use super::{Geom, GeomParams};
14
15pub struct GeomRibbon {
17 pub fill: (u8, u8, u8),
18 pub alpha: f64,
19}
20
21impl Default for GeomRibbon {
22 fn default() -> Self {
23 GeomRibbon {
24 fill: (97, 156, 255),
25 alpha: 0.3,
26 }
27 }
28}
29
30impl Geom for GeomRibbon {
31 fn draw(
32 &self,
33 data: &DataFrame,
34 coord: &dyn Coord,
35 scales: &ScaleSet,
36 _theme: &Theme,
37 backend: &mut dyn DrawBackend,
38 ) -> Result<(), RenderError> {
39 let x_col = data
40 .column("x")
41 .ok_or(RenderError::MissingAesthetic("x".into()))?;
42 let ymin_col = data
43 .column("ymin")
44 .ok_or(RenderError::MissingAesthetic("ymin".into()))?;
45 let ymax_col = data
46 .column("ymax")
47 .ok_or(RenderError::MissingAesthetic("ymax".into()))?;
48
49 let plot_area = backend.plot_area();
50 let x_scale = scales.get(&Aesthetic::X);
51 let y_scale = scales.get(&Aesthetic::Y);
52
53 let mut upper: Vec<(f64, f64)> = Vec::new();
54 let mut lower: Vec<(f64, f64)> = Vec::new();
55
56 for i in 0..data.nrows() {
57 let nx = x_scale.map(|s| s.map(&x_col[i])).unwrap_or(0.0);
58 let ny_max = y_scale.map(|s| s.map(&ymax_col[i])).unwrap_or(0.0);
59 let ny_min = y_scale.map(|s| s.map(&ymin_col[i])).unwrap_or(0.0);
60 upper.push(coord.transform((nx, ny_max), &plot_area));
61 lower.push(coord.transform((nx, ny_min), &plot_area));
62 }
63
64 let mut polygon = upper;
65 lower.reverse();
66 polygon.extend(lower);
67
68 if polygon.len() >= 3 {
69 backend.draw_polygon(
70 &polygon,
71 &RectStyle {
72 fill: Some(self.fill),
73 stroke: None,
74 stroke_width: 0.0,
75 alpha: self.alpha,
76 clip: true,
77 },
78 )?;
79 }
80
81 Ok(())
82 }
83
84 fn required_aes(&self) -> Vec<Aesthetic> {
85 vec![Aesthetic::X, Aesthetic::Ymin, Aesthetic::Ymax]
86 }
87
88 fn default_stat(&self) -> Box<dyn Stat> {
89 Box::new(StatIdentity)
90 }
91 fn default_position(&self) -> Box<dyn Position> {
92 Box::new(PositionIdentity)
93 }
94 fn default_params(&self) -> GeomParams {
95 GeomParams::default()
96 }
97 fn name(&self) -> &str {
98 "ribbon"
99 }
100
101 fn set_series_color(&mut self, color: (u8, u8, u8)) {
102 self.fill = color;
103 }
104}