research-toolpaths.rs

2.2 kB · rust · 73 lines

1use figures::{ink, save, Board};2use mrlyrs::core::error::Result;34const DIRS: [usize; 7] = [0, 5, 3, 4, 0, 0, 1];5const FLIPS: [bool; 7] = [false, true, true, false, false, false, true];6const LEVEL: usize = 4;7const STEPS: usize = 2401;8const COUNTS: [usize; 3] = [343, 1371, 686];9const MARGIN: f64 = 0.08;10const PATH: f64 = 2.2;11const DOT: f64 = 3.1;1213fn expand(seq: &[(usize, bool)]) -> Vec<(usize, bool)> {14    let mut out = Vec::with_capacity(seq.len() * 7);15    for &(d, r) in seq {16        for j in 0..7 {17            let i = if r { 6 - j } else { j };18            out.push(((d + DIRS[i]) % 6, FLIPS[i] != r));19        }20    }21    out22}2324fn main() -> Result<()> {25    let mut seq = vec![(0usize, false)];26    for _ in 0..LEVEL {27        seq = expand(&seq);28    }29    assert_eq!(seq.len(), STEPS);30    let unit: Vec<(f64, f64)> = (0..6)31        .map(|d| {32            let a = std::f64::consts::PI / 3.0 * d as f64;33            (a.cos(), a.sin())34        })35        .collect();36    let mut pts = vec![(0.0, 0.0)];37    for &(d, _) in &seq {38        let (x, y) = pts[pts.len() - 1];39        pts.push((x + unit[d].0, y + unit[d].1));40    }41    let mut counts = [0usize; 3];42    let mut sharp = Vec::new();43    for i in 1..seq.len() {44        let t = (seq[i].0 + 6 - seq[i - 1].0) % 6;45        let t = t.min(6 - t);46        counts[t] += 1;47        if t == 2 {48            sharp.push(pts[i]);49        }50    }51    assert_eq!(counts, COUNTS);52    let (mut x0, mut y0, mut x1, mut y1) = (f64::MAX, f64::MAX, f64::MIN, f64::MIN);53    for &(x, y) in &pts {54        x0 = x0.min(x);55        y0 = y0.min(y);56        x1 = x1.max(x);57        y1 = y1.max(y);58    }59    let mut board = Board::square();60    let area = board.frame(MARGIN);61    let (cx, cy) = area.center();62    let scale = 2.0 * area.radius() / (x1 - x0).max(y1 - y0);63    let (mx, my) = ((x0 + x1) / 2.0, (y0 + y1) / 2.0);64    let at = |(x, y): (f64, f64)| (cx + (x - mx) * scale, cy - (y - my) * scale);65    let path: Vec<(f64, f64)> = pts.iter().map(|&p| at(p)).collect();66    board.polyline(&path, PATH, ink::dim());67    for &p in &sharp {68        let (x, y) = at(p);69        board.disc(x, y, DOT, ink::orange());70    }71    save("research-toolpaths", &board)?;72    Ok(())73}