grid
The generative layer, and the only part of the package with no opinion about pixels. A field is read on a lattice of cells, each level is quantized against an alphabet, and what comes out is characters.
import { calibrate, glyphAt, normalize, ramp, sample } from "@mariovagomarzal/lattice";
const field = (x: number, y: number, t: number) => Math.sin(2 * Math.hypot(x, y) - 1.5 * t);
const lattice = { columns: 60, rows: 20, span: 7 };
const levels = sample(normalize(field, calibrate(field)), lattice, 0);
const glyphs = Array.from(levels, (level) => glyphAt(level, ramp));:+***:· ·:+*xx*+::·:+*x#####xx*******++:· ·:+*xxx+:··:*x##x :***+:· ·:+xxx*:··:+*x#####x**++++++***+:·· ·:*xxx*+:·:+x##x +***+· ·:*xx*+:··:+x####x**+::···::+***+:···:+xx#x*:::+*### +**+:· ·+*x*+:···:*x##x**+::·· ·:+*x*+:··:+*x#x*+::+*x## +**+: :+***:· ·+*xxx*++::::· ·+*xx*+:··:*x##x+:::*x## +**+· :+**+:· ·:+*xx*+:::+++:·· ·:*xxx*+:::*x##x*+::+x## +**:· ·:+**+· ·:+*x*+:··:+***+:· ·:+x##x*:::+x###*+::+x## +*+:· ·:+**:· ·:***+:···+*##x*+::··:+x##x*+::+x###x+::+x## +*+: ·:**+:· ·:***:· ·+x##x***+:::+*###x+::+*###x+::+x## **+: ·:**+: ·:**+: ·+*x#**x#x+::+*###x+::+*###x+::+*## **+: ·:**+: ·:**+: ·:**+*###x*::+*###x*::+*###x+::+*## **+: ·:**+: ·:**+: ·+*x#**x#x+::+*###x+::+*###x+::+*## +*+: ·:**+:· ·:***:· ·+x##x***+:::+*###x+::+*###x+::+x## +*+:· ·:+**:· ·:***+:···+*##x*+::··:+x##x*+::+x###x+::+x## +**:· ·:+**+· ·:+*x*+:··:+***+:· ·:+x##x*:::+x###*+::+x## +**+· :+**+:· ·:+*xx*+:::+++:·· ·:*xxx*+:::*x##x*+::+x## +**+: :+***:· ·+*xxx*++::::· ·+*xx*+:··:*x##x+:::*x## +**+:· ·+*x*+:···:*x##x**+::·· ·:+*x*+:··:+*x#x*+::+*x## +***+· ·:*xx*+:··:+x####x**+::···::+***+:···:+xx#x*:::+*### :***+:· ·:+xxx*:··:+*x#####x**++++++***+:·· ·:*xxx*+:·:+x##x
The alphabet
0–14%
·14–29%
:29–43%
+43–57%
*57–71%
x71–86%
#86–100%
Reference
| export | signature | what it is |
|---|---|---|
| Field | (x, y, t) => number | A scalar field. The package ships none of its own. |
| Range | { lo, hi } | The low and high ends a field is rescaled against. |
| Lattice | { columns, rows, span } | The cell counts, and the field units the short side covers. |
| ramp | readonly string[] | Seven characters, from empty to full ink. |
| glyphAt | (level, alphabet?) => string | The glyph a level in [0, 1] quantizes to. |
| calibrate | (field, options?) => Range | A field's range, sampled across space and a few instants of time. An estimate, not a bound. |
| normalize | (field, range) => Field | The field wrapped into one that lands in [0, 1], clamping the rest. |
| sample | (field, lattice, t) => Float64Array | The field at every cell center, in row order, as levels[row * columns + col]. |
| fieldPoint | (lattice, col, row) => { x, y } | The field coordinates of a cell, from the origin at its center. Takes fractional indices. |
| latticePoint | (lattice, x, y) => { col, row } | The cell a field point falls on, as fractional indices. |