demo-spirograph.rs

1.8 kB · rust · 59 lines

1use mrlycore::errors::Result;2use mrlyfig::{ink, save, Board};3use mrlymath::two;4use mrlynum::spirograph::{distinct, frame, pencils, trace, track, Kind};56const CODE: u128 = 495;7const SIDE: usize = 3;8const LEVEL: usize = 1;9const BASE: usize = 3;10const RING: usize = 13;11const WHEEL: usize = 5;12const REACH: f64 = 1.2;13const SAMPLES: usize = 6000;14const PENCILS: usize = 9;15const CURVES: usize = 9;16const ORBITS: usize = 5;17const MARGIN: f64 = 0.08;18const THICK: f64 = 2.2;19const HAIR: f64 = 1.5;2021fn main() -> Result<()> {22    let cell = two::create(CODE, SIDE, LEVEL, 0, BASE)?;23    let types = cell.types().bytes().to_vec();24    let path = track("in", RING, WHEEL, 4, 1)?;25    let pens = pencils(&types, cell.width(), cell.height(), "both", REACH, 0.0, 1)?;26    assert_eq!(pens.len(), PENCILS);27    assert_eq!(distinct(&path, &pens, true), CURVES);28    assert_eq!(path.orbits, ORBITS);29    let points = trace(&path, &pens, SAMPLES)?;30    let [x0, y0, x1, y1] = frame(&path, &pens);3132    let mut board = Board::square();33    let area = board.frame(MARGIN);34    let scale = (area.w / (x1 - x0)).min(area.h / (y1 - y0));35    let (cx, cy) = area.center();36    let at = |x: f64, y: f64| {37        (38            cx + (x - (x0 + x1) / 2.0) * scale,39            cy - (y - (y0 + y1) / 2.0) * scale,40        )41    };42    board.ring(cx, cy, RING as f64 * scale, HAIR, ink::dim());43    for (k, pencil) in pens.iter().enumerate() {44        let pts: Vec<(f64, f64)> = (0..SAMPLES)45            .map(|i| {46                let j = 2 * (k * SAMPLES + i);47                at(f64::from(points[j]), f64::from(points[j + 1]))48            })49            .collect();50        let color = if pencil.kind == Kind::Void {51            ink::orange()52        } else {53            ink::blue()54        };55        board.polyline(&pts, THICK, color);56    }57    save("demo-spirograph", &board)?;58    Ok(())59}