#![cfg(feature = "std")]
use embedded_charts::{
axes::scale::{AxisScale, AxisScaleType, ScaleConfig},
chart::{Chart, ChartBuilder, ChartConfig, LineChart},
data::{Point2D, StaticDataSeries},
};
use embedded_graphics::{
pixelcolor::Rgb565,
prelude::*,
primitives::{Circle, Line, PrimitiveStyle, Rectangle},
};
use embedded_graphics_simulator::{OutputSettingsBuilder, SimulatorDisplay, Window};
fn generate_exponential_data() -> StaticDataSeries<Point2D, 256> {
let mut series = StaticDataSeries::new();
for i in 0..50 {
let x = i as f32;
let y = 10.0_f32.powf(i as f32 / 12.5); series.push(Point2D::new(x, y)).unwrap();
}
series
}
fn generate_frequency_response() -> StaticDataSeries<Point2D, 256> {
let mut series = StaticDataSeries::new();
for i in 0..100 {
let freq = 10.0 * 10.0_f32.powf(i as f32 / 25.0); let cutoff = 1000.0;
let magnitude = 1.0 / (1.0 + (freq / cutoff).powi(2)).sqrt();
let db = 20.0 * magnitude.log10();
series.push(Point2D::new(freq, db)).unwrap();
}
series
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut display = SimulatorDisplay::<Rgb565>::new(Size::new(800, 600));
display.clear(Rgb565::WHITE)?;
let chart1_area = Rectangle::new(Point::new(50, 50), Size::new(700, 250));
let chart2_area = Rectangle::new(Point::new(50, 350), Size::new(700, 200));
{
let data = generate_exponential_data();
let bounds = data.bounds().unwrap();
let y_scale_config = ScaleConfig {
min: bounds.min_y,
max: bounds.max_y,
include_zero: false,
nice_bounds: true,
};
let y_scale = AxisScale::new(AxisScaleType::Log10, y_scale_config)?;
let chart = LineChart::<Rgb565>::builder()
.line_color(Rgb565::BLUE)
.line_width(2)
.with_title("Exponential Growth (Log Y-Scale)")
.build()?;
let config = ChartConfig::default();
chart.draw(&data, &config, chart1_area, &mut display)?;
let ticks = y_scale.get_ticks(5)?;
for (i, &tick) in ticks.iter().enumerate() {
let y_pos = chart1_area.top_left.y + chart1_area.size.height as i32
- ((i as i32 * chart1_area.size.height as i32) / (ticks.len() as i32 - 1));
let _label = y_scale.format_value(tick);
let tick_start = Point::new(chart1_area.top_left.x - 5, y_pos);
let tick_end = Point::new(chart1_area.top_left.x, y_pos);
Line::new(tick_start, tick_end)
.into_styled(PrimitiveStyle::with_stroke(Rgb565::BLACK, 1))
.draw(&mut display)?;
}
}
{
let data = generate_frequency_response();
let bounds = data.bounds().unwrap();
let x_scale_config = ScaleConfig {
min: bounds.min_x,
max: bounds.max_x,
include_zero: false,
nice_bounds: true,
};
let x_scale = AxisScale::new(AxisScaleType::Log10, x_scale_config)?;
let chart = LineChart::<Rgb565>::builder()
.line_color(Rgb565::RED)
.line_width(2)
.with_title("Frequency Response (Log X-Scale)")
.build()?;
let config = ChartConfig::default();
chart.draw(&data, &config, chart2_area, &mut display)?;
let ticks = x_scale.get_ticks(6)?;
for (i, &tick) in ticks.iter().enumerate() {
let x_pos = chart2_area.top_left.x
+ ((i as i32 * chart2_area.size.width as i32) / (ticks.len() as i32 - 1));
let _label = x_scale.format_value(tick);
let tick_start = Point::new(
x_pos,
chart2_area.top_left.y + chart2_area.size.height as i32,
);
let tick_end = Point::new(
x_pos,
chart2_area.top_left.y + chart2_area.size.height as i32 + 5,
);
Line::new(tick_start, tick_end)
.into_styled(PrimitiveStyle::with_stroke(Rgb565::BLACK, 1))
.draw(&mut display)?;
}
}
let title_pos = Point::new(400, 20);
Circle::with_center(title_pos, 5)
.into_styled(PrimitiveStyle::with_fill(Rgb565::BLACK))
.draw(&mut display)?;
let output_settings = OutputSettingsBuilder::new().build();
Window::new("Logarithmic Scale Demo", &output_settings).show_static(&display);
Ok(())
}