research-method.rs

3.3 kB · rust · 110 lines

1use mrlycore::errors::Result;2use mrlyfig::{ink, iso, save, Board, Color};3use mrlymath::bang::bang;4use mrlymath::three::designs;5use mrlymath::three::faces::quads;6use mrlymath::three::Cell3d;78const ROWS: usize = 9;9const WIDEST: f64 = 6.5;1011fn cage(cx: f64, cy: f64, s: f64) -> Vec<[(f64, f64); 2]> {12    let corner = |i: usize| {13        let bit = |b: usize| ((i >> b) & 1) as f64 * 2.0 - 1.0;14        let p = iso::project(bit(0), bit(1), bit(2));15        (cx + p.0 * s, cy + p.1 * s)16    };17    let mut out = Vec::new();18    for a in 0usize..8 {19        for b in (a + 1)..8 {20            if (a ^ b).count_ones() == 1 {21                out.push([corner(a), corner(b)]);22            }23        }24    }25    out26}2728fn stamp(board: &mut Board, cell: &Cell3d, cx: f64, cy: f64, s: f64, shade: [Color; 3]) {29    let mut faces = Vec::new();30    for quad in quads(cell) {31        let n = (32            quad.normal.x as f64,33            quad.normal.y as f64,34            quad.normal.z as f64,35        );36        if n.0 + n.1 + n.2 <= 0.0 {37            continue;38        }39        let tone = if n.2 > 0.0 {40            041        } else if n.1 > 0.0 {42            143        } else {44            245        };46        let pts: Vec<(f64, f64)> = quad47            .verts48            .iter()49            .map(|v| {50                let p = iso::project(v.x as f64, v.y as f64, v.z as f64);51                (cx + p.0 * s, cy + p.1 * s)52            })53            .collect();54        let depth = quad55            .verts56            .iter()57            .map(|v| (v.x + v.y + v.z) as f64)58            .sum::<f64>();59        faces.push((depth, tone, pts));60    }61    faces.sort_by(|a, b| a.0.total_cmp(&b.0));62    for (_, tone, pts) in &faces {63        board.polygon(pts, shade[*tone]);64        let mut ring = pts.clone();65        ring.push(pts[0]);66        board.polyline(&ring, s / 14.0, ink::ground());67    }68}6970fn main() -> Result<()> {71    let mut board = Board::square();72    let frame = board.frame(0.08);73    let mut rows: Vec<Vec<u128>> = vec![Vec::new(); ROWS];74    for design in bang(3).canonical() {75        rows[design.i.count_ones() as usize].push(design.i);76    }77    assert_eq!(78        rows.iter().map(|r| r.len()).collect::<Vec<usize>>(),79        vec![1, 1, 3, 3, 6, 3, 3, 1, 1]80    );81    assert_eq!(rows.iter().map(|r| r.len()).sum::<usize>(), 22);82    let shade = [83        ink::blue(),84        ink::mix(ink::blue(), ink::ground(), 0.4),85        ink::mix(ink::blue(), ink::ground(), 0.65),86    ];87    let (mx, my) = frame.center();88    let pitch = frame.h / ROWS as f64;89    let step = frame.w / WIDEST;90    let s = pitch * 0.225;91    for (r, codes) in rows.iter().enumerate() {92        let cy = my + (r as f64 - (ROWS as f64 - 1.0) / 2.0) * pitch;93        for (j, code) in codes.iter().enumerate() {94            let cx = mx + (j as f64 - (codes.len() as f64 - 1.0) / 2.0) * step;95            for edge in cage(cx, cy, s) {96                board.segment(97                    edge[0],98                    edge[1],99                    s / 20.0,100                    ink::mix(ink::line(), ink::dim(), 0.3),101                );102            }103            let cube = designs::create(*code, 2, 1, 2)?;104            assert_eq!(cube.types().sum(), r as u64);105            stamp(&mut board, &cube, cx, cy, s, shade);106        }107    }108    save("research-method", &board)?;109    Ok(())110}