paper-design-dirichlet-inverse.rs
4.0 kB · rust · 133 lines
1use mrlycore::errors::Result;2use mrlycore::Color;3use mrlyfig::{ink, plot, save, Board, Frame};45const RE_WIDTH: f64 = 1.00;6const IM_REACH: f64 = 60.0;7const RHO: (f64, f64) = (0.720790, 28.605680);8const BOX_RE: (f64, f64) = (0.72074, 0.72084);9const BOX_IM: (f64, f64) = (28.60563, 28.60573);10const BANDS: [(f64, f64); 2] = [(22.01, 24.01), (56.00, 58.00)];11const BAND_RE: f64 = 3.02;12const OVER: f64 = 22.0;1314fn at(rect: Frame, abscissa: f64, re: f64, im: f64) -> (f64, f64) {15 (16 rect.x + rect.w * (re - abscissa) / RE_WIDTH,17 rect.y + rect.h * (1.0 - im / IM_REACH),18 )19}2021fn stroke_box(board: &mut Board, rect: Frame, thick: f64, color: Color) {22 let pts = [23 (rect.x, rect.y),24 (rect.x + rect.w, rect.y),25 (rect.x + rect.w, rect.y + rect.h),26 (rect.x, rect.y + rect.h),27 (rect.x, rect.y),28 ];29 board.polyline(&pts, thick, color);30}3132fn half_plane(board: &mut Board, rect: Frame) {33 board.rect(rect.x, rect.y, rect.w, rect.h, ink::panel());34 board.segment(35 (rect.x - OVER, rect.y + rect.h),36 (rect.x + rect.w, rect.y + rect.h),37 1.6,38 ink::line(),39 );40 board.segment(41 (rect.x, rect.y - OVER),42 (rect.x, rect.y + rect.h + OVER),43 2.8,44 ink::fade(ink::indigo(), 0.5),45 );46}4748fn band(board: &mut Board, rect: Frame, abscissa: f64, span: (f64, f64)) {49 let (_, low) = at(rect, abscissa, abscissa, span.0);50 let (_, high) = at(rect, abscissa, abscissa, span.1);51 let run = rect.w + OVER;52 board.rect(53 rect.x,54 high,55 run,56 low - high,57 ink::fade(ink::yellow(), 0.16),58 );59 board.segment(60 (rect.x, high),61 (rect.x + run, high),62 1.8,63 ink::fade(ink::yellow(), 0.5),64 );65 board.segment(66 (rect.x, low),67 (rect.x + run, low),68 1.8,69 ink::fade(ink::yellow(), 0.5),70 );71}7273fn comb(abscissa: f64, period: f64, reach: f64) -> Vec<(f64, f64)> {74 let mut poles = Vec::new();75 let mut j = 0;76 while j as f64 * period <= reach {77 poles.push((abscissa, j as f64 * period));78 j += 1;79 }80 poles81}8283fn main() -> Result<()> {84 let alpha = 2f64.ln() / 3f64.ln();85 let period = 2.0 * std::f64::consts::PI / 3f64.ln();86 let poles = comb(alpha, period, IM_REACH);87 let integers = 1.0f64;8889 assert_eq!((IM_REACH / period).floor() as usize, 10);90 assert_eq!(poles.len(), 11);91 assert_eq!(BANDS.len(), 2);92 assert!(poles.iter().all(|p| p.0 == alpha));93 assert!(RHO.0 > alpha && RHO.0 < alpha + RE_WIDTH);94 assert!(RHO.0 > BOX_RE.0 && RHO.0 < BOX_RE.1);95 assert!(RHO.1 > BOX_IM.0 && RHO.1 < BOX_IM.1);96 assert!(BANDS97 .iter()98 .all(|b| b.1 > b.0 && b.0 > 0.0 && b.1 < IM_REACH));99 const { assert!(BAND_RE > RE_WIDTH) };100 assert!((alpha - 0.6309297536).abs() < 1e-9);101 assert!((period - 5.7192017348).abs() < 1e-9);102103 let mut board = Board::square();104 let work = board.frame(0.08).inset(OVER + 2.0);105 let pw = work.w * 0.455;106 let ph = work.h * 0.865;107 let design = Frame::new(work.x, work.y, pw, ph);108 let control = Frame::new(work.x + work.w - pw, work.y + work.h - ph, pw, ph);109110 half_plane(&mut board, control);111 let (ix, iy) = at(control, integers, integers, 0.0);112 plot::dots(&mut board, &[(ix, iy)], 6.0, ink::fade(ink::indigo(), 0.92));113114 half_plane(&mut board, design);115 for span in &BANDS {116 band(&mut board, design, alpha, *span);117 }118 let marks: Vec<(f64, f64)> = poles.iter().map(|p| at(design, alpha, p.0, p.1)).collect();119 plot::dots(&mut board, &marks, 6.0, ink::fade(ink::indigo(), 0.92));120121 let emblem = at(design, alpha, RHO.0, RHO.1);122 let half = design.w * 0.057;123 stroke_box(124 &mut board,125 Frame::new(emblem.0 - half, emblem.1 - half, 2.0 * half, 2.0 * half),126 2.0,127 ink::fade(ink::yellow(), 0.85),128 );129 plot::dots(&mut board, &[emblem], 12.0, ink::yellow());130131 save("paper-design-dirichlet-inverse", &board)?;132 Ok(())133}