research-spin.rs
2.4 kB · rust · 73 lines
1use mrlycore::errors::Result;2use mrlyfig::board::Board;3use mrlyfig::ink::Ramp;4use mrlyfig::{ink, save};5use mrlymath::two;6use mrlynum::spin;78const LEVEL: usize = 5;9const SIDE: usize = 243;10const RINGS: usize = 1600;1112fn mirror(cell: &two::Cell2d) -> Vec<f32> {13 let span = 2 * SIDE;14 let types = cell.types();15 let mut out = vec![0f32; span * span];16 for row in 0..span {17 let y = if row < SIDE {18 SIDE - 1 - row19 } else {20 row - SIDE21 };22 for col in 0..span {23 let x = if col < SIDE {24 SIDE - 1 - col25 } else {26 col - SIDE27 };28 out[row * span + col] = types.get(&[y, x]) as f32;29 }30 }31 out32}3334fn main() -> Result<()> {35 let carpet = two::designs::create(495, 3, LEVEL, 0, 3)?;36 assert_eq!(carpet.width(), SIDE);37 assert_eq!(carpet.types().sum(), 8u64.pow(LEVEL as u32));38 let span = 2 * SIDE;39 let board_data = mirror(&carpet);40 let profile: Vec<f64> = (0..=RINGS)41 .map(|k| spin::ring(&board_data, span, SIDE as f64 * k as f64 / RINGS as f64))42 .collect();43 assert!((profile[0] - 1.0).abs() < 1e-9);44 let lo = profile.iter().copied().fold(f64::MAX, f64::min);45 let hi = profile.iter().copied().fold(f64::MIN, f64::max);46 assert!(hi - lo > 0.5);4748 let ramp = Ramp::new(vec![ink::ground(), ink::blue(), ink::yellow()]);49 let mut board = Board::square();50 let frame = board.frame(0.08);51 let (cx, cy) = frame.center();52 let reach = frame.radius();53 let x0 = (cx - reach - 1.0).max(0.0) as usize;54 let y0 = (cy - reach - 1.0).max(0.0) as usize;55 let x1 = ((cx + reach + 1.0) as usize).min(board.width);56 let y1 = ((cy + reach + 1.0) as usize).min(board.height);57 for py in y0..y1 {58 for px in x0..x1 {59 let d = ((px as f64 + 0.5 - cx).powi(2) + (py as f64 + 0.5 - cy).powi(2)).sqrt();60 let cover = (reach + 0.5 - d).clamp(0.0, 1.0);61 if cover <= 0.0 {62 continue;63 }64 let t = (d / reach) * RINGS as f64;65 let i = (t.floor() as usize).min(RINGS - 1);66 let f = t - i as f64;67 let value = profile[i] * (1.0 - f) + profile[i + 1] * f;68 board.blend(px, py, ramp.at((value - lo) / (hi - lo)), cover);69 }70 }71 save("research-spin", &board)?;72 Ok(())73}