use embassy_ssd1306_graphics::Graphics;
use embedded_hal_async::i2c::I2c;
use crate::draw_utils::{segment, filled_disk, filled_rect};
#[derive(Clone, Copy, Debug)]
pub struct Pendulum {
pub pivot_x: i32,
pub pivot_y: i32,
pub length: i32,
pub wall_w: i32,
pub wall_h: i32,
}
impl Pendulum {
#[inline]
pub fn new(pivot_x: i32, pivot_y: i32, length: i32) -> Self {
Self { pivot_x, pivot_y, length, wall_w: 16, wall_h: 5 }
}
#[inline]
pub fn with_wall(pivot_x: i32, pivot_y: i32, length: i32, wall_w: i32, wall_h: i32) -> Self {
Self { pivot_x, pivot_y, length, wall_w, wall_h }
}
pub fn draw<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
angle: f32,
on: bool,
cos_fn: fn(f32) -> f32,
sin_fn: fn(f32) -> f32,
) {
let hw = self.wall_w / 2;
let wall_x = self.pivot_x - hw;
let wall_y = self.pivot_y - self.wall_h;
filled_rect(gfx, wall_x, wall_y, self.wall_w, self.wall_h, on);
let mut d = 0i32;
while d < self.wall_w + self.wall_h {
for dx in 0..self.wall_w {
let dy = d - dx;
if dy >= 0 && dy < self.wall_h {
gfx.pixel(wall_x + dx, wall_y + dy, !on);
}
}
d += 4;
}
segment(
gfx,
self.pivot_x - hw - 1, self.pivot_y,
self.pivot_x + hw + 1, self.pivot_y,
on,
);
let mx = self.pivot_x + ((self.length as f32) * sin_fn(angle) + 0.5) as i32;
let my = self.pivot_y + ((self.length as f32) * cos_fn(angle) + 0.5) as i32;
segment(gfx, self.pivot_x, self.pivot_y, mx, my, on);
filled_disk(gfx, self.pivot_x, self.pivot_y, 1, on);
filled_disk(gfx, mx, my, 3, on);
}
#[inline]
pub fn erase<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
angle: f32,
cos_fn: fn(f32) -> f32,
sin_fn: fn(f32) -> f32,
) {
self.draw(gfx, angle, false, cos_fn, sin_fn);
}
}