research-zeta.ts
2.3 kB · typescript · 58 lines
1import { frame, plot, type Frame, type Ink, type Pen, type Point } from "mrlyjs/view";2import census from "../files/figures/census/research-zeta.json" with { type: "json" };34type Panel = { columns: number[]; ordinates: number[]; family: number[][]; teeth: number[][]; hollow: number[][] };56const HEIGHT = 40;7const WIDE = 1.2;8const REACH = 0.7;910export const units = {};1112// FACTS1314function check(p: Panel, sizes: [number, number, number]) {15 const counts = [p.family.length, p.teeth.length, p.hollow.length];16 if (counts.some((n, i) => n !== sizes[i])) throw new Error(`research-zeta: zeros ${counts}, want ${sizes}`);17 if (p.columns.length !== 2) throw new Error(`research-zeta: ${p.columns.length} pole columns, want 2`);18 const [alpha] = p.columns;19 for (const [re, im] of [...p.family, ...p.teeth, ...p.hollow]) {20 if (!(re > alpha - WIDE && re < alpha + REACH && im > 0 && im < HEIGHT)) throw new Error(`research-zeta: zero ${re} ${im} off the strip`);21 }22}2324// PANEL2526function panel(pen: Pen, ink: Ink, box: Frame, p: Panel) {27 const [alpha, below] = p.columns;28 const lo = alpha - WIDE;29 const hi = alpha + REACH;30 const at = (re: number, im: number): Point => [box.x + (box.w * (re - lo)) / (hi - lo), box.y + box.h * (1 - im / HEIGHT)];31 pen.rect(box.x, box.y, box.w, box.h, ink.panel);32 plot.axis(pen, box, ink.line);33 pen.segment(at(alpha, 0), at(alpha, HEIGHT), 1.6, ink.fade(ink.dim, 0.5));34 pen.segment(at(below, 0), at(below, HEIGHT), 1.6, ink.fade(ink.dim, 0.3));35 for (const t of p.ordinates) {36 if (t < 0.4) continue;37 for (const line of p.columns) {38 const [x, y] = at(line, t);39 pen.ring(x, y, 11, 1.6, ink.fade(ink.dim, 0.9));40 }41 }42 for (const [re, im] of p.family) pen.disc(...at(re, im), 7, ink.blue);43 for (const [re, im] of p.teeth) pen.disc(...at(re, im), 7, ink.yellow);44 for (const [re, im] of p.hollow) pen.disc(...at(re, im), 7, ink.fade(ink.fg, 0.9));45}4647// DRAW4849export default function draw(pen: Pen, ink: Ink) {50 const { design, full } = census as { design: Panel; full: Panel };51 check(design, [7, 6, 0]);52 check(full, [6, 0, 4]);53 const area = pen.area(0.08);54 const wide = area.w * 0.45;55 const tall = area.h * 0.8;56 panel(pen, ink, frame(area.x, area.y, wide, tall), design);57 panel(pen, ink, frame(area.x + area.w - wide, area.y + area.h - tall, wide, tall), full);58}