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}