paper-gasket-ray-machine.rs
2.3 kB · rust · 76 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, save, Board};3use mrlymath::two::designs;4use mrlynum::classics::{fibonacci, gcd};5use std::collections::HashMap;67const LEVEL: usize = 5;89fn main() -> Result<()> {10 let cell = designs::from_corners(&[vec![0, 0], vec![1, 0], vec![0, 1]], 3, LEVEL, 0, 3)?;11 let side = cell.width();12 let types = cell.types();13 let mut points = Vec::new();14 for row in 0..side {15 for col in 0..side {16 if types.get(&[row, col]) != 0 {17 points.push((row, col));18 }19 }20 }21 assert_eq!(side, 3usize.pow(LEVEL as u32));22 assert_eq!(points.len(), 3usize.pow(LEVEL as u32));2324 let mut rays: HashMap<(usize, usize), Vec<(usize, usize)>> = HashMap::new();25 for point in &points {26 if *point == (0, 0) {27 continue;28 }29 let step = gcd(point.0 as u128, point.1 as u128) as usize;30 rays.entry((point.0 / step, point.1 / step))31 .or_default()32 .push(*point);33 }34 let ladder = fibonacci(1000);35 let shift = rays[&(1, 3)].len();36 assert_eq!(shift, ladder[LEVEL] - 1);37 assert_eq!(rays[&(3, 1)].len(), shift);3839 let mut board = Board::square();40 let frame = board.frame(0.08);41 let reach = points42 .iter()43 .map(|point| point.0.max(point.1))44 .max()45 .expect("the gasket holds a point") as f64;46 let step = frame.w / reach;47 let at = |point: &(usize, usize)| {48 (49 frame.x + point.1 as f64 * step,50 frame.y + frame.h - point.0 as f64 * step,51 )52 };53 let origin = at(&(0, 0));54 let mut order: Vec<_> = rays.iter().collect();55 order.sort_by_key(|(ray, on)| (on.len(), **ray));56 for (ray, on) in order {57 let far = on58 .iter()59 .max_by_key(|point| point.0 + point.1)60 .expect("a ray holds a point");61 let mass = on.len() as f64;62 let gold = *ray == (1, 3) || *ray == (3, 1);63 let color = if gold {64 ink::yellow()65 } else {66 ink::fade(ink::blue(), (0.16 + 0.13 * (mass - 1.0)).min(1.0))67 };68 board.segment(origin, at(far), if gold { 3.0 } else { 1.6 }, color);69 }70 for point in &points {71 let (x, y) = at(point);72 board.disc(x, y, 2.8, ink::fg());73 }74 save("paper-gasket-ray-machine", &board)?;75 Ok(())76}