diff --git a/Cargo.toml b/Cargo.toml index a4cb1d0..68ed282 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,8 @@ edition = "2018" [dependencies] embedded-graphics = "0.6.0" itertools = "0.9.0" +heapless = "0.5.6" [dev-dependencies] embedded-graphics-simulator = "0.2.1" test-case = "1.0.0" - diff --git a/examples/basic-plot/main.rs b/examples/basic-plot/main.rs deleted file mode 100644 index aefa48b..0000000 --- a/examples/basic-plot/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -use embedded_graphics::{ - pixelcolor::Rgb565, - prelude::*, -}; - -use embedded_graphics_simulator::{ - SimulatorDisplay, - Window, - OutputSettingsBuilder -}; - -use embedded_plots::curve::{PlotPoint, Curve}; - -fn main() -> Result<(), core::convert::Infallible> { - let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new(480, 272)); - - let data = vec![ - PlotPoint{x: 0,y: 0}, - PlotPoint{x: 1,y: 1}, - PlotPoint{x: 2,y: 1}, - PlotPoint{x: 3,y: 0}, - ]; - Curve::new(data.as_slice()) - .into_drawable_curve(&(0..3),&(0..1),&Point{x: 20, y: 20}, &Point{x:450,y:250},RgbColor::WHITE) - .draw(&mut display)?; - - let output_settings = OutputSettingsBuilder::new() - .build(); - Window::new("Hello World", &output_settings).show_static(&display); - - Ok(()) -} \ No newline at end of file diff --git a/examples/free_axis.rs b/examples/free_axis.rs new file mode 100644 index 0000000..2376c61 --- /dev/null +++ b/examples/free_axis.rs @@ -0,0 +1,51 @@ +use embedded_graphics::{ + pixelcolor::Rgb565, + prelude::*, +}; + +use embedded_graphics_simulator::{ + SimulatorDisplay, + Window, + OutputSettingsBuilder, + +}; + +use embedded_plots::{ + axis::{Axis,Orientation,Scale}, +}; + +fn main() -> Result<(), core::convert::Infallible> { + let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new(480, 272)); + + Axis::new("X Fixed 0-100(10)",Orientation::X{x1: 10, x2: 230, y: 10},0..100,Scale::Fixed(10),RgbColor::WHITE) + .draw(&mut display)?; + + Axis::new("X Fixed 0-200(100)",Orientation::X{x1: 240, x2: 470, y: 10},0..200,Scale::Fixed(100),RgbColor::YELLOW) + .draw(&mut display)?; + + Axis::new("X Fixed 0-100(7)",Orientation::X{x1: 20, x2: 220, y: 30},0..100,Scale::RangeFraction(7),RgbColor::BLUE) + .draw(&mut display)?; + + Axis::new("X Fixed 0-200(4)",Orientation::X{x1: 250, x2: 460, y: 30},0..200,Scale::RangeFraction(4),RgbColor::RED) + .draw(&mut display)?; + + Axis::new("Y Fixed 0-100(10)",Orientation::Y{y1: 60, y2: 250, x: 90},0..100,Scale::Fixed(10),RgbColor::WHITE) + .draw(&mut display)?; + + Axis::new("Y Fixed 0-200(100)",Orientation::Y{y1: 70, y2: 230, x: 210},0..200,Scale::Fixed(100),RgbColor::YELLOW) + .draw(&mut display)?; + + Axis::new("Y Fixed 0-100(7)",Orientation::Y{y1: 60, y2: 180, x: 330},0..100,Scale::RangeFraction(7),RgbColor::BLUE) + .draw(&mut display)?; + + Axis::new("Y Fixed 0-200(4)",Orientation::Y{y1: 90, y2: 260, x: 450},0..200,Scale::RangeFraction(4),RgbColor::RED) + .draw(&mut display)?; + + + let output_settings = OutputSettingsBuilder::new() + // .pixel_spacing(1) + .build(); + Window::new("Basic plot", &output_settings).show_static(&display); + + Ok(()) +} \ No newline at end of file diff --git a/src/axis.rs b/src/axis.rs index a09c678..32e48ec 100644 --- a/src/axis.rs +++ b/src/axis.rs @@ -3,10 +3,13 @@ use embedded_graphics::drawable::Drawable; use embedded_graphics::DrawTarget; use core::ops::Range; use embedded_graphics::prelude::*; -use embedded_graphics::style::{PrimitiveStyle}; -use core::borrow::Borrow; +use embedded_graphics::style::{PrimitiveStyle, TextStyleBuilder}; +use crate::range_conv::Scalable; +use embedded_graphics::fonts::{Text, Font6x8}; +use heapless::{consts::*, String}; +use core::fmt::Write; -enum Orientation { +pub enum Orientation { X { x1: i32, x2: i32, @@ -19,61 +22,86 @@ enum Orientation { }, } -enum Scale { - Fixed { - interval: usize, - }, - RangeFraction { - fraction: usize, - }, +pub enum Scale { + Fixed(usize), + RangeFraction(usize), } -pub struct Axis { +pub struct Axis<'a, C> { + title: &'a str, orientation: Orientation, range: Range, scale: Scale, - color: C + color: C, } -impl Axis +impl<'a, C> Axis<'a, C> where C: PixelColor, { - fn new(orientation: Orientation, range: Range, scale: Scale, color: C) -> Axis { - Axis { orientation, range, scale, color } + pub fn new(title: &'a str, orientation: Orientation, range: Range, scale: Scale, color: C) -> Axis<'a, C> { + Axis { title, orientation, range, scale, color } } } -impl Drawable for Axis +impl<'a, C> Drawable for Axis<'a, C> where C: PixelColor, { fn draw>(self, display: &mut D) -> Result<(), D::Error> { let lines = match self.scale { - Scale::Fixed { interval } => { - self.range.step_by(interval) + Scale::Fixed(interval) => { + self.range.clone().into_iter().step_by(interval) } - Scale::RangeFraction { fraction } => { + Scale::RangeFraction(fraction) => { let len = self.range.len(); - self.range.step_by(len / fraction) + self.range.clone().into_iter().step_by(len / fraction) } }; + // Create a new text style + let style = TextStyleBuilder::new(Font6x8) + .text_color(self.color) + .build(); match self.orientation { - Orientation::X{x1,x2,y} => { - Line{start: Point{x: x1,y}, end: Point{x: x2,y}} - .into_styled(PrimitiveStyle::with_stroke(self.color,1)) + Orientation::X { x1, x2, y } => { + Line { start: Point { x: x1, y }, end: Point { x: x2, y } } + .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) .draw(display)?; + let title = Text::new(self.title, Point { x: x1, y: y + 10 }) + .into_styled(style); + let title = title.translate(Point { x: (x2 - x1) / 2 - title.size().width as i32 / 2, y: 0 }); + title.draw(display)?; + for line in lines { - line.abs(); + let x = line.scale_between_ranges(&self.range, &(x1..x2)); + Line { start: Point { x, y: y - 2 }, end: Point { x, y: y + 2 } } + .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .draw(display)?; + let mut buf: String:: = String::new(); + write!(buf, "{}", line).unwrap(); + Text::new(&buf, Point { x: x + 1, y: y + 1 }).into_styled(style).draw(display)?; } } - Orientation::Y{y1,y2,x} => { - Line{start: Point{x,y: y1}, end: Point{x,y: y2}} - .into_styled(PrimitiveStyle::with_stroke(self.color,1)) + Orientation::Y { y1, y2, x } => { + Line { start: Point { x, y: y1 }, end: Point { x, y: y2 } } + .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) .draw(display)?; + let title = Text::new(self.title, Point { x, y: y1 }) + .into_styled(style); + let title = title.translate(Point { x: -(title.size().width as i32) - 5, y: (y2-y1)/2 }); + title.draw(display)?; + for line in lines { - line.abs(); + let y = line.scale_between_ranges(&self.range, &(y2..y1)); + Line { start: Point { x: x - 2, y }, end: Point { x: x + 2, y} } + .into_styled(PrimitiveStyle::with_stroke(self.color, 1)) + .draw(display)?; + let mut buf: String:: = String::new(); + write!(buf, "{}", line).unwrap(); + let tick = Text::new(&buf, Point { x, y}).into_styled(style); + let tick = tick.translate(Point{ x: -(tick.size().width as i32), y: 0 }); + tick.draw(display)?; } } } diff --git a/src/lib.rs b/src/lib.rs index b4e540a..60972ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,4 @@ pub mod single_plot; mod drawable_curve; mod range_conv; -mod axis; +pub mod axis;