From a555d74a256af99fcf2350e34ac3a652d623be39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chodzikiewicz?= Date: Thu, 25 Feb 2021 23:53:10 +0100 Subject: [PATCH 1/4] Refactor single_plot to builder pattern --- examples/free_axis.rs | 30 +++++++++----- examples/single_plot_mono.rs | 3 +- examples/single_plot_rgb.rs | 9 ++--- src/axis.rs | 4 +- src/curve.rs | 3 +- src/drawable_axis.rs | 13 +++--- src/drawable_curve.rs | 6 ++- src/polyplot.rs | 1 + src/single_plot.rs | 77 +++++++++++++++++++++++++++++++----- 9 files changed, 108 insertions(+), 38 deletions(-) diff --git a/examples/free_axis.rs b/examples/free_axis.rs index 662662b..1db5319 100644 --- a/examples/free_axis.rs +++ b/examples/free_axis.rs @@ -31,7 +31,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::X{x1: 40, x2: 230, y: 10}, RgbColor::WHITE, text_style_white, - 2 + 2, + 2, ) .draw(&mut display)?; @@ -40,7 +41,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::X{x1: 240, x2: 470, y: 10}, RgbColor::YELLOW, text_style_yellow_compact, - 1 + 1, + 2, ) .draw(&mut display)?; @@ -49,7 +51,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::X{x1: 50, x2: 220, y: 30}, RgbColor::BLUE, text_style_white, - 3 + 3, + 1, ) .draw(&mut display)?; @@ -58,7 +61,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::X{x1: 250, x2: 460, y: 40}, RgbColor::RED, text_style_yellow_compact, - 7 + 7, + 1, ) .draw(&mut display)?; @@ -67,7 +71,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::Y{y1: 70, y2: 230, x: 160}, RgbColor::WHITE, text_style_white, - 2 + 2, + 1, ) .draw(&mut display)?; @@ -76,7 +81,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::Y{y1: 70, y2: 210, x: 260}, RgbColor::YELLOW, text_style_yellow_compact, - 1 + 1, + 1, ) .draw(&mut display)?; @@ -85,7 +91,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::Y{y1: 60, y2: 180, x: 370}, RgbColor::BLUE, text_style_white, - 3 + 3, + 1, ) .draw(&mut display)?; @@ -94,7 +101,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::Y{y1: 90, y2: 220, x: 470}, RgbColor::RED, text_style_yellow_compact, - 7 + 7, + 1, ) .draw(&mut display)?; @@ -103,7 +111,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::X{x1: 30, x2: 470, y: 250}, RgbColor::YELLOW, text_style_white, - 2 + 2, + 1, ) .draw(&mut display)?; @@ -112,7 +121,8 @@ fn main() -> Result<(), core::convert::Infallible> { Placement::Y{y1: 10, y2: 250, x: 30}, RgbColor::WHITE, text_style_white, - 2 + 2, + 1, ) .draw(&mut display)?; diff --git a/examples/single_plot_mono.rs b/examples/single_plot_mono.rs index 569c6ff..5fc011a 100644 --- a/examples/single_plot_mono.rs +++ b/examples/single_plot_mono.rs @@ -27,10 +27,9 @@ fn main() -> Result<(), core::convert::Infallible> { Scale::RangeFraction(3), Scale::RangeFraction(2), ).into_drawable( - BinaryColor::On, Point { x: 18, y: 2 }, Point { x: 120, y: 30 }, - ); + ).set_color(BinaryColor::On); plot.draw(&mut display)?; let output_settings = OutputSettingsBuilder::new() diff --git a/examples/single_plot_rgb.rs b/examples/single_plot_rgb.rs index 87ed2c5..f3c0c29 100644 --- a/examples/single_plot_rgb.rs +++ b/examples/single_plot_rgb.rs @@ -29,13 +29,10 @@ fn main() -> Result<(), core::convert::Infallible> { let plot = SinglePlot::new( &curve, Scale::RangeFraction(3), - Scale::RangeFraction(2), - ) - .into_drawable( - RgbColor::YELLOW, + Scale::RangeFraction(2)).into_drawable( Point { x: 50, y: 10 }, - Point { x: 430, y: 250 } - ); + Point { x: 430, y: 250 }, + ).set_color(RgbColor::YELLOW).set_text_color(RgbColor::WHITE); plot.draw(&mut display)?; let output_settings = OutputSettingsBuilder::new() diff --git a/src/axis.rs b/src/axis.rs index d5a1a42..bf71e42 100644 --- a/src/axis.rs +++ b/src/axis.rs @@ -34,12 +34,12 @@ impl<'a> Axis<'a> Axis{title, range, scale} } - pub fn into_drawable_axis(self, placement: Placement, plot_color: C, text_style: TextStyle, tick_height: usize) -> DrawableAxis<'a, C, F> + pub fn into_drawable_axis(self, placement: Placement, plot_color: C, text_style: TextStyle, tick_height: usize, thickness: usize) -> DrawableAxis<'a, C, F> where C: PixelColor, F: Font, TextStyle: Clone, { - DrawableAxis::new(self.title,placement,self.range,self.scale,plot_color,text_style,tick_height) + DrawableAxis::new(self.title,placement,self.range,self.scale,plot_color,text_style,tick_height,thickness) } } diff --git a/src/curve.rs b/src/curve.rs index 8d32245..e077825 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -44,6 +44,7 @@ impl<'a> Curve<'a> { top_left: &'a Point, bottom_right: &'a Point, color: C, + thickness: usize, ) -> DrawableCurve + '_> where C: PixelColor { @@ -63,7 +64,7 @@ impl<'a> Curve<'a> { &Range { start: bottom_right.y, end: top_left.y }, ), }); - DrawableCurve::new(it, color) + DrawableCurve::new(it, color,thickness) } } diff --git a/src/drawable_axis.rs b/src/drawable_axis.rs index b93359b..48e18fc 100644 --- a/src/drawable_axis.rs +++ b/src/drawable_axis.rs @@ -22,6 +22,7 @@ pub struct DrawableAxis<'a, C, F> color: C, text_style: TextStyle, tick_size: usize, + thickness: usize, } impl<'a, C, F> DrawableAxis<'a, C, F> @@ -30,8 +31,8 @@ impl<'a, C, F> DrawableAxis<'a, C, F> F: Font, TextStyle: Clone, { - pub(in crate) fn new(title: &'a str, placement: Placement, range: Range, scale: Scale, color: C, text_style: TextStyle, tick_height: usize) -> DrawableAxis<'a, C, F> { - DrawableAxis { title, placement, range, scale, color, text_style, tick_size: tick_height } + pub(in crate) fn new(title: &'a str, placement: Placement, range: Range, scale: Scale, color: C, text_style: TextStyle, tick_height: usize, thickness: usize) -> DrawableAxis<'a, C, F> { + DrawableAxis { title, placement, range, scale, color, text_style, tick_size: tick_height, thickness } } pub fn size(&self) -> Point { @@ -59,7 +60,7 @@ impl<'a, C, F> Drawable for DrawableAxis<'a, C, F> match self.placement { Placement::X { x1, x2, y } => { Line { start: Point { x: x1, y }, end: Point { x: x2, y } } - .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) .draw(display)?; let title = Text::new(self.title, Point { x: x1, y: y + 10 }) .into_styled(self.text_style); @@ -69,7 +70,7 @@ impl<'a, C, F> Drawable for DrawableAxis<'a, C, F> for mark in scale_marks { let x = mark.scale_between_ranges(&self.range, &(x1..x2)); Line { start: Point { x, y: y - self.tick_size as i32 }, end: Point { x, y: y + self.tick_size as i32 } } - .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) .draw(display)?; let mut buf: String:: = String::new(); write!(buf, "{}", mark).unwrap(); @@ -78,14 +79,14 @@ impl<'a, C, F> Drawable for DrawableAxis<'a, C, F> } Placement::Y { y1, y2, x } => { Line { start: Point { x, y: y1 }, end: Point { x, y: y2 } } - .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) .draw(display)?; let mut max_tick_text_width = 0; for mark in scale_marks { let y = mark.scale_between_ranges(&self.range, &(y2..y1)); Line { start: Point { x: x - self.tick_size as i32, y }, end: Point { x: x + self.tick_size as i32, y } } - .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) .draw(display)?; let mut buf: String:: = String::new(); write!(buf, "{}", mark).unwrap(); diff --git a/src/drawable_curve.rs b/src/drawable_curve.rs index 4b65cf5..fcc513f 100644 --- a/src/drawable_curve.rs +++ b/src/drawable_curve.rs @@ -9,6 +9,7 @@ pub struct DrawableCurve { scaled_data: I, color: C, + thickness: usize, } impl DrawableCurve @@ -16,10 +17,11 @@ impl DrawableCurve C: PixelColor, I: Iterator, { - pub(in crate) fn new(data: I, color: C) -> DrawableCurve { + pub(in crate) fn new(data: I, color: C, thickness: usize) -> DrawableCurve { DrawableCurve { scaled_data: data, color, + thickness, } } } @@ -29,7 +31,7 @@ impl Drawable for DrawableCurve I: Iterator, { fn draw>(self, display: &mut D) -> Result<(), D::Error> { - let style = PrimitiveStyle::with_stroke(self.color, 2); + let style = PrimitiveStyle::with_stroke(self.color, self.thickness as u32); let mut iter = self.scaled_data.into_iter(); let mut prev = iter.next().unwrap(); for point in iter { diff --git a/src/polyplot.rs b/src/polyplot.rs index 34ae499..6c3984f 100644 --- a/src/polyplot.rs +++ b/src/polyplot.rs @@ -30,6 +30,7 @@ impl<'a, C> Drawable for PolyPlot<'a, C> &self.top_left, &self.bottom_right, *color, + 2 ).draw(display)?; } Ok(()) diff --git a/src/single_plot.rs b/src/single_plot.rs index a1a6d0a..230d962 100644 --- a/src/single_plot.rs +++ b/src/single_plot.rs @@ -18,42 +18,101 @@ impl<'a> SinglePlot<'a> { SinglePlot { curve, x_scale, y_scale } } - pub fn into_drawable(self, color: C, top_left: Point, bottom_right: Point) -> DrawableSinglePlot<'a, C> { - DrawableSinglePlot { plot: self, color, top_left, bottom_right } + pub fn into_drawable(self, top_left: Point, bottom_right: Point) -> DrawableSinglePlot<'a, C> { + DrawableSinglePlot { plot: self, color: None, text_color: None, axis_color: None, thickness: None, axis_thickness: None, top_left, bottom_right } } } pub struct DrawableSinglePlot<'a, C> where - C: PixelColor + C: PixelColor + Default, { plot: SinglePlot<'a>, - color: C, + color: Option, + text_color: Option, + axis_color: Option, + thickness: Option, + axis_thickness: Option, top_left: Point, bottom_right: Point, } +impl<'a, C> DrawableSinglePlot<'a, C> + where + C: PixelColor + Default, +{ + pub fn set_color(mut self, color: C) -> DrawableSinglePlot<'a, C> { + self.color = Some(color); + self + } + + pub fn set_text_color(mut self, color: C) -> DrawableSinglePlot<'a, C> { + self.text_color = Some(color); + self + } + + pub fn set_axis_color(mut self, color: C) -> DrawableSinglePlot<'a, C> { + self.axis_color = Some(color); + self + } + + pub fn set_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> { + self.thickness = Some(thickness); + self + } + + pub fn set_axis_thickness(mut self, thickness: usize) -> DrawableSinglePlot<'a, C> { + self.axis_thickness = Some(thickness); + self + } + +} + impl<'a, C> Drawable for DrawableSinglePlot<'a, C> where - C: PixelColor + C: PixelColor + Default, { fn draw>(self, display: &mut D) -> Result<(), D::Error> { + let color = match self.color { + None => C::default(), + Some(c) => c, + }; + let text_color = match self.text_color { + None => color, + Some(c) => c, + }; + let axis_color = match self.axis_color { + None => color, + Some(c) => c, + }; + + let thickness = match self.thickness { + None => 2, + Some(t) => t, + }; + + let axis_thickness = match self.axis_thickness { + None => thickness, + Some(t) => t, + }; + let text_style = TextStyleBuilder::new(Font6x8) - .text_color(self.color) + .text_color(text_color) .build(); Axis::new("X", self.plot.curve.x_range.clone(), self.plot.x_scale) - .into_drawable_axis(Placement::X { x1: self.top_left.x, x2: self.bottom_right.x, y: self.bottom_right.y }, self.color, text_style, 2) + .into_drawable_axis(Placement::X { x1: self.top_left.x, x2: self.bottom_right.x, y: self.bottom_right.y }, axis_color, text_style, 2, axis_thickness) .draw(display)?; Axis::new("Y", self.plot.curve.y_range.clone(), self.plot.y_scale) - .into_drawable_axis(Placement::Y { y1: self.top_left.y, y2: self.bottom_right.y, x: self.top_left.x }, self.color, text_style, 2) + .into_drawable_axis(Placement::Y { y1: self.top_left.y, y2: self.bottom_right.y, x: self.top_left.x }, axis_color, text_style, 2,axis_thickness) .draw(display)?; self.plot.curve.into_drawable_curve( &self.top_left, &self.bottom_right, - self.color, + color, + thickness, ).draw(display)?; Ok(()) } From 5139122a958b1c66802b91560169d70b0a29f6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chodzikiewicz?= Date: Fri, 26 Feb 2021 01:03:14 +0100 Subject: [PATCH 2/4] Refactor curve to builder pattern --- src/curve.rs | 65 +++++++++++++++++++++++++++++++++++++++---- src/drawable_curve.rs | 45 ------------------------------ src/lib.rs | 1 - src/polyplot.rs | 8 +++--- src/single_plot.rs | 6 ++-- 5 files changed, 67 insertions(+), 58 deletions(-) delete mode 100644 src/drawable_curve.rs diff --git a/src/curve.rs b/src/curve.rs index e077825..0036141 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -1,10 +1,16 @@ use core::ops::{Range}; use crate::range_conv::Scalable; -use crate::drawable_curve::DrawableCurve; -use embedded_graphics::prelude::*; use itertools::{Itertools, MinMaxResult::MinMax, MinMaxResult}; +use embedded_graphics::drawable::{Drawable}; +use embedded_graphics::DrawTarget; +use embedded_graphics::geometry::Point; +use embedded_graphics::pixelcolor::{PixelColor}; +use embedded_graphics::primitives::{Line, Primitive}; +use embedded_graphics::style::PrimitiveStyle; + + pub struct PlotPoint { pub x: i32, pub y: i32, @@ -43,8 +49,6 @@ impl<'a> Curve<'a> { pub fn into_drawable_curve(&self, top_left: &'a Point, bottom_right: &'a Point, - color: C, - thickness: usize, ) -> DrawableCurve + '_> where C: PixelColor { @@ -64,10 +68,61 @@ impl<'a> Curve<'a> { &Range { start: bottom_right.y, end: top_left.y }, ), }); - DrawableCurve::new(it, color,thickness) + DrawableCurve { + scaled_data: it, + color: None, + thickness: None, + } } } +pub struct DrawableCurve +{ + scaled_data: I, + color: Option, + thickness: Option, +} + +impl DrawableCurve + where + C: PixelColor, + I: Iterator, +{ + pub fn set_color(mut self, color: C) -> DrawableCurve { + self.color = Some(color); + self + } + pub fn set_thickness(mut self, thickness: usize) -> DrawableCurve { + self.thickness = Some(thickness); + self + } +} + +impl Drawable for DrawableCurve + where C: PixelColor + Default, + I: Iterator, +{ + fn draw>(self, display: &mut D) -> Result<(), D::Error> { + let color = match self.color { + None => C::default(), + Some(c) => c, + }; + let thickness = match self.thickness { + None => 2, + Some(t) => t, + }; + let style = PrimitiveStyle::with_stroke(color, thickness as u32); + let mut iter = self.scaled_data.into_iter(); + let mut prev = iter.next().unwrap(); + for point in iter { + Line::new(prev, point) + .into_styled(style) + .draw(display)?; + prev = point; + } + Ok(()) + } +} #[cfg(test)] mod tests { diff --git a/src/drawable_curve.rs b/src/drawable_curve.rs deleted file mode 100644 index fcc513f..0000000 --- a/src/drawable_curve.rs +++ /dev/null @@ -1,45 +0,0 @@ -use embedded_graphics::drawable::{Drawable}; -use embedded_graphics::DrawTarget; -use embedded_graphics::geometry::Point; -use embedded_graphics::pixelcolor::{PixelColor}; -use embedded_graphics::primitives::{Line, Primitive}; -use embedded_graphics::style::PrimitiveStyle; - -pub struct DrawableCurve -{ - scaled_data: I, - color: C, - thickness: usize, -} - -impl DrawableCurve - where - C: PixelColor, - I: Iterator, -{ - pub(in crate) fn new(data: I, color: C, thickness: usize) -> DrawableCurve { - DrawableCurve { - scaled_data: data, - color, - thickness, - } - } -} - -impl Drawable for DrawableCurve - where C: PixelColor, - I: Iterator, -{ - fn draw>(self, display: &mut D) -> Result<(), D::Error> { - let style = PrimitiveStyle::with_stroke(self.color, self.thickness as u32); - let mut iter = self.scaled_data.into_iter(); - let mut prev = iter.next().unwrap(); - for point in iter { - Line::new(prev, point) - .into_styled(style) - .draw(display)?; - prev = point; - } - Ok(()) - } -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a41e3cb..fafaba5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,5 @@ pub mod axis; pub mod polyplot; pub mod single_plot; -mod drawable_curve; mod range_conv; mod drawable_axis; diff --git a/src/polyplot.rs b/src/polyplot.rs index 6c3984f..279d1c7 100644 --- a/src/polyplot.rs +++ b/src/polyplot.rs @@ -22,16 +22,16 @@ impl<'a, C> PolyPlot<'a, C> impl<'a, C> Drawable for PolyPlot<'a, C> where - C: PixelColor + C: PixelColor + Default, { fn draw>(self, display: &mut D) -> Result<(), D::Error> { for (curve, color) in self.curves { curve.into_drawable_curve( &self.top_left, &self.bottom_right, - *color, - 2 - ).draw(display)?; + ).set_color(*color) + .set_thickness(2) + .draw(display)?; } Ok(()) } diff --git a/src/single_plot.rs b/src/single_plot.rs index 230d962..59b233b 100644 --- a/src/single_plot.rs +++ b/src/single_plot.rs @@ -111,9 +111,9 @@ impl<'a, C> Drawable for DrawableSinglePlot<'a, C> self.plot.curve.into_drawable_curve( &self.top_left, &self.bottom_right, - color, - thickness, - ).draw(display)?; + ).set_color(color) + .set_thickness(thickness) + .draw(display)?; Ok(()) } } \ No newline at end of file From 76c399ac6c7b9bd4c2db6b141112f9cc1a0958b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chodzikiewicz?= Date: Tue, 2 Mar 2021 21:18:53 +0100 Subject: [PATCH 3/4] Refactor axis to builder pattern --- examples/free_axis.rs | 149 ++++++++++++++++++-------------------- src/axis.rs | 165 +++++++++++++++++++++++++++++++++++++++--- src/drawable_axis.rs | 106 --------------------------- src/lib.rs | 3 +- src/single_plot.rs | 47 ++++++------ 5 files changed, 247 insertions(+), 223 deletions(-) delete mode 100644 src/drawable_axis.rs diff --git a/examples/free_axis.rs b/examples/free_axis.rs index 1db5319..b47b82c 100644 --- a/examples/free_axis.rs +++ b/examples/free_axis.rs @@ -26,104 +26,97 @@ fn main() -> Result<(), core::convert::Infallible> { .text_color(RgbColor::YELLOW) .build(); - Axis::new("X Fixed 0-100(10)", 0..100, Scale::Fixed(10)) - .into_drawable_axis( - Placement::X{x1: 40, x2: 230, y: 10}, - RgbColor::WHITE, - text_style_white, - 2, - 2, - ) + Axis::new(0..100) + .set_title("X Fixed 0-100(10)") + .set_scale(Scale::Fixed(10)) + .into_drawable_axis(Placement::X { x1: 40, x2: 230, y: 10 }) + .set_color(RgbColor::WHITE) + .set_text_style(text_style_white) + .set_thickness(2) + .set_tick_size(2) .draw(&mut display)?; - Axis::new("X Fixed 0-200(100)", 0..200, Scale::Fixed(100)) - .into_drawable_axis( - Placement::X{x1: 240, x2: 470, y: 10}, - RgbColor::YELLOW, - text_style_yellow_compact, - 1, - 2, - ) + Axis::new(0..200) + .set_title("X Fixed 0-200(100)") + .set_scale(Scale::Fixed(100)) + .into_drawable_axis(Placement::X { x1: 240, x2: 470, y: 10 }) + .set_color(RgbColor::YELLOW) + .set_text_style(text_style_yellow_compact) + .set_tick_size(2) .draw(&mut display)?; - Axis::new("X Frac 0-100(7)", 0..100, Scale::RangeFraction(7)) - .into_drawable_axis( - Placement::X{x1: 50, x2: 220, y: 30}, - RgbColor::BLUE, - text_style_white, - 3, - 1, - ) + Axis::new(0..100) + .set_title("X Frac 0-100(7)") + .set_scale(Scale::RangeFraction(7)) + .into_drawable_axis(Placement::X { x1: 50, x2: 220, y: 30 }) + .set_color(RgbColor::BLUE) + .set_text_style(text_style_white) + .set_tick_size(3) .draw(&mut display)?; - Axis::new("X Frac 0-200(4)", 0..200, Scale::RangeFraction(4)) - .into_drawable_axis( - Placement::X{x1: 250, x2: 460, y: 40}, - RgbColor::RED, - text_style_yellow_compact, - 7, - 1, - ) + Axis::new(0..200) + .set_title("X Frac 0-200(4)") + .set_scale(Scale::RangeFraction(4)) + .into_drawable_axis(Placement::X { x1: 250, x2: 460, y: 40 }) + .set_color(RgbColor::RED) + .set_text_style(text_style_yellow_compact) + .set_tick_size(7) .draw(&mut display)?; - Axis::new("Y Fixed 0-100(10)", 0..100, Scale::Fixed(10)) + Axis::new(0..100) + .set_title("Y Fixed 0-100(10)") + .set_scale(Scale::Fixed(10)) .into_drawable_axis( - Placement::Y{y1: 70, y2: 230, x: 160}, - RgbColor::WHITE, - text_style_white, - 2, - 1, - ) + Placement::Y { y1: 70, y2: 230, x: 160 }) + .set_color(RgbColor::WHITE) + .set_text_style(text_style_white) + .set_tick_size(2) .draw(&mut display)?; - Axis::new("Y Fixed 0-200(100)", 0..200, Scale::Fixed(100)) + Axis::new(0..200) + .set_title("Y Fixed 0-200(100)") + .set_scale(Scale::Fixed(100)) .into_drawable_axis( - Placement::Y{y1: 70, y2: 210, x: 260}, - RgbColor::YELLOW, - text_style_yellow_compact, - 1, - 1, - ) + Placement::Y { y1: 70, y2: 210, x: 260 }) + .set_color(RgbColor::YELLOW) + .set_text_style(text_style_yellow_compact) + .set_tick_size(1) .draw(&mut display)?; - Axis::new("Y Frac 0-100(7)", 0..100, Scale::RangeFraction(7)) - .into_drawable_axis( - Placement::Y{y1: 60, y2: 180, x: 370}, - RgbColor::BLUE, - text_style_white, - 3, - 1, - ) + Axis::new(0..100) + .set_title("Y Frac 0-100(7)") + .set_scale(Scale::RangeFraction(7)) + .into_drawable_axis(Placement::Y { y1: 60, y2: 180, x: 370 }) + .set_color(RgbColor::BLUE) + .set_text_style(text_style_white) + .set_tick_size(3) .draw(&mut display)?; - Axis::new("Y Frac 0-200(4)", 0..200, Scale::RangeFraction(4)) - .into_drawable_axis( - Placement::Y{y1: 90, y2: 220, x: 470}, - RgbColor::RED, - text_style_yellow_compact, - 7, - 1, - ) + Axis::new(0..200) + .set_title("Y Frac 0-200(4)") + .set_scale(Scale::RangeFraction(4)) + .into_drawable_axis(Placement::Y { y1: 90, y2: 220, x: 470 }) + .set_color(RgbColor::RED) + .set_text_style(text_style_yellow_compact) + .set_tick_size(7) .draw(&mut display)?; - Axis::new("X", 123..2137, Scale::Fixed(150)) - .into_drawable_axis( - Placement::X{x1: 30, x2: 470, y: 250}, - RgbColor::YELLOW, - text_style_white, - 2, - 1, - ) + Axis::new(123..2137) + .set_title("X") + .set_scale(Scale::Fixed(150)) + .into_drawable_axis(Placement::X { x1: 30, x2: 470, y: 250 }) + .set_color(RgbColor::YELLOW) + .set_text_style(text_style_white) + .set_tick_size(2) .draw(&mut display)?; - Axis::new("Y", 0..2137, Scale::RangeFraction(15)) - .into_drawable_axis( - Placement::Y{y1: 10, y2: 250, x: 30}, - RgbColor::WHITE, - text_style_white, - 2, - 1, - ) + Axis::new(0..2137) + .set_title("Y") + .set_scale(Scale::RangeFraction(15)) + .into_drawable_axis(Placement::Y { y1: 10, y2: 250, x: 30 }) + .set_color(RgbColor::WHITE) + .set_text_style(text_style_white) + .set_tick_size(2) .draw(&mut display)?; diff --git a/src/axis.rs b/src/axis.rs index bf71e42..f3e8ab3 100644 --- a/src/axis.rs +++ b/src/axis.rs @@ -1,8 +1,15 @@ use core::ops::Range; -use embedded_graphics::prelude::*; -use embedded_graphics::style::{TextStyle}; +use core::fmt::Write; +use heapless::{consts::*, String}; + +use embedded_graphics::{ + prelude::*, + style::{TextStyle, PrimitiveStyle}, + primitives::Line, + fonts::Text, +}; +use crate::range_conv::Scalable; -use crate::drawable_axis::DrawableAxis; pub enum Placement { X { @@ -22,24 +29,160 @@ pub enum Scale { RangeFraction(usize), } +impl Default for Scale { + fn default() -> Self { + Scale::RangeFraction(5) + } +} + pub struct Axis<'a> { - title: &'a str, range: Range, - scale: Scale, + title: Option<&'a str>, + scale: Option, } impl<'a> Axis<'a> { - pub fn new(title: &'a str, range: Range, scale: Scale) -> Axis<'a> { - Axis{title, range, scale} + pub fn new(range: Range) -> Axis<'a> { + Axis { range, title: None, scale: None } } - pub fn into_drawable_axis(self, placement: Placement, plot_color: C, text_style: TextStyle, tick_height: usize, thickness: usize) -> DrawableAxis<'a, C, F> + pub fn set_scale(mut self, scale: Scale) -> Axis<'a> { + self.scale = Some(scale); + self + } + + pub fn set_title(mut self, title: &'a str) -> Axis<'a> { + self.title = Some(title); + self + } + + pub fn into_drawable_axis(self, placement: Placement) -> DrawableAxis<'a, C, F> where - C: PixelColor, + C: PixelColor + Default, F: Font, - TextStyle: Clone, + TextStyle: Clone + Default, { - DrawableAxis::new(self.title,placement,self.range,self.scale,plot_color,text_style,tick_height,thickness) + DrawableAxis{ + axis: self, + placement, + color: None, + text_style: None, + tick_size: None, + thickness: None, + } } } + +pub struct DrawableAxis<'a, C, F> + where + C: PixelColor, + F: Font, + TextStyle: Clone + Default, +{ + axis: Axis<'a>, + placement: Placement, + color: Option, + text_style: Option>, + tick_size: Option, + thickness: Option, +} + +impl<'a, C, F> DrawableAxis<'a, C, F> + where + C: PixelColor + Default, + F: Font, + TextStyle: Clone + Default, +{ + pub fn set_color(mut self, val: C) -> DrawableAxis<'a, C, F> { + self.color = Some(val); + self + } + pub fn set_text_style(mut self, val: TextStyle) -> DrawableAxis<'a, C, F> { + self.text_style = Some(val); + self + } + pub fn set_tick_size(mut self, val: usize) -> DrawableAxis<'a, C, F> { + self.tick_size = Some(val); + self + } + pub fn set_thickness(mut self, val: usize) -> DrawableAxis<'a, C, F> { + self.thickness = Some(val); + self + } +} + + +impl<'a, C, F> Drawable for DrawableAxis<'a, C, F> + where + C: PixelColor + Default, + F: Font + Copy, + TextStyle: Clone + Default, +{ + fn draw>(self, display: &mut D) -> Result<(), D::Error> { + let color = self.color.unwrap_or_default(); + let text_style = self.text_style.unwrap_or_default(); + let thickness = self.thickness.unwrap_or(1); + let tick_size = self.tick_size.unwrap_or(2); + + + let scale_marks = match self.axis.scale.unwrap_or_default() { + Scale::Fixed(interval) => { + self.axis.range.clone().into_iter().step_by(interval) + } + Scale::RangeFraction(fraction) => { + let len = self.axis.range.len(); + self.axis.range.clone().into_iter().step_by(len / fraction) + } + }; + match self.placement { + Placement::X { x1, x2, y } => { + Line { start: Point { x: x1, y }, end: Point { x: x2, y } } + .into_styled(PrimitiveStyle::with_stroke(color, thickness as u32)) + .draw(display)?; + if let Some(title) = self.axis.title { + let title = Text::new(title, Point { x: x1, y: y + 10 }) + .into_styled(text_style); + let title = title.translate(Point { x: (x2 - x1) / 2 - title.size().width as i32 / 2, y: 0 }); + title.draw(display)?; + } + + for mark in scale_marks { + let x = mark.scale_between_ranges(&self.axis.range, &(x1..x2)); + Line { start: Point { x, y: y - tick_size as i32 }, end: Point { x, y: y + tick_size as i32 } } + .into_styled(PrimitiveStyle::with_stroke(color, thickness as u32)) + .draw(display)?; + let mut buf: String:: = String::new(); + write!(buf, "{}", mark).unwrap(); + Text::new(&buf, Point { x: x + 2, y: y + 2 }).into_styled(text_style).draw(display)?; + } + } + Placement::Y { y1, y2, x } => { + Line { start: Point { x, y: y1 }, end: Point { x, y: y2 } } + .into_styled(PrimitiveStyle::with_stroke(color, thickness as u32)) + .draw(display)?; + + let mut max_tick_text_width = 0; + for mark in scale_marks { + let y = mark.scale_between_ranges(&self.axis.range, &(y2..y1)); + Line { start: Point { x: x - tick_size as i32, y }, end: Point { x: x + tick_size as i32, y } } + .into_styled(PrimitiveStyle::with_stroke(color, thickness as u32)) + .draw(display)?; + let mut buf: String:: = String::new(); + write!(buf, "{}", mark).unwrap(); + let tick_val = Text::new(&buf, Point { x, y }).into_styled(text_style); + let tick_val = tick_val.translate(Point { x: -(tick_val.size().width as i32) - 2, y: 2 }); + if tick_val.size().width > max_tick_text_width { max_tick_text_width = tick_val.size().width } + tick_val.draw(display)?; + } + if let Some(title) = self.axis.title { + let title = Text::new(title, Point { x, y: y1 }) + .into_styled(text_style); + let title = title.translate(Point { x: -(title.size().width as i32) - max_tick_text_width as i32 - tick_size as i32 - 2, y: (y2 - y1) / 2 }); + title.draw(display)?; + } + } + } + Ok(()) + } +} \ No newline at end of file diff --git a/src/drawable_axis.rs b/src/drawable_axis.rs deleted file mode 100644 index 48e18fc..0000000 --- a/src/drawable_axis.rs +++ /dev/null @@ -1,106 +0,0 @@ -use embedded_graphics::prelude::*; -use crate::axis::{Placement, Scale}; -use core::ops::Range; -use embedded_graphics::style::{TextStyle, PrimitiveStyle}; -use embedded_graphics::fonts::Text; -use crate::range_conv::Scalable; -use embedded_graphics::primitives::Line; -use heapless::{consts::*, String}; -use core::fmt::Write; - - -pub struct DrawableAxis<'a, C, F> - where - C: PixelColor, - F: Font, - TextStyle: Clone, -{ - title: &'a str, - placement: Placement, - range: Range, - scale: Scale, - color: C, - text_style: TextStyle, - tick_size: usize, - thickness: usize, -} - -impl<'a, C, F> DrawableAxis<'a, C, F> - where - C: PixelColor, - F: Font, - TextStyle: Clone, -{ - pub(in crate) fn new(title: &'a str, placement: Placement, range: Range, scale: Scale, color: C, text_style: TextStyle, tick_height: usize, thickness: usize) -> DrawableAxis<'a, C, F> { - DrawableAxis { title, placement, range, scale, color, text_style, tick_size: tick_height, thickness } - } - - pub fn size(&self) -> Point { - Point { x: 50, y: 50 } - } -} - - -impl<'a, C, F> Drawable for DrawableAxis<'a, C, F> - where - C: PixelColor, - F: Font + Copy, - TextStyle: Clone, -{ - fn draw>(self, display: &mut D) -> Result<(), D::Error> { - let scale_marks = match self.scale { - Scale::Fixed(interval) => { - self.range.clone().into_iter().step_by(interval) - } - Scale::RangeFraction(fraction) => { - let len = self.range.len(); - self.range.clone().into_iter().step_by(len / fraction) - } - }; - match self.placement { - Placement::X { x1, x2, y } => { - Line { start: Point { x: x1, y }, end: Point { x: x2, y } } - .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) - .draw(display)?; - let title = Text::new(self.title, Point { x: x1, y: y + 10 }) - .into_styled(self.text_style); - let title = title.translate(Point { x: (x2 - x1) / 2 - title.size().width as i32 / 2, y: 0 }); - title.draw(display)?; - - for mark in scale_marks { - let x = mark.scale_between_ranges(&self.range, &(x1..x2)); - Line { start: Point { x, y: y - self.tick_size as i32 }, end: Point { x, y: y + self.tick_size as i32 } } - .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) - .draw(display)?; - let mut buf: String:: = String::new(); - write!(buf, "{}", mark).unwrap(); - Text::new(&buf, Point { x: x + 2, y: y + 2 }).into_styled(self.text_style).draw(display)?; - } - } - Placement::Y { y1, y2, x } => { - Line { start: Point { x, y: y1 }, end: Point { x, y: y2 } } - .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) - .draw(display)?; - - let mut max_tick_text_width = 0; - for mark in scale_marks { - let y = mark.scale_between_ranges(&self.range, &(y2..y1)); - Line { start: Point { x: x - self.tick_size as i32, y }, end: Point { x: x + self.tick_size as i32, y } } - .into_styled(PrimitiveStyle::with_stroke(self.color, self.thickness as u32)) - .draw(display)?; - let mut buf: String:: = String::new(); - write!(buf, "{}", mark).unwrap(); - let tick_val = Text::new(&buf, Point { x, y }).into_styled(self.text_style); - let tick_val = tick_val.translate(Point { x: -(tick_val.size().width as i32) - 2, y: 2 }); - if tick_val.size().width > max_tick_text_width { max_tick_text_width = tick_val.size().width } - tick_val.draw(display)?; - } - let title = Text::new(self.title, Point { x, y: y1 }) - .into_styled(self.text_style); - let title = title.translate(Point { x: -(title.size().width as i32) - max_tick_text_width as i32 - self.tick_size as i32 - 2, y: (y2 - y1) / 2 }); - title.draw(display)?; - } - } - Ok(()) - } -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index fafaba5..3b7e2e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,5 +5,4 @@ pub mod axis; pub mod polyplot; pub mod single_plot; -mod range_conv; -mod drawable_axis; +mod range_conv; \ No newline at end of file diff --git a/src/single_plot.rs b/src/single_plot.rs index 59b233b..58f5ddc 100644 --- a/src/single_plot.rs +++ b/src/single_plot.rs @@ -73,39 +73,34 @@ impl<'a, C> Drawable for DrawableSinglePlot<'a, C> C: PixelColor + Default, { fn draw>(self, display: &mut D) -> Result<(), D::Error> { - let color = match self.color { - None => C::default(), - Some(c) => c, - }; - let text_color = match self.text_color { - None => color, - Some(c) => c, - }; - let axis_color = match self.axis_color { - None => color, - Some(c) => c, - }; - - let thickness = match self.thickness { - None => 2, - Some(t) => t, - }; - - let axis_thickness = match self.axis_thickness { - None => thickness, - Some(t) => t, - }; + let color = self.color.unwrap_or_default(); + let text_color = self.text_color.unwrap_or(color); + let axis_color = self.axis_color.unwrap_or(color); + let thickness = self.thickness.unwrap_or(2); + let axis_thickness = self.axis_thickness.unwrap_or(thickness); let text_style = TextStyleBuilder::new(Font6x8) .text_color(text_color) .build(); - Axis::new("X", self.plot.curve.x_range.clone(), self.plot.x_scale) - .into_drawable_axis(Placement::X { x1: self.top_left.x, x2: self.bottom_right.x, y: self.bottom_right.y }, axis_color, text_style, 2, axis_thickness) + Axis::new( self.plot.curve.x_range.clone()) + .set_title("X") + .set_scale(self.plot.x_scale) + .into_drawable_axis(Placement::X { x1: self.top_left.x, x2: self.bottom_right.x, y: self.bottom_right.y }) + .set_color(axis_color) + .set_text_style(text_style) + .set_tick_size(2) + .set_thickness(axis_thickness) .draw(display)?; - Axis::new("Y", self.plot.curve.y_range.clone(), self.plot.y_scale) - .into_drawable_axis(Placement::Y { y1: self.top_left.y, y2: self.bottom_right.y, x: self.top_left.x }, axis_color, text_style, 2,axis_thickness) + Axis::new(self.plot.curve.y_range.clone()) + .set_title("Y") + .set_scale(self.plot.y_scale) + .into_drawable_axis(Placement::Y { y1: self.top_left.y, y2: self.bottom_right.y, x: self.top_left.x }) + .set_color(axis_color) + .set_text_style(text_style) + .set_tick_size(2) + .set_thickness(axis_thickness) .draw(display)?; self.plot.curve.into_drawable_curve( From 16231f31b36163c69cf2fe76a29c68bda52b7043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chodzikiewicz?= Date: Tue, 2 Mar 2021 21:19:26 +0100 Subject: [PATCH 4/4] Remove polyplot --- examples/polyplot_mono.rs | 50 --------------------------------------- examples/polyplot_rgb.rs | 49 -------------------------------------- src/lib.rs | 1 - src/polyplot.rs | 38 ----------------------------- 4 files changed, 138 deletions(-) delete mode 100644 examples/polyplot_mono.rs delete mode 100644 examples/polyplot_rgb.rs delete mode 100644 src/polyplot.rs diff --git a/examples/polyplot_mono.rs b/examples/polyplot_mono.rs deleted file mode 100644 index d767a12..0000000 --- a/examples/polyplot_mono.rs +++ /dev/null @@ -1,50 +0,0 @@ -use embedded_graphics::{ - pixelcolor::BinaryColor, - prelude::*, -}; - -use embedded_graphics_simulator::{ - SimulatorDisplay, - Window, - OutputSettingsBuilder, - BinaryColorTheme -}; - -use embedded_plots::{ - polyplot::{PolyPlot}, - curve::{PlotPoint, Curve}, -}; - -fn main() -> Result<(), core::convert::Infallible> { - let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new(128, 48)); - - let data1 = vec![ - PlotPoint { x: 0, y: 0 }, - PlotPoint { x: 1, y: 1 }, - PlotPoint { x: 2, y: 1 }, - PlotPoint { x: 3, y: 0 }, - ]; - - let data2 = vec![ - PlotPoint { x: 0, y: 1 }, - PlotPoint { x: 1, y: 0 }, - PlotPoint { x: 2, y: 3 }, - PlotPoint { x: 3, y: 2 }, - PlotPoint { x: 4, y: 2 }, - ]; - - let curves = vec![ - (Curve::from_data(data1.as_slice()), BinaryColor::On), - (Curve::from_data(data2.as_slice()), BinaryColor::On), - ]; - - let plot = PolyPlot::new(curves.as_slice(), Point { x: 10, y: 3 }, Point { x: 120, y: 45 }); - - plot.draw(&mut display)?; - let output_settings = OutputSettingsBuilder::new() - .theme(BinaryColorTheme::OledBlue) - .build(); - Window::new("Basic plot", &output_settings).show_static(&display); - - Ok(()) -} \ No newline at end of file diff --git a/examples/polyplot_rgb.rs b/examples/polyplot_rgb.rs deleted file mode 100644 index 056e3d5..0000000 --- a/examples/polyplot_rgb.rs +++ /dev/null @@ -1,49 +0,0 @@ -use embedded_graphics::{ - pixelcolor::Rgb565, - prelude::*, -}; - -use embedded_graphics_simulator::{ - SimulatorDisplay, - Window, - OutputSettingsBuilder, - -}; - -use embedded_plots::{ - polyplot::{PolyPlot}, - curve::{PlotPoint, Curve}, -}; - -fn main() -> Result<(), core::convert::Infallible> { - let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new(480, 272)); - - let data1 = vec![ - PlotPoint { x: 0, y: 0 }, - PlotPoint { x: 1, y: 1 }, - PlotPoint { x: 2, y: 1 }, - PlotPoint { x: 3, y: 0 }, - ]; - - let data2 = vec![ - PlotPoint { x: 0, y: 1 }, - PlotPoint { x: 1, y: 0 }, - PlotPoint { x: 2, y: 3 }, - PlotPoint { x: 3, y: 2 }, - PlotPoint { x: 4, y: 2 }, - ]; - - let curves = vec![ - (Curve::from_data(data1.as_slice()), RgbColor::YELLOW), - (Curve::from_data(data2.as_slice()), RgbColor::RED), - ]; - - let plot = PolyPlot::new(curves.as_slice(), Point { x: 10, y: 10 }, Point { x: 470, y: 260 }); - - plot.draw(&mut display)?; - let output_settings = OutputSettingsBuilder::new() - .build(); - Window::new("Basic plot", &output_settings).show_static(&display); - - Ok(()) -} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 3b7e2e2..7b2b50c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ pub mod curve; pub mod axis; -pub mod polyplot; pub mod single_plot; mod range_conv; \ No newline at end of file diff --git a/src/polyplot.rs b/src/polyplot.rs deleted file mode 100644 index 279d1c7..0000000 --- a/src/polyplot.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::curve::Curve; -use embedded_graphics::drawable::Drawable; -use embedded_graphics::DrawTarget; -use embedded_graphics::prelude::Point; -use embedded_graphics::pixelcolor::PixelColor; - -pub struct PolyPlot<'a, C> -{ - curves: &'a [(Curve<'a>, C)], - top_left: Point, - bottom_right: Point, -} - -impl<'a, C> PolyPlot<'a, C> - where - C: PixelColor -{ - pub fn new(curves: &'a [(Curve<'a>, C)], top_left: Point, bottom_right: Point) -> PolyPlot { - PolyPlot { curves, top_left, bottom_right } - } -} - -impl<'a, C> Drawable for PolyPlot<'a, C> - where - C: PixelColor + Default, -{ - fn draw>(self, display: &mut D) -> Result<(), D::Error> { - for (curve, color) in self.curves { - curve.into_drawable_curve( - &self.top_left, - &self.bottom_right, - ).set_color(*color) - .set_thickness(2) - .draw(display)?; - } - Ok(()) - } -} \ No newline at end of file