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}