demo-minkowski.rs

3.2 kB · rust · 89 lines

1use figures::{ink, save, Board, Color, Frame};2use mrlyrs::core::error::Result;3use mrlyrs::math::three::sponge::{profile, reading, COVER, EDGE};45const PERIODS: usize = 8;6const STEPS: usize = 144;7const OPEN: usize = 45;8const TWELFTH: (f64, f64) = (2.122718, 2.122723);9const SIXTH: (f64, f64) = (2.135019, 2.136794);1011fn runs(12    values: &[Option<f64>],13    place: impl Fn(usize, f64) -> Option<(f64, f64)>,14) -> Vec<Vec<(f64, f64)>> {15    let mut out = Vec::new();16    let mut run = Vec::new();17    for (i, value) in values.iter().enumerate() {18        match value.and_then(|v| place(i, v)) {19            Some(point) => run.push(point),20            None => {21                if run.len() > 1 {22                    out.push(std::mem::take(&mut run));23                }24                run.clear();25            }26        }27    }28    if run.len() > 1 {29        out.push(run);30    }31    out32}3334fn stroke(board: &mut Board, lines: &[Vec<(f64, f64)>], thick: f64, color: Color) {35    for line in lines {36        board.polyline(line, thick, color);37    }38}3940fn main() -> Result<()> {41    let start = (1.0 / COVER).ln();42    let period = 3f64.ln();43    let count = PERIODS * STEPS;44    let us: Vec<f64> = (0..count)45        .map(|i| start + period * (i as f64 + 0.5) / STEPS as f64)46        .collect();47    let once: Vec<Option<f64>> = us[..STEPS].iter().map(|u| profile((-u).exp())).collect();48    let waves: Vec<Option<f64>> = (0..count).map(|i| once[i % STEPS]).collect();49    let reads: Vec<Option<f64>> = us.iter().map(|u| reading((-u).exp())).collect();5051    assert_eq!(waves.iter().filter(|v| v.is_none()).count(), PERIODS * OPEN);52    assert!(waves53        .iter()54        .zip(&reads)55        .all(|(p, r)| p.is_none() == r.is_none()));56    assert!(waves.iter().zip(&reads).all(|(p, r)| p.is_none() || r < p));57    let twelfth = profile(1.0 / 12.0).unwrap_or(0.0);58    let sixth = profile(EDGE).unwrap_or(0.0);59    assert!(TWELFTH.0 <= twelfth && twelfth <= TWELFTH.1);60    assert!(SIXTH.0 <= sixth && sixth <= SIXTH.1);6162    let seen: Vec<f64> = once.iter().flatten().copied().collect();63    let low = seen.iter().copied().fold(f64::INFINITY, f64::min);64    let high = seen.iter().copied().fold(f64::NEG_INFINITY, f64::max);65    let spread = high - low;66    let (floor, roof) = (low - 1.6 * spread, high + 0.35 * spread);6768    let mut board = Board::square();69    let plot: Frame = board.frame(0.08);70    let (u0, u1) = (start, start + PERIODS as f64 * period);71    let x_of = |u: f64| plot.x + plot.w * (u - u0) / (u1 - u0);72    let y_of = |v: f64| plot.y + plot.h * (roof - v) / (roof - floor);73    let gap = (COVER / EDGE).ln();74    for k in 0..PERIODS {75        let left = x_of(u0 + k as f64 * period);76        let right = x_of(u0 + k as f64 * period + gap);77        board.rect(left, plot.y, right - left, plot.h, ink::panel());78    }79    let hair = (plot.w / 512.0).max(1.0);80    for k in 1..PERIODS {81        let x = x_of(u0 + k as f64 * period);82        board.segment((x, plot.y), (x, plot.y + plot.h), hair, ink::line());83    }84    let place = |i: usize, v: f64| (v >= floor).then(|| (x_of(us[i]), y_of(v.min(roof))));85    stroke(&mut board, &runs(&waves, place), 7.0, ink::yellow());86    stroke(&mut board, &runs(&reads, place), 5.0, ink::blue());87    save("demo-minkowski", &board)?;88    Ok(())89}