demo-snail.rs
2.3 kB · rust · 70 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, save, Board};3use mrlymath::two;4use mrlynum::spiral::{snail, Growth};56const TOP: u64 = 300;7const BASE: u64 = 2;8const CODE: u128 = 7;9const MARGIN: f64 = 0.07;1011fn main() -> Result<()> {12 let mut board = Board::square();13 let frame = board.area(MARGIN);14 let shell = snail(BASE, TOP, Growth::Every);15 assert_eq!(shell.tiles.len(), 300);16 assert_eq!(shell.primes, 62);17 assert_eq!(shell.levels, vec![1, 2, 4, 8, 16, 32, 64, 128, 45]);18 assert_eq!(shell.area, 5_345_865);19 let wide = (shell.high.0 - shell.low.0) as f64;20 let tall = (shell.high.1 - shell.low.1) as f64;21 assert_eq!((wide, tall), (4608.0, 4352.0));22 let unit = (frame.w / wide).min(frame.h / tall);23 let left = frame.x + (frame.w - wide * unit) / 2.0;24 let foot = frame.y + (frame.h + tall * unit) / 2.0;25 let at = |x: f64, y: f64| {26 (27 left + (x - shell.low.0 as f64) * unit,28 foot - (y - shell.low.1 as f64) * unit,29 )30 };31 let path: Vec<(f64, f64)> = shell32 .tiles33 .iter()34 .map(|tile| {35 let half = tile.side as f64 / 2.0;36 at(tile.x as f64 + half, tile.y as f64 + half)37 })38 .collect();39 board.polyline(&path, 1.6, ink::line());40 let mut art = Vec::new();41 for level in 0..shell.levels.len() {42 art.push(match level {43 0 => None,44 _ => Some(two::create(CODE, BASE as usize, level, 0, 2)?),45 });46 }47 let mut drawn = 0usize;48 for tile in shell.tiles.iter().filter(|tile| tile.level > 0) {49 let cell = art[tile.level as usize].as_ref().expect("a grown level");50 let types = cell.types();51 let side = cell.width();52 let tone = if tile.prime { ink::blue() } else { ink::dim() };53 for row in 0..side {54 for col in 0..side {55 if types.get(&[row, col]) == 0 {56 continue;57 }58 let (x, y) = at(59 tile.x as f64 + col as f64,60 tile.y as f64 + (side - row) as f64,61 );62 board.rect(x, y, unit, unit, tone);63 drawn += 1;64 }65 }66 }67 assert_eq!(drawn, 631_167);68 save("demo-snail", &board)?;69 Ok(())70}