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}