research-slices.rs

3.1 kB · rust · 92 lines

1use mrlycore::errors::Result;2use mrlycore::Color;3use mrlyfig::board::{Board, Frame};4use mrlyfig::{hex, ink, save};5use mrlymath::six;6use mrlymath::six::Cell6d;78const SIDE: usize = 11;910fn at(cell: &Cell6d, row: usize, col: usize) -> u8 {11    let offset = (cell.width() - hex::row_len(SIDE, row)) / 2;12    cell.cell.types().get(&[row, col + offset])13}1415const RATIO: f64 = 0.866_025_403_784_438_6;1617fn shrink(pts: [(f64, f64); 3], gap: f64) -> [(f64, f64); 3] {18    let cx = (pts[0].0 + pts[1].0 + pts[2].0) / 3.0;19    let cy = (pts[0].1 + pts[1].1 + pts[2].1) / 3.0;20    let edge = ((pts[1].0 - pts[0].0).powi(2) + (pts[1].1 - pts[0].1).powi(2)).sqrt();21    let inradius = edge / (2.0 * 3f64.sqrt());22    let k = ((inradius - gap) / inradius).max(0.0);23    let pull = |p: (f64, f64)| (cx + (p.0 - cx) * k, cy + (p.1 - cy) * k);24    [pull(pts[0]), pull(pts[1]), pull(pts[2])]25}2627fn hexagon(28    board: &mut Board,29    frame: Frame,30    n: usize,31    gap: f64,32    ink: impl Fn(usize, usize) -> Option<Color>,33) {34    let edge = (frame.w / (2 * n) as f64).min(frame.h / (n as f64 * 2.0 * RATIO));35    let rise = edge * RATIO;36    let (cx, cy) = frame.center();37    let left = cx - edge * n as f64;38    let top = cy - rise * n as f64;39    for row in 0..2 * n {40        let reach = if row < n { row } else { 2 * n - 1 - row };41        let up = row < n;42        let (long, short) = (n + reach + 1, n + reach);43        let (top_len, bot_len) = if up { (short, long) } else { (long, short) };44        let tx = left + (2 * n - top_len) as f64 * edge / 2.0;45        let bx = left + (2 * n - bot_len) as f64 * edge / 2.0;46        let (y0, y1) = (top + row as f64 * rise, top + (row + 1) as f64 * rise);47        for col in 0..top_len + bot_len {48            let points = if (col % 2 == 0) == up {49                let j = (col / 2) as f64;50                [51                    (bx + j * edge, y1),52                    (bx + (j + 1.0) * edge, y1),53                    (bx + (j + 0.5) * edge, y0),54                ]55            } else {56                let i = (col / 2) as f64;57                [58                    (tx + i * edge, y0),59                    (tx + (i + 1.0) * edge, y0),60                    (tx + (i + 0.5) * edge, y1),61                ]62            };63            if let Some(color) = ink(row, col) {64                let small = shrink(points, gap);65                board.triangle(small[0], small[1], small[2], color);66            }67        }68    }69}7071fn main() -> Result<()> {72    let carpet = six::cut_design(23, SIDE, 1, 2)?;73    let net = six::cut_design(232, SIDE, 1, 2)?;74    assert_eq!(six::fills(&carpet), 486);75    assert_eq!(six::fills(&net), 240);76    assert_eq!(six::holes(&carpet)?, 19);77    assert_eq!(six::fills(&carpet) + six::fills(&net), hex::count(SIDE));7879    let mut board = Board::square();80    let frame = board.frame(0.08);81    hexagon(&mut board, frame, SIDE, 1.6, |row, col| {82        if at(&carpet, row, col) == six::FILL {83            Some(ink::blue())84        } else if at(&net, row, col) == six::FILL {85            Some(ink::orange())86        } else {87            None88        }89    });90    save("research-slices", &board)?;91    Ok(())92}