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}