wiki-spectral-radius.rs

2.1 kB · rust · 66 lines

1use mrlycore::errors::Result;2use mrlyfig::{ink, save, Board};34const ARROWS: usize = 8;5const MATRIX: [[f64; 2]; 2] = [[2.0, 1.0], [1.0, 3.0]];6const START: (f64, f64) = (1.0, -0.6);78fn push(v: (f64, f64)) -> (f64, f64) {9    (10        MATRIX[0][0] * v.0 + MATRIX[0][1] * v.1,11        MATRIX[1][0] * v.0 + MATRIX[1][1] * v.1,12    )13}1415fn main() -> Result<()> {16    let mut v = START;17    let mut angles = Vec::with_capacity(ARROWS);18    for _ in 0..ARROWS {19        angles.push(v.1.atan2(v.0));20        v = push(v);21    }22    let golden = (1.0 + 5f64.sqrt()) / 2.0;23    let settled = golden.atan2(1.0);24    assert_eq!(angles.len(), ARROWS);25    assert!(angles.windows(2).all(|pair| pair[1] > pair[0]));26    assert!((settled - angles[ARROWS - 1]).abs() < 0.10);27    assert!(angles[0] < 0.0);2829    let mut board = Board::square();30    let frame = board.frame(0.08);31    let (cx, cy) = frame.at(0.30, 0.59);32    let reach = frame.w * 0.62;33    let far = frame.w * 0.70;34    board.segment(35        (cx - far * settled.cos(), cy + far * settled.sin()),36        (cx + far * settled.cos(), cy - far * settled.sin()),37        3.0,38        ink::fade(ink::dim(), 0.8),39    );40    board.arc(41        (cx, cy),42        reach * 1.05,43        (-settled - 0.12, -angles[0] + 0.12),44        3.0,45        ink::fade(ink::dim(), 0.8),46    );47    for (index, angle) in angles.iter().enumerate() {48        let heat = index as f64 / (ARROWS - 1) as f64;49        let paint = ink::mix(ink::blue(), ink::yellow(), heat);50        let tip = (cx + reach * angle.cos(), cy - reach * angle.sin());51        let way = (angle.cos(), -angle.sin());52        let side = (-way.1, way.0);53        let head = frame.w * 0.045;54        let base = (tip.0 - way.0 * head, tip.1 - way.1 * head);55        board.segment((cx, cy), base, 7.0, paint);56        board.triangle(57            tip,58            (base.0 + side.0 * head * 0.5, base.1 + side.1 * head * 0.5),59            (base.0 - side.0 * head * 0.5, base.1 - side.1 * head * 0.5),60            paint,61        );62    }63    board.disc(cx, cy, frame.w * 0.018, ink::fg());64    save("wiki-spectral-radius", &board)?;65    Ok(())66}