Dirty axis implementation

This commit is contained in:
Michał Chodzikiewicz 2020-12-30 16:33:08 +01:00
parent 1f0e729777
commit 975cf9b38a
5 changed files with 109 additions and 62 deletions

View file

@ -9,8 +9,8 @@ edition = "2018"
[dependencies] [dependencies]
embedded-graphics = "0.6.0" embedded-graphics = "0.6.0"
itertools = "0.9.0" itertools = "0.9.0"
heapless = "0.5.6"
[dev-dependencies] [dev-dependencies]
embedded-graphics-simulator = "0.2.1" embedded-graphics-simulator = "0.2.1"
test-case = "1.0.0" test-case = "1.0.0"

View file

@ -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<Rgb565> = 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(())
}

51
examples/free_axis.rs Normal file
View file

@ -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<Rgb565> = 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(())
}

View file

@ -3,10 +3,13 @@ use embedded_graphics::drawable::Drawable;
use embedded_graphics::DrawTarget; use embedded_graphics::DrawTarget;
use core::ops::Range; use core::ops::Range;
use embedded_graphics::prelude::*; use embedded_graphics::prelude::*;
use embedded_graphics::style::{PrimitiveStyle}; use embedded_graphics::style::{PrimitiveStyle, TextStyleBuilder};
use core::borrow::Borrow; 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 { X {
x1: i32, x1: i32,
x2: i32, x2: i32,
@ -19,61 +22,86 @@ enum Orientation {
}, },
} }
enum Scale { pub enum Scale {
Fixed { Fixed(usize),
interval: usize, RangeFraction(usize),
},
RangeFraction {
fraction: usize,
},
} }
pub struct Axis<C> { pub struct Axis<'a, C> {
title: &'a str,
orientation: Orientation, orientation: Orientation,
range: Range<i32>, range: Range<i32>,
scale: Scale, scale: Scale,
color: C color: C,
} }
impl<C> Axis<C> impl<'a, C> Axis<'a, C>
where where
C: PixelColor, C: PixelColor,
{ {
fn new(orientation: Orientation, range: Range<i32>, scale: Scale, color: C) -> Axis<C> { pub fn new(title: &'a str, orientation: Orientation, range: Range<i32>, scale: Scale, color: C) -> Axis<'a, C> {
Axis { orientation, range, scale, color } Axis { title, orientation, range, scale, color }
} }
} }
impl<C> Drawable<C> for Axis<C> impl<'a, C> Drawable<C> for Axis<'a, C>
where where
C: PixelColor, C: PixelColor,
{ {
fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> { fn draw<D: DrawTarget<C>>(self, display: &mut D) -> Result<(), D::Error> {
let lines = match self.scale { let lines = match self.scale {
Scale::Fixed { interval } => { Scale::Fixed(interval) => {
self.range.step_by(interval) self.range.clone().into_iter().step_by(interval)
} }
Scale::RangeFraction { fraction } => { Scale::RangeFraction(fraction) => {
let len = self.range.len(); 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 { match self.orientation {
Orientation::X { x1, x2, y } => { Orientation::X { x1, x2, y } => {
Line { start: Point { x: x1, y }, end: Point { x: 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, 1))
.draw(display)?; .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 { 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::<U8> = 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 } => { Orientation::Y { y1, y2, x } => {
Line { start: Point { x, y: y1 }, end: Point { x, y: y2 } } 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, 1))
.draw(display)?; .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 { 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::<U8> = 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)?;
} }
} }
} }

View file

@ -6,4 +6,4 @@ pub mod single_plot;
mod drawable_curve; mod drawable_curve;
mod range_conv; mod range_conv;
mod axis; pub mod axis;