use embassy_ssd1306_graphics::Graphics;
use embedded_hal_async::i2c::I2c;
use crate::draw_utils::{segment, filled_disk, ring};
#[derive(Clone, Copy, Debug)]
pub struct Compass {
pub cx: i32,
pub cy: i32,
pub radius: i32,
}
impl Compass {
#[inline]
pub fn new(cx: i32, cy: i32, radius: i32) -> Self {
Self { cx, cy, radius }
}
pub fn draw<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
heading: f32,
on: bool,
cos_fn: fn(f32) -> f32,
sin_fn: fn(f32) -> f32,
) {
let r = self.radius;
ring(gfx, self.cx, self.cy, r, on);
let inner = r - 2;
gfx.pixel(self.cx, self.cy - inner, on); gfx.pixel(self.cx + inner, self.cy, on); gfx.pixel(self.cx, self.cy + inner, on); gfx.pixel(self.cx - inner, self.cy, on);
let sh = sin_fn(heading);
let ch = cos_fn(heading);
let needle = r - 3;
let nx = self.cx + ((needle as f32) * sh + 0.5) as i32;
let ny = self.cy - ((needle as f32) * ch + 0.5) as i32;
segment(gfx, self.cx, self.cy, nx, ny, on);
let dx = (nx - self.cx).abs();
let dy = (ny - self.cy).abs();
if dx >= dy {
segment(gfx, self.cx, self.cy + 1, nx, ny + 1, on);
} else {
segment(gfx, self.cx + 1, self.cy, nx + 1, ny, on);
}
let tail = (r / 2) - 1;
let tx = self.cx - ((tail as f32) * sh + 0.5) as i32;
let ty = self.cy + ((tail as f32) * ch + 0.5) as i32;
segment(gfx, self.cx, self.cy, tx, ty, on);
filled_disk(gfx, self.cx, self.cy, 1, on);
}
#[inline]
pub fn erase<I: I2c>(
&self,
gfx: &mut Graphics<'_, I>,
heading: f32,
cos_fn: fn(f32) -> f32,
sin_fn: fn(f32) -> f32,
) {
self.draw(gfx, heading, false, cos_fn, sin_fn);
}
}