import { Ink } from './ink'; export interface Dot { x: number; y: number; z: number; r: number; /** Ink value: 0 = darkest ink on paper. Mirrored on dark themes. */ white: number; a?: number; } /** A stroked edge between two projected points (the `connecting` web). */ export interface Line { x1: number; y1: number; x2: number; y2: number; /** Ink value, same convention as `Dot.white`. */ white: number; a?: number; w: number; } export type Projector = (x: number, y: number, z: number) => [number, number, number]; export declare function lerp(a: number, b: number, f: number): number; export declare function frac(x: number): number; /** Value noise on a 2D lattice — smooth, deterministic, cheap. */ export declare function vnoise(x: number, y: number): number; /** Deterministic hash in [0, 1). */ export declare function hashD(a: number, b: number): number; /** Stable directions on a unit sphere (Fibonacci lattice). */ export declare function fibDir(i: number, n: number): [number, number, number]; /** Shortest signed angular distance, wrapped to (-π, π]. */ export declare function angleDelta(a: number, b: number): number; /** Shared spin + tilt + orthographic projection. */ export declare function makeProj(yaw: number, tilt: number, cx: number, cy: number, scale: number): Projector; /** * Painter: z-sort far→near, matte dots. On dark substrates the ink value is * mirrored (1 - white) so near dots read bright — the same depth language * on an inverted substrate. A gradient ink keeps that depth and adds hue. */ export declare function paint(ctx: CanvasRenderingContext2D, dots: Dot[], ink: Ink, rMin?: number): void; /** Stroke pass for edge-based modes. Runs before `paint` so nodes sit on top. */ export declare function paintLines(ctx: CanvasRenderingContext2D, lines: Line[], ink: Ink): void; /** * Dot radii were tuned for a 300pt frame; sub-linear scaling keeps small * spinners legible. Lower pow = radii shrink less with size. */ export declare function radiusScale(size: number, pow: number): number;