use super::super::draw;
use super::super::{BarContext, ProgressStyle};
use crate::{BrailleGrid, DotmaxError};
use std::f32::consts::PI;
const PHI: f32 = 1.618_033_9;
pub fn styles() -> Vec<Box<dyn ProgressStyle>> {
vec![
Box::new(GoldenSpiral),
Box::new(GoldenRectangle),
Box::new(FibonacciSquares),
Box::new(Pentagram),
Box::new(PentagonNest),
Box::new(GoldenGnomon),
Box::new(PhiPhyllotaxisPent),
Box::new(Nautilus),
Box::new(GoldenAngleRays),
Box::new(Dodecagram),
Box::new(KeplerTriangle),
]
}
#[inline]
fn center(dw: usize, dh: usize) -> (f32, f32) {
(dw as f32 / 2.0, dh as f32 / 2.0)
}
#[inline]
fn fit_scale(dw: usize, dh: usize) -> f32 {
let hw = (dw as f32 / 2.0 - 1.0).max(1.0);
let hh = (dh as f32 / 2.0 - 1.0).max(1.0);
hw.min(hh)
}
fn bresenham(grid: &mut BrailleGrid, x0: i32, y0: i32, x1: i32, y1: i32) {
let mut x = x0;
let mut y = y0;
let dx = (x1 - x0).abs();
let dy = -(y1 - y0).abs();
let sx: i32 = if x0 < x1 { 1 } else { -1 };
let sy: i32 = if y0 < y1 { 1 } else { -1 };
let mut err = dx + dy;
let max_steps = (dx.abs() + dy.abs() + 2) as usize;
let mut steps = 0usize;
loop {
draw::dot_i(grid, x, y);
if x == x1 && y == y1 {
break;
}
steps += 1;
if steps > max_steps {
break;
}
let e2 = 2 * err;
if e2 >= dy {
err += dy;
x += sx;
}
if e2 <= dx {
err += dx;
y += sy;
}
}
}
fn arc(grid: &mut BrailleGrid, cx: f32, cy: f32, r: f32, a0: f32, a1: f32) {
if r < 0.5 {
return;
}
let arc_len = (a1 - a0).abs() * r;
let steps = (arc_len * 2.0).round() as usize;
let steps = steps.max(2);
for i in 0..=steps {
let t = i as f32 / steps as f32;
let angle = a0 + t * (a1 - a0);
let px = (cx + r * angle.cos()).round() as i32;
let py = (cy - r * angle.sin()).round() as i32;
draw::dot_i(grid, px, py);
}
}
fn ngon_vertices(n: usize, cx: f32, cy: f32, r: f32, rot: f32) -> Vec<(i32, i32)> {
(0..n)
.map(|i| {
let angle = rot + 2.0 * PI * i as f32 / n as f32;
(
(cx + r * angle.cos()).round() as i32,
(cy - r * angle.sin()).round() as i32,
)
})
.collect()
}
fn ngon_outline(grid: &mut BrailleGrid, n: usize, cx: f32, cy: f32, r: f32, rot: f32) {
let verts = ngon_vertices(n, cx, cy, r, rot);
for i in 0..n {
let (x0, y0) = verts[i];
let (x1, y1) = verts[(i + 1) % n];
bresenham(grid, x0, y0, x1, y1);
}
}
struct GoldenSpiral;
impl ProgressStyle for GoldenSpiral {
fn name(&self) -> &str {
"golden-spiral"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Fibonacci-square tiling with quarter-circle arcs forming the golden logarithmic \
spiral; squares and arcs revealed one step per eased progress"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let scale = fit_scale(dw, dh);
let fibs: [f32; 9] = [1.0, 1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 21.0, 34.0];
let n_total: usize = 9;
let n_show = ((ctx.eased * n_total as f32).round() as usize).min(n_total);
let long = fibs[n_total - 1];
let unit = (scale * 1.8 / long).max(0.5);
let dirs: [(f32, f32); 4] = [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)];
let arc_starts: [f32; 4] = [PI, 3.0 * PI / 2.0, 0.0, PI / 2.0];
let mut dir_idx = 0usize;
let mut px_n: f32 = 0.0;
let mut py_n: f32 = 0.0;
let (dcx, dcy) = center(dw, dh);
for i in 0..n_show {
let side = fibs[i];
let a_start = arc_starts[dir_idx % 4];
let a_end = a_start - PI / 2.0;
let arc_cx = dcx + px_n * unit;
let arc_cy = dcy + py_n * unit;
let (ddx, ddy) = dirs[dir_idx % 4];
{
let perp = match dir_idx % 4 {
0 => (0.0, -1.0), 1 => (1.0, 0.0), 2 => (0.0, 1.0), _ => (-1.0, 0.0), };
let s = side;
let c0 = (px_n, py_n);
let c1 = (px_n + ddx * s, py_n + ddy * s);
let c2 = (px_n + ddx * s + perp.0 * s, py_n + ddy * s + perp.1 * s);
let c3 = (px_n + perp.0 * s, py_n + perp.1 * s);
let corners = [c0, c1, c2, c3];
for k in 0..4 {
let (ax, ay) = corners[k];
let (bx, by) = corners[(k + 1) % 4];
let p0x = (dcx + ax * unit).round() as i32;
let p0y = (dcy + ay * unit).round() as i32;
let p1x = (dcx + bx * unit).round() as i32;
let p1y = (dcy + by * unit).round() as i32;
bresenham(grid, p0x, p0y, p1x, p1y);
}
}
arc(grid, arc_cx, arc_cy, side * unit, a_start, a_end);
let (adx, ady) = match dir_idx % 4 {
0 => (side, 0.0), 1 => (0.0, side), 2 => (-side, 0.0), _ => (0.0, -side), };
px_n += adx;
py_n += ady;
dir_idx += 1;
}
Ok(())
}
}
struct GoldenRectangle;
impl ProgressStyle for GoldenRectangle {
fn name(&self) -> &str {
"golden-rectangle"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Recursive φ-rectangle subdivision into a square + smaller φ-rectangle — \
the whirling-rectangles diagram, with each subdivision revealed as progress rises"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let scale_w = (dw as f32 - 2.0) / PHI;
let scale_h = (dh as f32 - 2.0) / 1.0;
let unit = scale_w.min(scale_h).max(1.0);
let rect_w = PHI * unit;
let rect_h = 1.0 * unit;
let ox = ((dw as f32 - rect_w) / 2.0).max(0.0);
let oy = ((dh as f32 - rect_h) / 2.0).max(0.0);
let max_depth: usize = 10;
let depth = ((ctx.eased * max_depth as f32).round() as usize)
.min(max_depth)
.max(1);
let rects: Vec<(f32, f32, f32, f32, bool)> = vec![(ox, oy, rect_w, rect_h, true)];
let mut drawn = 0usize;
{
let (x0, y0, w, h, _) = rects[0];
draw::rect_outline(
grid,
x0.round() as usize,
y0.round() as usize,
w.round().max(1.0) as usize,
h.round().max(1.0) as usize,
);
}
drawn += 1;
let mut next_rects: Vec<(f32, f32, f32, f32, bool)> = Vec::new();
let mut current = rects.clone();
for _d in 0..depth.saturating_sub(1) {
next_rects.clear();
for &(x0, y0, w, h, horiz) in ¤t {
if horiz {
let sq = h;
if sq >= 1.0 && w - sq >= 1.0 {
let lx = (x0 + sq).round() as usize;
let ly0 = y0.round() as usize;
let ly1 = (y0 + h - 1.0).round() as usize;
if lx < dw {
draw::vline(
grid,
lx,
ly0.min(dh.saturating_sub(1)),
ly1.min(dh.saturating_sub(1)),
);
}
next_rects.push((x0 + sq, y0, w - sq, h, false));
drawn += 1;
}
} else {
let sq = w;
if sq >= 1.0 && h - sq >= 1.0 {
let ly = (y0 + sq).round() as usize;
let lx0 = x0.round() as usize;
let lx1 = (x0 + w - 1.0).round() as usize;
if ly < dh {
draw::hline(
grid,
lx0.min(dw.saturating_sub(1)),
lx1.min(dw.saturating_sub(1)),
ly,
);
}
next_rects.push((x0, y0 + sq, w, h - sq, true));
drawn += 1;
}
}
if drawn >= depth * 2 {
break;
}
}
if next_rects.is_empty() {
break;
}
current = next_rects.clone();
}
let _ = drawn;
Ok(())
}
}
struct FibonacciSquares;
impl ProgressStyle for FibonacciSquares {
fn name(&self) -> &str {
"fibonacci-squares"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Outward Fibonacci-square tiling (1,1,2,3,5,8,13,21,34…): each square \
outline appears as progress advances, building the canonical φ-rectangle mosaic"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (dcx, dcy) = center(dw, dh);
let fibs: [f32; 10] = [1.0, 1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 21.0, 34.0, 55.0];
let n_total: usize = 10;
let n_show = ((ctx.eased * n_total as f32).round() as usize).min(n_total);
let long = fibs[n_total - 1];
let unit = ((dw.min(dh) as f32 - 2.0) / long * 1.6).max(0.5);
let dirs: [(f32, f32); 4] = [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)];
let perps: [(f32, f32); 4] = [(0.0, -1.0), (1.0, 0.0), (0.0, 1.0), (-1.0, 0.0)];
let mut px_n: f32 = 0.0;
let mut py_n: f32 = 0.0;
let mut dir_idx = 0usize;
for i in 0..n_show {
let side = fibs[i];
let (ddx, ddy) = dirs[dir_idx % 4];
let (ppx, ppy) = perps[dir_idx % 4];
let s = side;
let c0 = (px_n, py_n);
let c1 = (px_n + ddx * s, py_n + ddy * s);
let c2 = (px_n + ddx * s + ppx * s, py_n + ddy * s + ppy * s);
let c3 = (px_n + ppx * s, py_n + ppy * s);
let corners = [c0, c1, c2, c3];
for k in 0..4 {
let (ax, ay) = corners[k];
let (bx, by) = corners[(k + 1) % 4];
let p0x = (dcx + ax * unit).round() as i32;
let p0y = (dcy + ay * unit).round() as i32;
let p1x = (dcx + bx * unit).round() as i32;
let p1y = (dcy + by * unit).round() as i32;
bresenham(grid, p0x, p0y, p1x, p1y);
}
let step = match dir_idx % 4 {
0 => (side, 0.0),
1 => (0.0, side),
2 => (-side, 0.0),
_ => (0.0, -side),
};
px_n += step.0;
py_n += step.1;
dir_idx += 1;
}
Ok(())
}
}
struct Pentagram;
impl ProgressStyle for Pentagram {
fn name(&self) -> &str {
"pentagram"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Nested pentagram-in-pentagon: each star's inner pentagon contains a smaller \
pentagram scaled by 1/φ², revealing infinite φ self-similarity as progress deepens"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let base_r = fit_scale(dw, dh) * 0.95;
let max_depth: usize = 6;
let depth = ((ctx.eased * max_depth as f32).ceil() as usize)
.min(max_depth)
.max(1);
let rot0 = ctx.time * 0.2 - PI / 2.0;
let inner_scale = 1.0 / (PHI * PHI);
let mut r = base_r;
let mut rot = rot0;
for _ in 0..depth {
if r < 1.0 {
break;
}
let verts = ngon_vertices(5, cx, cy, r, rot);
let star_order = [0usize, 2, 4, 1, 3, 0];
for k in 0..5 {
let (x0, y0) = verts[star_order[k]];
let (x1, y1) = verts[star_order[k + 1]];
bresenham(grid, x0, y0, x1, y1);
}
ngon_outline(grid, 5, cx, cy, r, rot);
r *= inner_scale;
rot += PI / 5.0; }
Ok(())
}
}
struct PentagonNest;
impl ProgressStyle for PentagonNest {
fn name(&self) -> &str {
"pentagon-nest"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Concentric pentagons each scaled 1/φ² smaller, counter-rotating with time — \
a hypnotic tunnel of five-fold symmetry"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let base_r = fit_scale(dw, dh) * 0.95;
let max_rings: usize = 8;
let rings = ((ctx.eased * max_rings as f32).ceil() as usize)
.min(max_rings)
.max(1);
let inner_scale = 1.0 / (PHI * PHI);
let mut r = base_r;
for i in 0..rings {
if r < 1.0 {
break;
}
let sign = if i % 2 == 0 { 1.0_f32 } else { -1.0_f32 };
let rot = ctx.time * 0.15 * sign - PI / 2.0 + i as f32 * 0.1;
ngon_outline(grid, 5, cx, cy, r, rot);
r *= inner_scale;
}
Ok(())
}
}
struct GoldenGnomon;
impl ProgressStyle for GoldenGnomon {
fn name(&self) -> &str {
"golden-gnomon"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"36-72-72 golden gnomon recursively bisected into smaller golden triangles — \
the geometric basis of Penrose tilings, depth revealed with progress"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh) * 0.9;
let rot0 = ctx.time * 0.18 - PI / 2.0;
let max_depth: usize = 5;
let depth = ((ctx.eased * max_depth as f32).ceil() as usize)
.min(max_depth)
.max(1);
let half_base_angle = 72.0_f32.to_radians(); let apex_angle = 36.0_f32.to_radians();
let _ = half_base_angle;
let _ = apex_angle;
let sin36 = 36.0_f32.to_radians().sin();
let cos36 = 36.0_f32.to_radians().cos();
type Pt = (f32, f32);
fn rot_pt(p: Pt, angle: f32) -> Pt {
(
p.0 * angle.cos() - p.1 * angle.sin(),
p.0 * angle.sin() + p.1 * angle.cos(),
)
}
fn lerp_pt(a: Pt, b: Pt, t: f32) -> Pt {
(a.0 + (b.0 - a.0) * t, a.1 + (b.1 - a.1) * t)
}
fn draw_tri(grid: &mut BrailleGrid, cx: f32, cy: f32, a: Pt, b: Pt, c: Pt) {
let to_dot = |p: Pt| ((cx + p.0).round() as i32, (cy - p.1).round() as i32);
let (ax, ay) = to_dot(a);
let (bx, by) = to_dot(b);
let (ccx, ccy) = to_dot(c);
bresenham(grid, ax, ay, bx, by);
bresenham(grid, bx, by, ccx, ccy);
bresenham(grid, ccx, ccy, ax, ay);
}
let apex: Pt = (0.0, cos36 * scale);
let base_l: Pt = (-sin36 * scale, 0.0);
let base_r: Pt = (sin36 * scale, 0.0);
let apex = rot_pt(apex, rot0);
let base_l = rot_pt(base_l, rot0);
let base_r = rot_pt(base_r, rot0);
let mut tris: Vec<(Pt, Pt, Pt, bool)> = vec![(apex, base_l, base_r, true)];
for _d in 0..depth.saturating_sub(1) {
let mut next: Vec<(Pt, Pt, Pt, bool)> = Vec::new();
for &(a, b, c, is_gnomon) in &tris {
if is_gnomon {
let p = lerp_pt(a, b, 1.0 / PHI);
next.push((p, a, c, true)); next.push((b, p, c, false)); } else {
let p = lerp_pt(a, b, 1.0 / PHI);
next.push((c, p, a, true)); next.push((b, p, c, false)); }
}
for &(a, b, c, _) in &next {
draw_tri(grid, cx, cy, a, b, c);
}
tris = next;
if tris.len() > 128 {
break;
} }
draw_tri(grid, cx, cy, apex, base_l, base_r);
Ok(())
}
}
struct PhiPhyllotaxisPent;
impl ProgressStyle for PhiPhyllotaxisPent {
fn name(&self) -> &str {
"phi-phyllotaxis-pent"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Five-fold phyllotaxis: seeds placed at the golden angle but grouped into five \
symmetric spiral arms, creating pentagonal lattice symmetry with φ spacing"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh);
let golden_angle = 2.0 * PI / (PHI * PHI); let n_max: usize = 300;
let n_plot = ((ctx.eased * n_max as f32).round() as usize).min(n_max);
let c = scale / (n_max as f32).sqrt();
let rot = ctx.time * 0.12;
let mut sector_prev: [Option<(i32, i32)>; 5] = [None; 5];
for n in 0..n_plot {
let angle = n as f32 * golden_angle + rot;
let r = c * (n as f32).sqrt();
let px = (cx + r * angle.cos()).round() as i32;
let py = (cy - r * angle.sin()).round() as i32;
let sector = n % 5;
if let Some((lx, ly)) = sector_prev[sector] {
bresenham(grid, lx, ly, px, py);
} else {
draw::dot_i(grid, px, py);
}
sector_prev[sector] = Some((px, py));
}
Ok(())
}
}
struct Nautilus;
impl ProgressStyle for Nautilus {
fn name(&self) -> &str {
"nautilus"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"φ-logarithmic nautilus spiral r=a·φ^(θ·2/π) with chambered septa every \
quarter turn — the classic cephalopod shell built from pure golden-ratio growth"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh);
let theta_total = 8.0 * PI;
let theta_max = ctx.eased * theta_total;
let rot = ctx.time * 0.15;
let r_at_full = PHI.powf(theta_total * 2.0 / PI);
let a = 1.0 / r_at_full;
let steps = ((theta_max / (2.0 * PI) * 120.0).round() as usize).max(2);
for i in 0..=steps {
let theta = i as f32 / steps as f32 * theta_max;
let r = a * PHI.powf(theta * 2.0 / PI) * scale;
let angle = theta + rot;
let px = (cx + r * angle.cos()).round() as i32;
let py = (cy - r * angle.sin()).round() as i32;
draw::dot_i(grid, px, py);
}
let n_septa = (theta_max / (PI / 2.0)).floor() as usize;
for k in 0..=n_septa {
let theta_wall = k as f32 * PI / 2.0;
if theta_wall > theta_max {
break;
}
let r_outer = a * PHI.powf(theta_wall * 2.0 / PI) * scale;
let theta_inner = theta_wall - 2.0 * PI;
let r_inner = if theta_inner > 0.0 {
a * PHI.powf(theta_inner * 2.0 / PI) * scale
} else {
0.0
};
let angle = theta_wall + rot;
let x_outer = (cx + r_outer * angle.cos()).round() as i32;
let y_outer = (cy - r_outer * angle.sin()).round() as i32;
let x_inner = (cx + r_inner * angle.cos()).round() as i32;
let y_inner = (cy - r_inner * angle.sin()).round() as i32;
bresenham(grid, x_inner, y_inner, x_outer, y_outer);
}
Ok(())
}
}
struct GoldenAngleRays;
impl ProgressStyle for GoldenAngleRays {
fn name(&self) -> &str {
"golden-angle-rays"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Rays at successive 137.5° golden-angle increments from the center, each \
growing longer — the irrational spacing that prevents clustering and produces \
optimal coverage of the disk"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh);
let golden_angle = 2.0 * PI / (PHI * PHI); let n_max: usize = 55; let n_rays = ((ctx.eased * n_max as f32).round() as usize).min(n_max);
let rot = ctx.time * 0.1;
for i in 0..n_rays {
let angle = i as f32 * golden_angle + rot;
let t = (i + 1) as f32 / n_max as f32;
let len = scale * t; let x_end = (cx + len * angle.cos()).round() as i32;
let y_end = (cy - len * angle.sin()).round() as i32;
let cx_i = cx.round() as i32;
let cy_i = cy.round() as i32;
bresenham(grid, cx_i, cy_i, x_end, y_end);
}
Ok(())
}
}
struct Dodecagram;
impl ProgressStyle for Dodecagram {
fn name(&self) -> &str {
"dodecagram"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Dodecagram {12/5}: connecting every 5th vertex of a regular 12-gon produces \
a twelve-pointed φ-star; chords materialise progressively while the star rotates"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh) * 0.92;
let n: usize = 12;
let step: usize = 5; let rot = ctx.time * 0.14;
let n_chords = ((ctx.eased * n as f32).round() as usize).min(n);
ngon_outline(grid, n, cx, cy, scale, rot);
let verts = ngon_vertices(n, cx, cy, scale, rot);
for i in 0..n_chords {
let j = (i + step) % n;
let (x0, y0) = verts[i];
let (x1, y1) = verts[j];
bresenham(grid, x0, y0, x1, y1);
}
Ok(())
}
}
struct KeplerTriangle;
impl ProgressStyle for KeplerTriangle {
fn name(&self) -> &str {
"kepler-triangle"
}
fn theme(&self) -> &str {
"goldenratio"
}
fn describe(&self) -> &str {
"Kepler triangle fan: right triangles with sides 1:√φ:φ tiled around the \
center, each rotated by the golden angle — where Pythagoras meets φ"
}
fn render(&self, grid: &mut BrailleGrid, ctx: &BarContext) -> Result<(), DotmaxError> {
let (dw, dh) = draw::dot_dims(grid);
let (cx, cy) = center(dw, dh);
let scale = fit_scale(dw, dh);
let a = scale / PHI; let b = scale / PHI.sqrt();
let golden_angle = 2.0 * PI / (PHI * PHI);
let n_max: usize = 34; let n_tris = ((ctx.eased * n_max as f32).round() as usize).min(n_max);
let rot_base = ctx.time * 0.1;
for i in 0..n_tris {
let rot = i as f32 * golden_angle + rot_base;
let tip_a = (cx + a * rot.cos(), cy - a * rot.sin());
let tip_b = (
cx + b * (rot + PI / 2.0).cos(),
cy - b * (rot + PI / 2.0).sin(),
);
let origin = (cx.round() as i32, cy.round() as i32);
let (ax, ay) = (tip_a.0.round() as i32, tip_a.1.round() as i32);
let (bx, by) = (tip_b.0.round() as i32, tip_b.1.round() as i32);
bresenham(grid, origin.0, origin.1, ax, ay); bresenham(grid, origin.0, origin.1, bx, by); bresenham(grid, ax, ay, bx, by); }
Ok(())
}
}