demo-dissection.rs
2.0 kB · rust · 64 lines
1use figures::{ink, save, Board};2use mrlyrs::core::error::Result;3use mrlyrs::num::dissection::{regions, weights, Region};4use std::f64::consts::TAU;56const NAME: &str = "demo-dissection";7const BASE: u64 = 10;8const MISSING: u64 = 7;9const LEVEL: u32 = 3;10const Z: u64 = 8;11const COUNTS: [usize; 4] = [732, 202, 26, 40];12const DECADES: f64 = 4.0;1314fn slot(region: Region) -> usize {15 match region {16 Region::A => 0,17 Region::B => 1,18 Region::C1 => 2,19 Region::C2 => 3,20 }21}2223fn main() -> Result<()> {24 let digits: Vec<u64> = (0..BASE).filter(|&d| d != MISSING).collect();25 let cut = regions(BASE, LEVEL, Z);26 let weight = weights(BASE, &digits, LEVEL);27 let y = cut.len();28 let scale = (digits.len() as f64).powi(LEVEL as i32);29 let mut counts = [0usize; 4];30 for r in &cut {31 counts[slot(*r)] += 1;32 }33 assert_eq!(counts, COUNTS);34 assert_eq!(y, 1000);35 assert!((weight[0] / scale - 1.0).abs() < 1e-12);3637 let mut board = Board::square();38 let frame = board.frame(0.08);39 let (cx, cy) = frame.center();40 let outer = frame.radius();41 let inner = 0.36 * outer;42 let inks = [ink::blue(), ink::dim(), ink::orange(), ink::yellow()];43 let at = |r: f64, t: f64| (cx + r * t.sin(), cy - r * t.cos());44 let step = TAU / y as f64;45 board.ring(cx, cy, inner - 6.0, 1.0, ink::line());46 for pass in [1usize, 0, 2, 3] {47 for a in (0..y).filter(|&a| slot(cut[a]) == pass) {48 let w = weight[a] / scale;49 let reach = (1.0 + w.max(1e-12).log10() / DECADES).clamp(0.015, 1.0);50 let top = inner + (outer - inner) * reach;51 let mid = a as f64 * step;52 let half = 0.34 * step;53 let pts = [54 at(inner, mid - half),55 at(top, mid - half),56 at(top, mid + half),57 at(inner, mid + half),58 ];59 board.polygon(&pts, inks[pass]);60 }61 }62 save(NAME, &board)?;63 Ok(())64}