embedded_plots/
single_plot.rs

1use crate::axis::{Axis, Placement, Scale};
2use crate::curve::Curve;
3use embedded_graphics::mono_font::MonoTextStyleBuilder;
4use embedded_graphics::{
5    draw_target::DrawTarget, pixelcolor::PixelColor, prelude::Point, Drawable,
6};
7/// Display agnostic single curve plot object
8#[derive(Clone, Copy)]
9pub struct SinglePlot<'a> {
10    /// curve to be drawn on the plot
11    curve: &'a Curve<'a>,
12    /// range of X axis on which curve will be drawn
13    x_scale: Scale,
14    /// range of Y axis on which curve will be drawn
15    y_scale: Scale,
16}
17impl<'a> SinglePlot<'a> {
18    /// create SinglePlot object with manual range
19    pub fn new(curve: &'a Curve<'a>, x_scale: Scale, y_scale: Scale) -> SinglePlot {
20        SinglePlot {
21            curve,
22            x_scale,
23            y_scale,
24        }
25    }
26    //TODO: add auto range plot constructor
27    /// convert to drawable form for specific display
28    pub fn into_drawable<C: PixelColor + Default>(
29        self,
30        top_left: Point,
31        bottom_right: Point,
32    ) -> DrawableSinglePlot<'a, C> {
33        DrawableSinglePlot {
34            plot: self,
35            color: None,
36            text_color: None,
37            axis_color: None,
38            thickness: None,
39            axis_thickness: None,
40            top_left,
41            bottom_right,
42        }
43    }
44}
45/// Drawable single plot object, constructed for specific display
46pub struct DrawableSinglePlot<'a, C>
47where
48    C: PixelColor + Default,
49{
50    plot: SinglePlot<'a>,
51    color: Option<C>,
52    text_color: Option<C>,
53    axis_color: Option<C>,
54    thickness: Option<usize>,
55    axis_thickness: Option<usize>,
56    top_left: Point,
57    bottom_right: Point,
58}
59/// builder methods to modify plot decoration
60impl<'a, C> DrawableSinglePlot<'a, C>
61where
62    C: PixelColor + Default,
63{
64    pub fn set_color(mut self, color: C) -> DrawableSinglePlot<'a, C> {
65        self.color = Some(color);
66        self
67    }
68    /// if not set, main color will be used
69    pub fn set_text_color(mut self, color: C) -> DrawableSinglePlot<'a, C> {
70        self.text_color = Some(color);
71        self
72    }
73    /// if not set, main color will be used
74    pub fn set_axis_color(mut self, color: C) -> DrawableSinglePlot<'a, C> {
75        self.axis_color = Some(color);
76        self
77    }
78    /// set curve thickness
79    pub fn set_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> {
80        self.thickness = Some(thickness);
81        self
82    }
83    ///set axis thickness
84    pub fn set_axis_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> {
85        self.axis_thickness = Some(thickness);
86        self
87    }
88    //TODO: add axis ticks thickness
89}
90impl<'a, C> Drawable for DrawableSinglePlot<'a, C>
91where
92    C: PixelColor + Default,
93{
94    type Color = C;
95    type Output = ();
96    /// most important function - draw the plot on the display
97    fn draw<D>(&self, display: &mut D) -> Result<Self::Output, D::Error>
98    where
99        D: DrawTarget<Color = C>,
100    {
101        let color = self.color.unwrap_or_default();
102        let text_color = self.text_color.unwrap_or(color);
103        let axis_color = self.axis_color.unwrap_or(color);
104        let thickness = self.thickness.unwrap_or(2);
105        let axis_thickness = self.axis_thickness.unwrap_or(thickness);
106        let text_style = MonoTextStyleBuilder::new().text_color(text_color).build();
107        Axis::new(self.plot.curve.x_range.clone())
108            .set_title("X")
109            .set_scale(self.plot.x_scale)
110            .into_drawable_axis(Placement::X {
111                x1: self.top_left.x,
112                x2: self.bottom_right.x,
113                y: self.bottom_right.y,
114            })
115            .set_color(axis_color)
116            .set_text_style(text_style)
117            .set_tick_size(2)
118            .set_thickness(axis_thickness)
119            .draw(display)?;
120        Axis::new(self.plot.curve.y_range.clone())
121            .set_title("Y")
122            .set_scale(self.plot.y_scale)
123            .into_drawable_axis(Placement::Y {
124                y1: self.top_left.y,
125                y2: self.bottom_right.y,
126                x: self.top_left.x,
127            })
128            .set_color(axis_color)
129            .set_text_style(text_style)
130            .set_tick_size(2)
131            .set_thickness(axis_thickness)
132            .draw(display)?;
133        self.plot
134            .curve
135            .into_drawable_curve(&self.top_left, &self.bottom_right)
136            .set_color(color)
137            .set_thickness(thickness)
138            .draw(display)?;
139        Ok(())
140    }
141}