Added QFT
This commit is contained in:
373
tools/qft-variations-craft.mjs
Normal file
373
tools/qft-variations-craft.mjs
Normal file
@@ -0,0 +1,373 @@
|
||||
/* ============================================================
|
||||
qft-variations-craft.mjs — sketch 06.
|
||||
Each variation isolates ONE craft idea so the effect is
|
||||
readable on its own. Five blocks:
|
||||
|
||||
A · Cubic origin plays — push origin off-page or into the
|
||||
viewer's space along the (isometric) Z axis
|
||||
B · Multi-rosettes — offset origins, varied scales
|
||||
C · Lighter-on-midtone — paper at MID tone so a brighter
|
||||
rosette can actually read as lighter-than-ground
|
||||
D · Plain white on light — bold white strokes on warm paper
|
||||
E · Schlegel plays — weight / origin / shifted axes
|
||||
(outerR · innerR · rot3D)
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch06';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
|
||||
({ hueStart, hueEnd, saturation, lightness, opacity });
|
||||
const paper = (flat, glowInDelta = [18, 16, 14], glowOutDelta = [-25, -22, -20]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
const WHITE = (op = 0.95) => F(0, 0, 0, 0.97, op);
|
||||
|
||||
const variations = [
|
||||
// ─────────────────────── BLOCK A · cubic origin plays ───────────────────────
|
||||
{
|
||||
name: 'A1_cubic-origin-far-right',
|
||||
label: 'A1 · cubic origin pushed off-page right — orthogonal mesh streams in from the right edge',
|
||||
overrides: {
|
||||
paperOverride: paper([225, 215, 200]),
|
||||
vignOverride: [70, 60, 45], featureOverride: [60, 45, 30],
|
||||
stroke: 1.8, gradientMode: 'linear-x',
|
||||
cubicScale: 1.4, cubicOriginX: 1.45, cubicOriginY: 0, // mostly off-screen to the right
|
||||
schlegelScale: 0.65,
|
||||
distStrength: 0, // disable distortion when origin is offset
|
||||
e8Origins: [{ x: -0.45, y: 0, scale: 0.42 }], // counterweight rosette left
|
||||
linkCount: 4,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.08, 0.65, 0.35, 0.78),
|
||||
schlegel: F(0.10, 0.08, 0.45, 0.40, 0.55),
|
||||
e8: F(0.10, 0.04, 0.65, 0.45, 0.88),
|
||||
links: F(0.05, 0.10, 0.70, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'A2_cubic-zoom-toward-viewer',
|
||||
label: 'A2 · cubic zoomed in (Z toward viewer) — we are INSIDE the lattice',
|
||||
overrides: {
|
||||
paperOverride: paper([225, 215, 198]),
|
||||
vignOverride: [60, 50, 35], featureOverride: [70, 55, 30],
|
||||
stroke: 2.4,
|
||||
cubicScale: 3.2, // huge — fills well past the frame
|
||||
schlegelScale: 0,
|
||||
distStrength: 0,
|
||||
e8Origins: [{ x: 0.55, y: 0.55, scale: 0.32 }], // single small rosette one corner
|
||||
linkCount: 3,
|
||||
fields: {
|
||||
cubic: F(0.04, 0.13, 0.65, 0.32, 0.80),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.05, 0.12, 0.65, 0.45, 0.88),
|
||||
links: F(0.06, 0.12, 0.65, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'A3_cubic-origin-upper-left',
|
||||
label: 'A3 · cubic origin pushed upper-left, rest of canvas opens to lower-right',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 222, 205]),
|
||||
vignOverride: [70, 55, 40], featureOverride: [60, 50, 35],
|
||||
stroke: 1.6, gradientMode: 'radial',
|
||||
cubicScale: 1.6, cubicOriginX: -0.85, cubicOriginY: -0.85,
|
||||
schlegelScale: 0.55, schlegelOriginX: -0.30, schlegelOriginY: -0.30,
|
||||
distStrength: 0,
|
||||
e8Origins: [{ x: 0.40, y: 0.40, scale: 0.45 }], // rosette in opposing corner
|
||||
linkCount: 4,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.65, 0.36, 0.80),
|
||||
schlegel: F(0.58, 0.10, 0.45, 0.40, 0.60),
|
||||
e8: F(0.06, 0.12, 0.70, 0.45, 0.88),
|
||||
links: F(0.05, 0.10, 0.65, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ─────────────────────── BLOCK B · multi-rosettes ────────────────────────────
|
||||
{
|
||||
name: 'B1_three-rosettes-horizontal',
|
||||
label: 'B1 · three rosettes along a horizontal axis',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 222, 205]),
|
||||
vignOverride: [60, 50, 35], featureOverride: [55, 45, 30],
|
||||
stroke: 1.8,
|
||||
cubicScale: 1.3, schlegelScale: 0,
|
||||
e8Origins: [
|
||||
{ x: -0.55, y: 0, scale: 0.32 },
|
||||
{ x: 0.00, y: 0, scale: 0.42 },
|
||||
{ x: 0.55, y: 0, scale: 0.32 },
|
||||
],
|
||||
linkCount: 6,
|
||||
fields: {
|
||||
cubic: F(0.50, 0.10, 0.45, 0.40, 0.35),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.55, 0.05, 0.55, 0.48, 0.85),
|
||||
links: F(0.06, 0.12, 0.65, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'B2_triangular-rosette-cluster',
|
||||
label: 'B2 · three rosettes in a triangle · varied sizes',
|
||||
overrides: {
|
||||
paperOverride: paper([222, 210, 220]),
|
||||
vignOverride: [55, 40, 60], featureOverride: [65, 45, 75],
|
||||
stroke: 1.6,
|
||||
cubicScale: 1.4, schlegelScale: 0.65,
|
||||
e8Origins: [
|
||||
{ x: 0.00, y: -0.45, scale: 0.50 },
|
||||
{ x: -0.45, y: 0.30, scale: 0.32 },
|
||||
{ x: 0.45, y: 0.30, scale: 0.32 },
|
||||
],
|
||||
linkCount: 6,
|
||||
fields: {
|
||||
cubic: F(0.78, 0.92, 0.50, 0.38, 0.40),
|
||||
schlegel: F(0.82, 0.92, 0.40, 0.40, 0.50),
|
||||
e8: F(0.82, 0.95, 0.55, 0.46, 0.85),
|
||||
links: F(0.85, 0.96, 0.65, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'B3_five-rosettes-quincunx',
|
||||
label: 'B3 · quincunx: 4 corners + centre · five rosettes total',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 222, 205]),
|
||||
vignOverride: [60, 50, 35], featureOverride: [55, 45, 30],
|
||||
stroke: 1.6,
|
||||
cubicScale: 1.3, schlegelScale: 0,
|
||||
e8Origins: [
|
||||
{ x: -0.50, y: -0.50, scale: 0.26 },
|
||||
{ x: 0.50, y: -0.50, scale: 0.26 },
|
||||
{ x: 0.00, y: 0.00, scale: 0.42 },
|
||||
{ x: -0.50, y: 0.50, scale: 0.26 },
|
||||
{ x: 0.50, y: 0.50, scale: 0.26 },
|
||||
],
|
||||
linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.10, 0.16, 0.40, 0.40, 0.35),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.10, 0.16, 0.60, 0.45, 0.85),
|
||||
links: F(0.06, 0.12, 0.65, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'B4_central-large-plus-orbit',
|
||||
label: 'B4 · one large central rosette + smaller orbiting satellites',
|
||||
overrides: {
|
||||
paperOverride: paper([225, 215, 198]),
|
||||
vignOverride: [60, 50, 35], featureOverride: [55, 45, 30],
|
||||
stroke: 1.6, gradientMode: 'radial',
|
||||
cubicScale: 1.4, schlegelScale: 0,
|
||||
e8Origins: [
|
||||
{ x: 0.00, y: 0.00, scale: 0.70 },
|
||||
{ x: 0.55, y: -0.55, scale: 0.18 },
|
||||
{ x: -0.55, y: -0.55, scale: 0.18 },
|
||||
{ x: 0.00, y: 0.62, scale: 0.18 },
|
||||
],
|
||||
linkCount: 6,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.55, 0.38, 0.35),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.55, 0.05, 0.55, 0.46, 0.85),
|
||||
links: F(0.06, 0.12, 0.70, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ────────────────── BLOCK C · lighter-on-midtone ─────────────────────────────
|
||||
{
|
||||
name: 'C1_lighter-on-deep-cream',
|
||||
label: 'C1 · lighter rosette on DEEP-cream midtone',
|
||||
overrides: {
|
||||
paperOverride: paper([180, 165, 140]), // mid-tone deep cream
|
||||
vignOverride: [90, 70, 45], featureOverride: [240, 230, 215],
|
||||
stroke: 2.4,
|
||||
cubicScale: 1.45, schlegelScale: 0.75,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.78 }],
|
||||
fields: {
|
||||
cubic: F(0.06, 0.13, 0.30, 0.38, 0.55),
|
||||
schlegel: F(0.08, 0.10, 0.30, 0.38, 0.50),
|
||||
e8: F(0.08, 0.13, 0.20, 0.88, 0.80), // LIGHTER than the midtone paper
|
||||
links: F(0.06, 0.12, 0.40, 0.92, 0.85),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'C2_lighter-on-warm-grey',
|
||||
label: 'C2 · lighter rosette on warm-grey midtone',
|
||||
overrides: {
|
||||
paperOverride: paper([155, 150, 140]), // warm grey midtone
|
||||
vignOverride: [80, 70, 55], featureOverride: [235, 230, 220],
|
||||
stroke: 2.6,
|
||||
cubicScale: 1.55, schlegelScale: 0,
|
||||
e8Origins: [{ x: -0.20, y: 0, scale: 0.55 },
|
||||
{ x: 0.20, y: 0, scale: 0.55 }],
|
||||
fields: {
|
||||
cubic: F(0.06, 0.12, 0.20, 0.40, 0.55),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.06, 0.12, 0.18, 0.90, 0.80), // pale ivory on grey
|
||||
links: F(0.06, 0.12, 0.30, 0.94, 0.85),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'C3_lighter-on-sage',
|
||||
label: 'C3 · lighter rosette on sage-grey midtone',
|
||||
overrides: {
|
||||
paperOverride: paper([155, 165, 145]), // sage midtone
|
||||
vignOverride: [55, 70, 50], featureOverride: [225, 235, 215],
|
||||
stroke: 2.4,
|
||||
cubicScale: 1.4, schlegelScale: 0.75,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.82 }],
|
||||
fields: {
|
||||
cubic: F(0.40, 0.48, 0.30, 0.42, 0.55),
|
||||
schlegel: F(0.42, 0.48, 0.25, 0.40, 0.50),
|
||||
e8: F(0.40, 0.48, 0.22, 0.90, 0.80),
|
||||
links: F(0.40, 0.50, 0.35, 0.94, 0.85),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ────────────────── BLOCK D · plain white on light ───────────────────────────
|
||||
{
|
||||
name: 'D1_thick-white-on-cream',
|
||||
label: 'D1 · bold WHITE strokes on warm cream — embossed',
|
||||
overrides: {
|
||||
paperOverride: paper([222, 210, 188]),
|
||||
vignOverride: [70, 55, 35], featureOverride: [60, 50, 35],
|
||||
stroke: 3.4, // thick
|
||||
cubicScale: 1.45, schlegelScale: 1.20,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.72 }],
|
||||
fields: {
|
||||
cubic: WHITE(0.85),
|
||||
schlegel: WHITE(0.65),
|
||||
e8: WHITE(0.92),
|
||||
links: WHITE(0.78),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'D2_white-on-pale-rose',
|
||||
label: 'D2 · plain white rosettes on pale rose',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 210, 210]),
|
||||
vignOverride: [80, 55, 55], featureOverride: [90, 55, 55],
|
||||
stroke: 3.2,
|
||||
cubicScale: 1.35, schlegelScale: 0,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.95 },
|
||||
{ x: 0, y: 0, scale: 0.60 },
|
||||
{ x: 0, y: 0, scale: 0.30 }],
|
||||
linkCount: 0,
|
||||
fields: {
|
||||
cubic: WHITE(0.40), // very subtle cubic atmosphere
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: WHITE(0.95), // strong solid white rosettes
|
||||
links: WHITE(0.5),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'D3_white-on-pale-blue',
|
||||
label: 'D3 · white schlegel + white rosette on pale blue',
|
||||
overrides: {
|
||||
paperOverride: paper([190, 215, 230]),
|
||||
vignOverride: [40, 55, 70], featureOverride: [30, 50, 75],
|
||||
stroke: 3.0,
|
||||
cubicScale: 1.0, schlegelScale: 1.50, // schlegel prominent
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.65 }],
|
||||
fields: {
|
||||
cubic: WHITE(0.45),
|
||||
schlegel: WHITE(0.85), // bold white tesseract
|
||||
e8: WHITE(0.92),
|
||||
links: WHITE(0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ────────────────── BLOCK E · schlegel plays ─────────────────────────────────
|
||||
{
|
||||
name: 'E1_schlegel-thin-nested',
|
||||
label: 'E1 · Schlegel: deep nesting (tiny inner cube) · thin lines',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 222, 200]),
|
||||
vignOverride: [60, 50, 40], featureOverride: [60, 50, 35],
|
||||
stroke: 1.4,
|
||||
cubicScale: 0.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.08, // very small inner cube → strong perspective
|
||||
schlegelRot3D: 0.20,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.42 }],
|
||||
fields: {
|
||||
cubic: F(0.58, 0.62, 0.30, 0.45, 0.40),
|
||||
schlegel: F(0.60, 0.68, 0.50, 0.32, 0.78), // schlegel is the subject
|
||||
e8: F(0.55, 0.65, 0.50, 0.45, 0.78),
|
||||
links: F(0.58, 0.66, 0.65, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'E2_schlegel-shifted-axis-thick',
|
||||
label: 'E2 · Schlegel with strongly rotated 4D axis · thick lines',
|
||||
overrides: {
|
||||
paperOverride: paper([222, 212, 195]),
|
||||
vignOverride: [70, 55, 40], featureOverride: [60, 45, 30],
|
||||
stroke: 3.0, // thick
|
||||
cubicScale: 0.65, schlegelScale: 1.55,
|
||||
schlegelInnerR: 0.42, // larger inner cube — less perspective, more parallel
|
||||
schlegelRot3D: 1.10, // strong rotation — looking at the tesseract from different angle
|
||||
schlegelOriginX: 0.15,
|
||||
e8Origins: [{ x: -0.45, y: -0.45, scale: 0.32 }],
|
||||
fields: {
|
||||
cubic: F(0.06, 0.12, 0.35, 0.40, 0.40),
|
||||
schlegel: F(0.06, 0.13, 0.55, 0.32, 0.85),
|
||||
e8: F(0.08, 0.16, 0.65, 0.45, 0.85),
|
||||
links: F(0.06, 0.12, 0.65, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'E3_dual-schlegels-rotated',
|
||||
label: 'E3 · BIG schlegel offset · faint thin counter-rotated cubic',
|
||||
overrides: {
|
||||
paperOverride: paper([200, 200, 215]), // pale lavender-grey midtone
|
||||
vignOverride: [60, 55, 75], featureOverride: [40, 40, 60],
|
||||
stroke: 2.6,
|
||||
cubicScale: 1.6, cubicRot: 0.80, // cubic strongly rotated
|
||||
schlegelScale: 1.85, // schlegel very large bleeding
|
||||
schlegelInnerR: 0.55, // inner cube larger
|
||||
schlegelRot3D: -0.30, // negative rotation — opposite angle
|
||||
schlegelOriginX: -0.10, schlegelOriginY: 0.10,
|
||||
e8Origins: [{ x: 0.40, y: -0.40, scale: 0.32 },
|
||||
{ x: -0.40, y: 0.40, scale: 0.32 }],
|
||||
fields: {
|
||||
cubic: F(0.62, 0.70, 0.30, 0.55, 0.35),
|
||||
schlegel: F(0.62, 0.72, 0.55, 0.32, 0.78),
|
||||
e8: F(0.65, 0.75, 0.60, 0.45, 0.85),
|
||||
links: F(0.62, 0.78, 0.70, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
251
tools/qft-variations-fine.mjs
Normal file
251
tools/qft-variations-fine.mjs
Normal file
@@ -0,0 +1,251 @@
|
||||
/* ============================================================
|
||||
qft-variations-fine.mjs — sketch 05.
|
||||
Two new mechanics exercised:
|
||||
(a) DENSER cubic mesh (cubicN=2 → 125 vertices / ~300 edges)
|
||||
+ finer photon waves (photonCyclesPerUnit ↑) → "even
|
||||
finer oscillating sub-grid with each line another hue
|
||||
in a gradient"
|
||||
(b) LARGER softer rosettes — E8 cluster scaled 0.55–0.85
|
||||
with lightness pushed ABOVE the paper's lightness and
|
||||
opacity dropped to 0.35–0.55 → the rosette becomes a
|
||||
soft luminous halo rather than a focal jewel.
|
||||
Plus fewer / dimmer cross-field links so they punctuate
|
||||
instead of dominate.
|
||||
Output → output/qft/sketch05/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch05';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
|
||||
({ hueStart, hueEnd, saturation, lightness, opacity });
|
||||
|
||||
const paper = (flat, glowInDelta = [18, 16, 14], glowOutDelta = [-25, -22, -20]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
|
||||
// shared base for the new sketches
|
||||
// Dense cubic (300 edges) needs MUCH thinner strokes than sketch04, otherwise it
|
||||
// piles into solid wallpaper and buries the soft rosettes. Stroke 1.0 + cubic
|
||||
// opacity ~0.45 leaves room for the rosette + schlegel to read.
|
||||
const FINE_BASE = {
|
||||
cubicN: 2, // 5³=125 vertices / ~300 edges
|
||||
photonCyclesPerUnit: 22, // finer waves than default (12)
|
||||
segmentsPerEdge: 10,
|
||||
linkCount: 5, // fewer cross-field links (was 8)
|
||||
stroke: 1.0, // thin so the dense mesh stays atmospheric, not opaque
|
||||
};
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_spectral-comb-pearl',
|
||||
label: 'Spectral comb · pearl · dense cubic + radial spectrum + soft rosette',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([240, 235, 230]),
|
||||
vignOverride: [80, 70, 65], featureOverride: [80, 70, 60],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.40, schlegelScale: 0, // no schlegel — let cubic + rosette breathe
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.72 }], // single large central rosette
|
||||
fields: {
|
||||
cubic: F(0.55, 0.04, 0.65, 0.45, 0.30), // cool centre → warm corners
|
||||
schlegel: F(0, 0, 0, 0.5, 0), // off
|
||||
e8: F(0.55, 0.08, 0.55, 0.48, 0.85), // very pale tinted-white halo (L > paper)
|
||||
links: F(0.04, 0.10, 0.55, 0.45, 0.55), // dim warm links
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_dense-radial-cream',
|
||||
label: 'Dense radial spectrum · cream · large pale rosette',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
substrate: 'cream',
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.55, schlegelScale: 0.85,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.78 }],
|
||||
fields: {
|
||||
cubic: F(0.58, 0.05, 0.70, 0.40, 0.30),
|
||||
schlegel: F(0.10, 0.05, 0.35, 0.45, 0.55),
|
||||
e8: F(0.08, 0.04, 0.55, 0.48, 0.85), // pale warm halo on cream
|
||||
links: F(0.05, 0.10, 0.60, 0.45, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_linear-horizon-ivory',
|
||||
label: 'Linear horizon · ivory · dense cubic with left→right gradient',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([232, 224, 202]),
|
||||
vignOverride: [70, 55, 40], featureOverride: [60, 50, 35],
|
||||
gradientMode: 'linear-x',
|
||||
cubicScale: 1.65, schlegelScale: 0.90,
|
||||
e8Origins: [{ x: -0.35, y: 0.25, scale: 0.55 },
|
||||
{ x: 0.35, y: 0.25, scale: 0.55 }], // twin pale rosettes lower
|
||||
fields: {
|
||||
cubic: F(0.58, 0.04, 0.65, 0.36, 0.30),
|
||||
schlegel: F(0.60, 0.08, 0.40, 0.40, 0.55),
|
||||
e8: F(0.55, 0.10, 0.55, 0.48, 0.85),
|
||||
links: F(0.06, 0.12, 0.60, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_twin-rosettes-mauve',
|
||||
label: 'Twin overlapping rosettes · pale mauve · soft & atmospheric',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([222, 205, 224]),
|
||||
vignOverride: [55, 35, 60], featureOverride: [75, 50, 90],
|
||||
gradientMode: 'along-edge',
|
||||
cubicScale: 1.45, schlegelScale: 0, // no schlegel
|
||||
e8Origins: [{ x: -0.20, y: 0, scale: 0.65 },
|
||||
{ x: 0.20, y: 0, scale: 0.65 }],
|
||||
fields: {
|
||||
cubic: F(0.72, 0.92, 0.55, 0.38, 0.30),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.78, 0.92, 0.55, 0.48, 0.85), // pale lighter-than-mauve glow
|
||||
links: F(0.82, 0.95, 0.65, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_finest-waves-linen',
|
||||
label: 'Finest photon waves · linen · super-dense cubic + soft halo',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([225, 210, 178]),
|
||||
vignOverride: [85, 60, 35], featureOverride: [80, 55, 30],
|
||||
photonCyclesPerUnit: 30, // even finer ripples than the FINE_BASE
|
||||
cubicScale: 1.50, schlegelScale: 0.75,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.82 }],
|
||||
fields: {
|
||||
cubic: F(0.08, 0.14, 0.60, 0.35, 0.30),
|
||||
schlegel: F(0.04, 0.10, 0.40, 0.35, 0.55),
|
||||
e8: F(0.10, 0.06, 0.55, 0.48, 0.85),
|
||||
links: F(0.06, 0.10, 0.60, 0.40, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_big-mandala-pale-blue',
|
||||
label: 'Big central mandala · pale blue · single huge rosette',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([190, 215, 230]),
|
||||
vignOverride: [40, 55, 70], featureOverride: [30, 50, 75],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.50, schlegelScale: 0.80,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.92 }], // very large central rosette
|
||||
fields: {
|
||||
cubic: F(0.60, 0.66, 0.65, 0.25, 0.30),
|
||||
schlegel: F(0.58, 0.62, 0.45, 0.28, 0.55),
|
||||
e8: F(0.55, 0.65, 0.55, 0.48, 0.85), // near-white tinted-blue halo
|
||||
links: F(0.58, 0.66, 0.65, 0.32, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_dense-ghostly-schlegel-bone',
|
||||
label: 'Dense cubic + ghostly large Schlegel · bone china',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([234, 230, 222]),
|
||||
vignOverride: [80, 70, 60], featureOverride: [70, 60, 50],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.55, schlegelScale: 1.85, // big BUT...
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.72 }],
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.65, 0.38, 0.30),
|
||||
schlegel: F(0.62, 0.10, 0.25, 0.92, 0.35), // ...made ghostly: pale + low opacity
|
||||
e8: F(0.10, 0.06, 0.55, 0.48, 0.85),
|
||||
links: F(0.06, 0.10, 0.55, 0.40, 0.50),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_atmospheric-mint',
|
||||
label: 'Atmospheric · pale mint · large soft rosette dominant',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([210, 225, 208]),
|
||||
vignOverride: [30, 55, 35], featureOverride: [40, 70, 45],
|
||||
stroke: 1.6, // thinner — let the rosette breathe
|
||||
cubicScale: 1.30, schlegelScale: 0,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.85 }],
|
||||
fields: {
|
||||
cubic: F(0.42, 0.50, 0.45, 0.36, 0.30),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.40, 0.50, 0.55, 0.48, 0.85),
|
||||
links: F(0.12, 0.18, 0.55, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_all-dense-layered-pearl',
|
||||
label: 'Everything dense and layered · pearl · 4 rosettes, full spectrum',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([240, 235, 230]),
|
||||
vignOverride: [80, 70, 65], featureOverride: [80, 70, 60],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.60, schlegelScale: 1.20,
|
||||
e8Origins: [
|
||||
{ x: -0.30, y: -0.30, scale: 0.42 },
|
||||
{ x: 0.30, y: -0.30, scale: 0.42 },
|
||||
{ x: -0.30, y: 0.30, scale: 0.42 },
|
||||
{ x: 0.30, y: 0.30, scale: 0.42 },
|
||||
],
|
||||
linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.65, 0.40, 0.30),
|
||||
schlegel: F(0.58, 0.10, 0.35, 0.42, 0.55),
|
||||
e8: F(0.55, 0.08, 0.55, 0.48, 0.85),
|
||||
links: F(0.06, 0.10, 0.55, 0.42, 0.55),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_concentric-rosettes-pale-rose',
|
||||
label: 'Concentric nested rosettes · pale rose · all centred',
|
||||
overrides: {
|
||||
...FINE_BASE,
|
||||
paperOverride: paper([232, 210, 210]),
|
||||
vignOverride: [80, 55, 55], featureOverride: [90, 55, 55],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.30, schlegelScale: 0,
|
||||
e8Origins: [
|
||||
{ x: 0, y: 0, scale: 0.95 }, // outermost
|
||||
{ x: 0, y: 0, scale: 0.62 }, // middle
|
||||
{ x: 0, y: 0, scale: 0.30 }, // innermost
|
||||
],
|
||||
linkCount: 0, // no links — the nested rosettes are the picture
|
||||
fields: {
|
||||
cubic: F(0.95, 0.03, 0.55, 0.38, 0.30),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0.92, 0.05, 0.55, 0.48, 0.85),
|
||||
links: F(0.9, 0.05, 0.55, 0.42, 0.50),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name} · ${v.label}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
230
tools/qft-variations-light.mjs
Normal file
230
tools/qft-variations-light.mjs
Normal file
@@ -0,0 +1,230 @@
|
||||
/* ============================================================
|
||||
qft-variations-light.mjs — sketch 04.
|
||||
Lighter backgrounds, larger field scales (most bleed past the
|
||||
frame), per-edge hue GRADIENTS within each field, and
|
||||
noticeably THICKER strokes than previous sketches. Custom
|
||||
paperOverride RGB for the more unusual pale grounds.
|
||||
Output → output/qft/sketch04/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch04';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
|
||||
({ hueStart, hueEnd, saturation, lightness, opacity });
|
||||
|
||||
// helper: build a paperOverride from one RGB and derive sensible glow stops
|
||||
const paper = (flat, glowInDelta = [18, 16, 14], glowOutDelta = [-25, -22, -20]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
|
||||
// dark header/vignette tones to read against light paper
|
||||
const DARK_FEATURE = [60, 48, 36];
|
||||
const DARK_VIGN = [70, 55, 40];
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_warm-sunset-cream',
|
||||
label: 'Warm sunset · cream · huge cubic bleeding past frame',
|
||||
overrides: {
|
||||
substrate: 'cream',
|
||||
stroke: 2.6,
|
||||
cubicScale: 1.75,
|
||||
schlegelScale: 0.85,
|
||||
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.10, 0.02, 0.65, 0.40, 0.82), // amber → red
|
||||
schlegel: F(0.13, 0.06, 0.45, 0.38, 0.65), // gold → orange
|
||||
e8: F(0.05, 0.13, 0.75, 0.42, 0.92), // red → gold
|
||||
links: F(0.95, 0.04, 0.85, 0.38, 0.96), // pink → red bright
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_pale-verdigris-linen',
|
||||
label: 'Pale verdigris · linen ground · large scales',
|
||||
overrides: {
|
||||
paperOverride: paper([222, 210, 184]),
|
||||
vignOverride: DARK_VIGN,
|
||||
featureOverride: DARK_FEATURE,
|
||||
stroke: 2.4,
|
||||
cubicScale: 1.55,
|
||||
schlegelScale: 1.35,
|
||||
e8Count: 3, e8Scale: 0.24, e8OriginRadius: 0.48,
|
||||
fields: {
|
||||
cubic: F(0.44, 0.50, 0.55, 0.34, 0.82), // teal → cyan
|
||||
schlegel: F(0.06, 0.10, 0.55, 0.38, 0.66), // copper accents
|
||||
e8: F(0.35, 0.46, 0.60, 0.32, 0.90), // sage → teal
|
||||
links: F(0.04, 0.10, 0.80, 0.38, 0.95),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_rose-peach',
|
||||
label: 'Rose pastel on peach paper · huge cubic',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 200, 175]),
|
||||
vignOverride: [90, 50, 40],
|
||||
featureOverride: [110, 60, 50],
|
||||
stroke: 2.8,
|
||||
cubicScale: 1.65,
|
||||
schlegelScale: 0.75, schlegelOriginX: 0.20,
|
||||
e8Count: 2, e8Scale: 0.28, e8OriginRadius: 0.52,
|
||||
fields: {
|
||||
cubic: F(0.92, 0.04, 0.55, 0.42, 0.82),
|
||||
schlegel: F(0.88, 0.94, 0.45, 0.40, 0.66),
|
||||
e8: F(0.96, 0.06, 0.65, 0.42, 0.92),
|
||||
links: F(0.90, 0.04, 0.85, 0.38, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_pale-sky-ivory',
|
||||
label: 'Pale sky · ivory · huge Schlegel tesseract',
|
||||
overrides: {
|
||||
paperOverride: paper([232, 222, 200]),
|
||||
vignOverride: [60, 50, 40],
|
||||
featureOverride: DARK_FEATURE,
|
||||
stroke: 2.4,
|
||||
cubicScale: 0.70,
|
||||
schlegelScale: 1.95, // massive — bleeds significantly
|
||||
e8Count: 3, e8Scale: 0.20, e8OriginRadius: 0.60,
|
||||
fields: {
|
||||
cubic: F(0.58, 0.66, 0.55, 0.30, 0.80), // blue → violet
|
||||
schlegel: F(0.62, 0.72, 0.55, 0.32, 0.66), // indigo → violet
|
||||
e8: F(0.55, 0.70, 0.65, 0.30, 0.92),
|
||||
links: F(0.60, 0.80, 0.85, 0.32, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_mint-gold-pale',
|
||||
label: 'Mint & gold · pale-mint ground',
|
||||
overrides: {
|
||||
paperOverride: paper([210, 225, 208]),
|
||||
vignOverride: [30, 55, 35],
|
||||
featureOverride: [40, 70, 45],
|
||||
stroke: 2.6,
|
||||
cubicScale: 1.50,
|
||||
schlegelScale: 1.25,
|
||||
e8Count: 3, e8Scale: 0.26, e8OriginRadius: 0.48,
|
||||
fields: {
|
||||
cubic: F(0.40, 0.50, 0.55, 0.30, 0.82), // mint teal
|
||||
schlegel: F(0.10, 0.16, 0.60, 0.36, 0.66), // gold
|
||||
e8: F(0.13, 0.20, 0.80, 0.40, 0.92),
|
||||
links: F(0.08, 0.14, 0.85, 0.40, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_bone-radial-gradient',
|
||||
label: 'Bone china · radial gradient (cool centre → warm edges)',
|
||||
overrides: {
|
||||
paperOverride: paper([234, 230, 222]),
|
||||
vignOverride: [70, 60, 50],
|
||||
featureOverride: DARK_FEATURE,
|
||||
stroke: 2.6, gradientMode: 'radial',
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.06, 0.62, 0.36, 0.82), // cyan centre → orange edges
|
||||
schlegel: F(0.58, 0.04, 0.50, 0.34, 0.70),
|
||||
e8: F(0.55, 0.05, 0.72, 0.40, 0.92),
|
||||
links: F(0.55, 0.05, 0.85, 0.40, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_pale-mauve-violet',
|
||||
label: 'Pale mauve fog · violet → pink gradients · thick',
|
||||
overrides: {
|
||||
paperOverride: paper([222, 205, 224]),
|
||||
vignOverride: [55, 35, 60],
|
||||
featureOverride: [75, 50, 90],
|
||||
stroke: 3.0,
|
||||
cubicScale: 1.85, // bleeds heavily
|
||||
schlegelScale: 0.90,
|
||||
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.50,
|
||||
fields: {
|
||||
cubic: F(0.74, 0.92, 0.55, 0.34, 0.84),
|
||||
schlegel: F(0.78, 0.86, 0.50, 0.32, 0.68),
|
||||
e8: F(0.82, 0.96, 0.65, 0.38, 0.92),
|
||||
links: F(0.78, 0.95, 0.85, 0.36, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_faded-blueprint',
|
||||
label: 'Faded blueprint · pale cyan paper · huge Schlegel',
|
||||
overrides: {
|
||||
paperOverride: paper([186, 214, 228]),
|
||||
vignOverride: [40, 55, 70],
|
||||
featureOverride: [30, 50, 75],
|
||||
stroke: 2.8,
|
||||
cubicScale: 0.80,
|
||||
schlegelScale: 1.90,
|
||||
e8Count: 3, e8Scale: 0.22, e8OriginRadius: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.60, 0.66, 0.60, 0.22, 0.86), // dark blue → navy
|
||||
schlegel: F(0.58, 0.62, 0.55, 0.20, 0.66),
|
||||
e8: F(0.62, 0.72, 0.70, 0.28, 0.92),
|
||||
links: F(0.58, 0.68, 0.85, 0.28, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_linen-sepia-large',
|
||||
label: 'Linen · warm sepia gradients · everything LARGE · thickest strokes',
|
||||
overrides: {
|
||||
paperOverride: paper([226, 210, 178]),
|
||||
vignOverride: [80, 55, 30],
|
||||
featureOverride: [85, 55, 30],
|
||||
stroke: 3.4, // chunkiest of the set
|
||||
cubicScale: 1.65, schlegelScale: 1.55,
|
||||
e8Count: 3, e8Scale: 0.28, e8OriginRadius: 0.50,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.12, 0.55, 0.30, 0.86),
|
||||
schlegel: F(0.10, 0.03, 0.45, 0.28, 0.70),
|
||||
e8: F(0.08, 0.16, 0.70, 0.36, 0.92),
|
||||
links: F(0.02, 0.12, 0.85, 0.30, 0.96),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_pearl-pastel-spectrum',
|
||||
label: 'Pearl · pastel rainbow (per-field hue families)',
|
||||
overrides: {
|
||||
paperOverride: paper([240, 235, 230]),
|
||||
vignOverride: [70, 65, 60],
|
||||
featureOverride: [80, 70, 60],
|
||||
stroke: 2.8,
|
||||
cubicScale: 1.50, schlegelScale: 1.40,
|
||||
e8Count: 3, e8Scale: 0.24, e8OriginRadius: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.70, 0.50, 0.42, 0.80), // cyan → violet pastel
|
||||
schlegel: F(0.08, 0.18, 0.45, 0.42, 0.62), // gold → yellow pastel
|
||||
e8: F(0.86, 0.04, 0.55, 0.42, 0.86), // pink → red pastel
|
||||
links: F(0.38, 0.55, 0.70, 0.40, 0.94), // green → cyan pastel
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name} · ${v.label}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
385
tools/qft-variations-perturb.mjs
Normal file
385
tools/qft-variations-perturb.mjs
Normal file
@@ -0,0 +1,385 @@
|
||||
/* ============================================================
|
||||
qft-variations-perturb.mjs — sketch 08.
|
||||
New mechanics — fields perturbed BY their own physics:
|
||||
|
||||
WAVEPACKETS — Gaussian local perturbation of the cubic
|
||||
(and schlegel) lattice; vertices push radially outward
|
||||
under a bell-curve falloff. The "particle" is now a
|
||||
feature OF the field, not a separate object placed on it.
|
||||
|
||||
RIPPLES — concentric expanding wavefronts from a source
|
||||
point. Each ring a many-segmented polyline; renderer
|
||||
applies propagator decoration to each chord.
|
||||
|
||||
Plus DENSER cubic (cubicN=2 → 125 vertices / ~300 edges) so
|
||||
more grid lines show the wavepacket distortion clearly.
|
||||
Output → output/qft/sketch08/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch08';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity, stroke) => {
|
||||
const f = { hueStart, hueEnd, saturation, lightness, opacity };
|
||||
if (stroke != null) f.stroke = stroke;
|
||||
return f;
|
||||
};
|
||||
const paper = (flat, glowInDelta = [16, 14, 12], glowOutDelta = [-22, -20, -18]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
|
||||
// Wavepacket helper: pos + amp + sigma
|
||||
const W = (x, y, amplitude, sigma) => ({ x, y, amplitude, sigma });
|
||||
// Ripple helper: pos + ring count + r0 + dR + optional propagator
|
||||
const R = (x, y, count = 6, r0 = 0.06, dR = 0.09, propagator = 'photon') =>
|
||||
({ x, y, count, r0, dR, propagator });
|
||||
|
||||
const BASE = {
|
||||
cubicN: 2, // DENSER cubic — more grid lines so wavepacket bulges read
|
||||
photonCyclesPerUnit: 14,
|
||||
segmentsPerEdge: 8, // fewer segments per edge — denser mesh + many circles
|
||||
linkCount: 8,
|
||||
e8Style: 'nautilus',
|
||||
nautilusTurns: 2.4, nautilusPerTurn: 14, nautilusGrowth: 0.22,
|
||||
};
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_single-wavepacket-bulge',
|
||||
label: 'Single wavepacket · lattice bulges around a centred particle',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([198, 198, 215]),
|
||||
vignOverride: [60, 55, 75], featureOverride: [40, 40, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.45,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
wavepackets: [W(0, 0, 0.085, 0.16)], // single positive bulge at centre
|
||||
e8Origins: [], linkCount: 6,
|
||||
fields: {
|
||||
cubic: F(0.60, 0.70, 0.50, 0.40, 0.60, 1.1),
|
||||
schlegel: F(0.62, 0.72, 0.55, 0.35, 0.78, 2.0),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.05, 0.12, 0.85, 0.50, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_two-wavepackets-interference',
|
||||
label: 'Two wavepackets · interference bulges between them',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 175, 195]),
|
||||
vignOverride: [55, 50, 70], featureOverride: [40, 40, 55],
|
||||
cubicScale: 1.60, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.55,
|
||||
wavepackets: [W(-0.32, 0, 0.075, 0.15), W(0.32, 0, 0.075, 0.15)],
|
||||
e8Origins: [], linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.68, 0.50, 0.40, 0.62, 1.1),
|
||||
schlegel: F(0.60, 0.74, 0.55, 0.35, 0.75, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.10, 0.04, 0.90, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_wavepacket-dimple',
|
||||
label: 'Wavepacket dimple · inward pull (negative amplitude)',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 160]),
|
||||
vignOverride: [60, 55, 45], featureOverride: [50, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.38, schlegelRot3D: 0.50,
|
||||
wavepackets: [W(0, 0, -0.075, 0.18)], // negative = pull vertices INWARD
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.32 }],
|
||||
linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.05, 0.13, 0.55, 0.38, 0.60, 1.1),
|
||||
schlegel: F(0.06, 0.14, 0.55, 0.35, 0.72, 1.8),
|
||||
e8: F(0.08, 0.18, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.50, 0.10, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_ripples-single-source',
|
||||
label: 'Single ripple source · concentric wavefronts expanding from origin',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 190]),
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.25,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
ripples: [R(0, 0, 7, 0.06, 0.10)],
|
||||
e8Origins: [], linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.62, 0.40, 0.42, 0.45, 0.9),
|
||||
schlegel: F(0.55, 0.68, 0.45, 0.38, 0.65, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.08, 0.18, 0.85, 0.55, 0.90, 2.4), // hot amber rings
|
||||
links: F(0.05, 0.13, 0.90, 0.55, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_two-ripple-sources-interfering',
|
||||
label: 'Two ripple sources interfering · double-slit feel',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 190]),
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.25,
|
||||
ripples: [R(-0.30, 0, 6, 0.05, 0.09), R(0.30, 0, 6, 0.05, 0.09)],
|
||||
e8Origins: [], linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.62, 0.40, 0.42, 0.45, 0.9),
|
||||
schlegel: F(0.55, 0.68, 0.45, 0.38, 0.60, 1.4),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.50, 0.62, 0.85, 0.50, 0.88, 2.4), // cyan rings
|
||||
links: F(0.05, 0.13, 0.90, 0.55, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_schrodinger-atom',
|
||||
label: 'Schrödinger atom · wavepacket + ripples at the SAME centre',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 175, 165]),
|
||||
vignOverride: [60, 55, 45], featureOverride: [55, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.38, schlegelRot3D: 0.50,
|
||||
wavepackets: [W(0, 0, 0.080, 0.18)],
|
||||
ripples: [R(0, 0, 5, 0.18, 0.12)], // ripples start at larger r0 (outside the wavepacket)
|
||||
e8Origins: [], linkCount: 10,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.14, 0.55, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.08, 0.18, 0.60, 0.36, 0.75, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.10, 0.04, 0.95, 0.55, 0.92, 2.6),
|
||||
links: F(0.95, 0.10, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_dense-cubic-with-wavepacket',
|
||||
label: 'Dense cubic + wavepacket · more grid lines show the distortion',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 180, 200]),
|
||||
vignOverride: [50, 50, 70], featureOverride: [40, 40, 55],
|
||||
cubicN: 2,
|
||||
cubicScale: 1.50, schlegelScale: 0.95,
|
||||
wavepackets: [W(0.20, -0.10, 0.090, 0.18)],
|
||||
e8Origins: [], linkCount: 7,
|
||||
fields: {
|
||||
cubic: F(0.50, 0.72, 0.55, 0.42, 0.50, 0.8), // dense + thin
|
||||
schlegel: F(0.60, 0.78, 0.50, 0.38, 0.60, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.06, 0.14, 0.90, 0.55, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_dense-cubic-with-ripples',
|
||||
label: 'Dense cubic backdrop · ripples expanding through it',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([195, 180, 165]),
|
||||
vignOverride: [70, 55, 40], featureOverride: [55, 45, 30],
|
||||
cubicN: 2,
|
||||
cubicScale: 1.50, schlegelScale: 0.95,
|
||||
ripples: [R(0, 0, 8, 0.07, 0.085)],
|
||||
e8Origins: [], linkCount: 8,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.16, 0.50, 0.40, 0.48, 0.8),
|
||||
schlegel: F(0.06, 0.14, 0.45, 0.38, 0.55, 1.4),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.06, 0.18, 0.95, 0.50, 0.92, 2.6),
|
||||
links: F(0.95, 0.10, 0.92, 0.55, 0.92, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_multi-particles-with-ripples-and-nautilus',
|
||||
label: 'Multiple wavepackets + ripples + nautilus chain · fully tangled',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 175]),
|
||||
vignOverride: [55, 50, 60], featureOverride: [45, 40, 50],
|
||||
cubicScale: 1.55, schlegelScale: 1.50,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
wavepackets: [W(-0.30, -0.30, 0.060, 0.14), W(0.30, 0.30, 0.060, 0.14)],
|
||||
ripples: [R(-0.30, -0.30, 4, 0.08, 0.08), R(0.30, 0.30, 4, 0.08, 0.08)],
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.35 }],
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.85, 0.50, 0.40, 0.52, 0.9),
|
||||
schlegel: F(0.60, 0.85, 0.55, 0.36, 0.72, 1.6),
|
||||
e8: F(0.05, 0.15, 0.85, 0.55, 0.90, 2.0),
|
||||
ripple: F(0.50, 0.80, 0.90, 0.50, 0.90, 2.2),
|
||||
links: F(0.95, 0.08, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_ripple-field-dominant',
|
||||
label: 'Ripple field dominant · five concentric expansions across the canvas',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([165, 165, 180]),
|
||||
vignOverride: [50, 50, 60], featureOverride: [40, 40, 55],
|
||||
cubicScale: 1.45, schlegelScale: 0,
|
||||
ripples: [
|
||||
R(-0.45, -0.45, 4, 0.05, 0.08),
|
||||
R( 0.45, -0.45, 4, 0.05, 0.08),
|
||||
R(-0.45, 0.45, 4, 0.05, 0.08),
|
||||
R( 0.45, 0.45, 4, 0.05, 0.08),
|
||||
R( 0.00, 0.00, 6, 0.06, 0.10),
|
||||
],
|
||||
e8Origins: [], linkCount: 10,
|
||||
fields: {
|
||||
cubic: F(0.50, 0.62, 0.40, 0.42, 0.40, 0.8),
|
||||
schlegel: F(0, 0, 0, 0.5, 0),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.55, 0.85, 0.85, 0.50, 0.85, 2.0), // cool spectrum rings
|
||||
links: F(0.50, 0.85, 0.95, 0.55, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '11_wavepacket-at-edge-cubic-bleed',
|
||||
label: 'Wavepacket near edge · cubic bleeding · particle entering/leaving frame',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 175, 155]),
|
||||
vignOverride: [70, 55, 35], featureOverride: [60, 45, 25],
|
||||
cubicScale: 1.80, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.55,
|
||||
wavepackets: [W(0.55, -0.25, 0.100, 0.20)],
|
||||
ripples: [R(0.55, -0.25, 5, 0.05, 0.10)],
|
||||
e8Origins: [], linkCount: 9,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.14, 0.55, 0.38, 0.55, 1.0),
|
||||
schlegel: F(0.04, 0.13, 0.60, 0.34, 0.78, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.10, 0.04, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.50, 0.10, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '12_asymmetric-perturbed-field',
|
||||
label: 'Asymmetric · wavepacket off-centre · everything biased',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 195]),
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.70, cubicOriginX: -0.10,
|
||||
schlegelScale: 1.75, schlegelOriginX: -0.20,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.40,
|
||||
wavepackets: [W(-0.30, -0.20, 0.075, 0.16)],
|
||||
ripples: [R(0.35, 0.30, 5, 0.05, 0.10)],
|
||||
e8Origins: [{ x: 0.20, y: 0.45, scale: 0.32 }],
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.68, 0.45, 0.40, 0.50, 1.0),
|
||||
schlegel: F(0.55, 0.70, 0.55, 0.36, 0.72, 1.8),
|
||||
e8: F(0.05, 0.16, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0.50, 0.10, 0.95, 0.55, 0.90, 2.4),
|
||||
links: F(0.95, 0.10, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '13_diatomic-two-particles-linked',
|
||||
label: 'Diatomic · two wavepackets + ripples · molecular feel',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 175, 175]),
|
||||
vignOverride: [60, 50, 55], featureOverride: [45, 40, 45],
|
||||
cubicScale: 1.60, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.55,
|
||||
wavepackets: [W(-0.25, 0, 0.075, 0.15), W(0.25, 0, 0.075, 0.15)],
|
||||
ripples: [R(-0.25, 0, 4, 0.05, 0.08), R(0.25, 0, 4, 0.05, 0.08)],
|
||||
e8Origins: [],
|
||||
linkCount: 14, // dense bond-like links
|
||||
fields: {
|
||||
cubic: F(0.85, 0.05, 0.50, 0.42, 0.52, 1.0),
|
||||
schlegel: F(0.88, 0.05, 0.55, 0.38, 0.72, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.92, 0.06, 0.90, 0.50, 0.90, 2.2),
|
||||
links: F(0.05, 0.16, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '14_field-cascade',
|
||||
label: 'Field cascade · ripples at varied scales · ladder of disturbances',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 165, 145]),
|
||||
vignOverride: [65, 50, 30], featureOverride: [55, 45, 30],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
ripples: [
|
||||
R(-0.50, 0.35, 3, 0.04, 0.05), // small tight ripples
|
||||
R(-0.10, 0.05, 5, 0.06, 0.08), // medium
|
||||
R( 0.40, -0.30, 7, 0.08, 0.12), // large widely spaced
|
||||
],
|
||||
e8Origins: [{ x: 0.40, y: 0.35, scale: 0.28 }],
|
||||
linkCount: 11,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.14, 0.50, 0.40, 0.50, 1.0),
|
||||
schlegel: F(0.05, 0.13, 0.55, 0.36, 0.70, 1.6),
|
||||
e8: F(0.10, 0.18, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0.10, 0.04, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.95, 0.06, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '15_quiet-single-ripple',
|
||||
label: 'Quiet counter-example · single small ripple · contemplative',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([190, 185, 178]),
|
||||
vignOverride: [55, 50, 45], featureOverride: [50, 45, 40],
|
||||
cubicScale: 1.40, schlegelScale: 1.20,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
ripples: [R(0, 0, 4, 0.08, 0.10)],
|
||||
e8Origins: [], linkCount: 4, // few links
|
||||
fields: {
|
||||
cubic: F(0.60, 0.68, 0.30, 0.42, 0.38, 0.8),
|
||||
schlegel: F(0.62, 0.70, 0.40, 0.40, 0.55, 1.2),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.08, 0.14, 0.70, 0.50, 0.82, 1.8),
|
||||
links: F(0.06, 0.14, 0.75, 0.50, 0.80, 1.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
148
tools/qft-variations-positions.mjs
Normal file
148
tools/qft-variations-positions.mjs
Normal file
@@ -0,0 +1,148 @@
|
||||
/* ============================================================
|
||||
qft-variations-positions.mjs — sketch 03.
|
||||
Hold the palette CONSTANT (per-field monochrome — each field
|
||||
one clear hue so the eye can track its position) and vary
|
||||
only origin / scale per field. Some fields deliberately
|
||||
extend past the canvas edge (scale > 1).
|
||||
Output → output/qft/sketch03/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch03';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
|
||||
({ hueStart, hueEnd, saturation, lightness, opacity });
|
||||
|
||||
// HELD CONSTANT: per-field monochrome palette so each field's position is legible
|
||||
// cyan cubic · magenta Schlegel · amber E8 · green cross-field links
|
||||
const COLORS = {
|
||||
cubic: F(0.55, 0.55, 0.55, 0.58, 0.72),
|
||||
schlegel: F(0.88, 0.88, 0.55, 0.55, 0.68),
|
||||
e8: F(0.12, 0.12, 0.75, 0.62, 0.92),
|
||||
links: F(0.34, 0.34, 0.80, 0.55, 0.95),
|
||||
};
|
||||
const SUBSTRATE = 'vintage';
|
||||
const BASE_OVERRIDES = { substrate: SUBSTRATE, gradientMode: 'along-edge', fields: COLORS };
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_centered-reference',
|
||||
label: 'Reference · everything centred at default scale',
|
||||
overrides: {}, // no position/scale overrides — defaults
|
||||
},
|
||||
{
|
||||
name: '02_cubic-left-schlegel-right',
|
||||
label: 'Cubic to the left, Schlegel to the right',
|
||||
overrides: {
|
||||
cubicOriginX: -0.45, cubicOriginY: 0,
|
||||
schlegelOriginX: 0.40, schlegelOriginY: 0,
|
||||
e8Count: 3, e8OriginRadius: 0.30,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_huge-cubic-bleed',
|
||||
label: 'Cubic blown up beyond the frame · others normal',
|
||||
overrides: {
|
||||
cubicScale: 1.85,
|
||||
schlegelScale: 0.65,
|
||||
e8Count: 3, e8Scale: 0.14, e8OriginRadius: 0.55,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_huge-schlegel-bleed',
|
||||
label: 'Schlegel dominating · cube-in-cube extends past edges',
|
||||
overrides: {
|
||||
cubicScale: 0.45,
|
||||
schlegelScale: 1.85,
|
||||
e8Count: 2, e8Scale: 0.14, e8OriginRadius: 0.30,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_tiny-lots-of-paper',
|
||||
label: 'Tiny lattices, lots of paper — a small island',
|
||||
overrides: {
|
||||
cubicScale: 0.42,
|
||||
schlegelScale: 0.32,
|
||||
e8Count: 2, e8Scale: 0.09, e8OriginRadius: 0.18,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_e8-cluster-lower-right',
|
||||
label: 'A single large E8 cluster in the lower-right',
|
||||
overrides: {
|
||||
cubicScale: 0.85, cubicOriginX: -0.25, cubicOriginY: -0.20,
|
||||
schlegelScale: 0.70, schlegelOriginX: -0.30, schlegelOriginY: -0.25,
|
||||
e8Origins: [{ x: 0.45, y: 0.40, scale: 0.42 }],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_e8-quartet-at-corners',
|
||||
label: 'Four E8 clusters near the corners',
|
||||
overrides: {
|
||||
cubicScale: 0.85,
|
||||
schlegelScale: 0.70,
|
||||
e8Origins: [
|
||||
{ x: -0.65, y: -0.65, scale: 0.20 },
|
||||
{ x: 0.65, y: -0.65, scale: 0.20 },
|
||||
{ x: -0.65, y: 0.65, scale: 0.20 },
|
||||
{ x: 0.65, y: 0.65, scale: 0.20 },
|
||||
],
|
||||
linkCount: 12,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_composition-shifted-upper-left',
|
||||
label: 'Whole composition pushed to upper-left · negative space lower-right',
|
||||
overrides: {
|
||||
compositionOffsetX: -0.32, compositionOffsetY: -0.32,
|
||||
cubicScale: 0.85, schlegelScale: 0.78,
|
||||
e8Count: 3, e8Scale: 0.16, e8OriginRadius: 0.55,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_vertical-stack',
|
||||
label: 'Vertical stack · cubic top, Schlegel middle, E8 bottom',
|
||||
overrides: {
|
||||
cubicScale: 0.55, cubicOriginX: 0, cubicOriginY: -0.45,
|
||||
schlegelScale: 0.55, schlegelOriginX: 0, schlegelOriginY: 0,
|
||||
e8Origins: [{ x: -0.25, y: 0.50, scale: 0.18 }, { x: 0.25, y: 0.50, scale: 0.18 }],
|
||||
linkCount: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_triptych-corners',
|
||||
label: 'Triptych · each field in its own corner',
|
||||
overrides: {
|
||||
cubicScale: 0.55, cubicOriginX: -0.40, cubicOriginY: -0.40,
|
||||
schlegelScale: 0.55, schlegelOriginX: 0.40, schlegelOriginY: -0.40,
|
||||
e8Origins: [{ x: 0, y: 0.45, scale: 0.25 }],
|
||||
linkCount: 12,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '11_inverse-scales',
|
||||
label: 'Bonus · inverted scales (tiny cubic, giant Schlegel)',
|
||||
overrides: {
|
||||
cubicScale: 0.30,
|
||||
schlegelScale: 1.70,
|
||||
e8Count: 3, e8Scale: 0.20, e8OriginRadius: 0.65,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...BASE_OVERRIDES, ...v.overrides };
|
||||
params.fields = COLORS;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name} · ${v.label}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
387
tools/qft-variations-tangle.mjs
Normal file
387
tools/qft-variations-tangle.mjs
Normal file
@@ -0,0 +1,387 @@
|
||||
/* ============================================================
|
||||
qft-variations-tangle.mjs — sketch 07.
|
||||
Pursuing "chaotic interconnectedness" via:
|
||||
- Cubic mesh FILLS the page (often bleeding past edges)
|
||||
- Schlegel hypercube also taking much space
|
||||
- Many bright Feynman cross-field links (8–14 per plate)
|
||||
- NAUTILUS rosettes (open spirals with chambers growing
|
||||
with radius) replacing closed concentric rings
|
||||
- Per-field stroke weights for hierarchical emphasis
|
||||
- Mid-tone substrates so brightness can work in BOTH
|
||||
directions (lighter than bg AND darker)
|
||||
Output → output/qft/sketch07/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch07';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
// Field config: hueStart, hueEnd, sat, light, opacity. Optional `stroke` per-field.
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity, stroke) => {
|
||||
const f = { hueStart, hueEnd, saturation, lightness, opacity };
|
||||
if (stroke != null) f.stroke = stroke;
|
||||
return f;
|
||||
};
|
||||
const paper = (flat, glowInDelta = [16, 14, 12], glowOutDelta = [-22, -20, -18]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
|
||||
// Shared base: every plate has cubic+schlegel large, many links, nautilus rosettes
|
||||
const BASE = {
|
||||
cubicN: 1, // N=2 is too busy when cubic fills the page
|
||||
photonCyclesPerUnit: 14,
|
||||
segmentsPerEdge: 10,
|
||||
linkCount: 11,
|
||||
// nautilus defaults (used unless overridden)
|
||||
e8Style: 'nautilus',
|
||||
nautilusTurns: 2.6, nautilusPerTurn: 14, nautilusGrowth: 0.22,
|
||||
};
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_E3-evolved-nautilus',
|
||||
label: 'E3 evolved · lavender-grey · twin nautilus + counter-rotated cubic',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([198, 198, 215]),
|
||||
vignOverride: [60, 55, 75], featureOverride: [40, 40, 60],
|
||||
cubicScale: 1.55, cubicRot: 0.80,
|
||||
schlegelScale: 1.85, schlegelInnerR: 0.55, schlegelRot3D: -0.30,
|
||||
schlegelOriginX: -0.10, schlegelOriginY: 0.10,
|
||||
e8Origins: [{ x: 0.42, y: -0.42, scale: 0.55 },
|
||||
{ x: -0.42, y: 0.42, scale: 0.55 }],
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.62, 0.70, 0.40, 0.50, 0.50, 1.1),
|
||||
schlegel: F(0.62, 0.72, 0.60, 0.32, 0.82, 2.6), // schlegel thick
|
||||
e8: F(0.65, 0.78, 0.65, 0.48, 0.88, 2.0),
|
||||
links: F(0.05, 0.12, 0.85, 0.50, 0.92, 2.4), // bright warm links
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_single-huge-nautilus',
|
||||
label: 'Single huge nautilus spiraling out · dense link web',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 185]), // dusty lavender-grey
|
||||
vignOverride: [55, 50, 70], featureOverride: [40, 40, 55],
|
||||
cubicScale: 1.50, schlegelScale: 1.20,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.95 }], // ONE huge spiral
|
||||
nautilusTurns: 3.2, nautilusGrowth: 0.24,
|
||||
linkCount: 14,
|
||||
fields: {
|
||||
cubic: F(0.58, 0.68, 0.40, 0.42, 0.45, 1.0),
|
||||
schlegel: F(0.06, 0.13, 0.50, 0.40, 0.70, 1.8),
|
||||
e8: F(0.08, 0.15, 0.85, 0.52, 0.92, 2.6), // saturated warm spiral
|
||||
links: F(0.05, 0.15, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_triangular-three-nautilus',
|
||||
label: 'Three nautilus in a triangle · many crisscrossing links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 175, 160]), // warm tan-grey
|
||||
vignOverride: [70, 55, 35], featureOverride: [50, 40, 25],
|
||||
cubicScale: 1.60, schlegelScale: 1.30,
|
||||
schlegelRot3D: 0.85,
|
||||
e8Origins: [
|
||||
{ x: 0.00, y: -0.40, scale: 0.40 },
|
||||
{ x: -0.45, y: 0.35, scale: 0.40 },
|
||||
{ x: 0.45, y: 0.35, scale: 0.40 },
|
||||
],
|
||||
linkCount: 14,
|
||||
fields: {
|
||||
cubic: F(0.04, 0.12, 0.45, 0.38, 0.50, 1.0),
|
||||
schlegel: F(0.06, 0.14, 0.55, 0.32, 0.72, 1.6),
|
||||
e8: F(0.05, 0.18, 0.80, 0.48, 0.90, 2.2),
|
||||
links: F(0.95, 0.10, 0.95, 0.50, 0.95, 2.4), // hot pink → orange links
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_asymmetric-chaos',
|
||||
label: 'Asymmetric · nautilus low-right · schlegel bleeding upper-left',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 165, 175]), // cool grey-mauve
|
||||
vignOverride: [60, 55, 70], featureOverride: [40, 40, 55],
|
||||
cubicScale: 1.70, cubicOriginX: -0.10,
|
||||
schlegelScale: 2.05, schlegelOriginX: -0.30, schlegelOriginY: -0.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.65,
|
||||
e8Origins: [{ x: 0.45, y: 0.40, scale: 0.55 },
|
||||
{ x: 0.20, y: 0.55, scale: 0.30 }],
|
||||
linkCount: 13,
|
||||
fields: {
|
||||
cubic: F(0.72, 0.85, 0.45, 0.40, 0.48, 0.9),
|
||||
schlegel: F(0.74, 0.92, 0.55, 0.32, 0.78, 2.4),
|
||||
e8: F(0.86, 0.98, 0.85, 0.50, 0.90, 2.2),
|
||||
links: F(0.50, 0.12, 0.95, 0.55, 0.95, 2.6), // teal→amber crosslinks
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_warm-tangle-tan',
|
||||
label: 'Warm tan-grey · dense cubic · many small nautilus · many links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([188, 168, 145]),
|
||||
vignOverride: [80, 55, 30], featureOverride: [60, 45, 25],
|
||||
cubicScale: 1.60, schlegelScale: 0.95,
|
||||
e8Origins: [
|
||||
{ x: -0.50, y: -0.45, scale: 0.30 },
|
||||
{ x: 0.45, y: -0.50, scale: 0.30 },
|
||||
{ x: -0.40, y: 0.45, scale: 0.30 },
|
||||
{ x: 0.50, y: 0.40, scale: 0.30 },
|
||||
{ x: 0.00, y: 0.00, scale: 0.30 }, // 5 small nautilus
|
||||
],
|
||||
nautilusTurns: 2.0,
|
||||
linkCount: 14,
|
||||
fields: {
|
||||
cubic: F(0.04, 0.12, 0.55, 0.35, 0.55, 1.0),
|
||||
schlegel: F(0.04, 0.10, 0.50, 0.32, 0.68, 1.4),
|
||||
e8: F(0.06, 0.14, 0.85, 0.52, 0.92, 2.2),
|
||||
links: F(0.50, 0.10, 0.90, 0.55, 0.92, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_sage-with-bright-lighter',
|
||||
label: 'Sage midtone · bright LIGHTER nautilus glowing above',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([155, 165, 145]), // sage midtone
|
||||
vignOverride: [55, 70, 50], featureOverride: [235, 240, 225],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.45, schlegelRot3D: 0.30,
|
||||
e8Origins: [{ x: -0.30, y: -0.10, scale: 0.55 },
|
||||
{ x: 0.30, y: 0.10, scale: 0.55 }],
|
||||
linkCount: 11,
|
||||
fields: {
|
||||
cubic: F(0.42, 0.50, 0.40, 0.38, 0.55, 1.1),
|
||||
schlegel: F(0.42, 0.48, 0.45, 0.32, 0.72, 1.8),
|
||||
e8: F(0.38, 0.50, 0.30, 0.90, 0.88, 2.2), // pale-mint lighter than sage
|
||||
links: F(0.38, 0.50, 0.45, 0.92, 0.92, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_deep-teal-luminous',
|
||||
label: 'Deep teal · luminous nautilus + cubic glowing brighter',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([60, 95, 100]), // deep teal
|
||||
vignOverride: [25, 45, 50], featureOverride: [195, 220, 220],
|
||||
cubicScale: 1.55, schlegelScale: 1.35,
|
||||
schlegelInnerR: 0.30, schlegelRot3D: 0.45,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.80 }],
|
||||
linkCount: 13,
|
||||
fields: {
|
||||
cubic: F(0.50, 0.55, 0.35, 0.82, 0.62, 1.0), // pale cyan glowing
|
||||
schlegel: F(0.48, 0.55, 0.30, 0.80, 0.65, 1.8),
|
||||
e8: F(0.10, 0.20, 0.85, 0.65, 0.92, 2.4), // hot amber-gold spiral
|
||||
links: F(0.10, 0.04, 0.95, 0.65, 0.95, 2.6), // bright orange links
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_bone-thick-white-nautilus',
|
||||
label: 'Bone midtone · thick WHITE nautilus chain · dense links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 175, 160]),
|
||||
vignOverride: [60, 50, 35], featureOverride: [55, 45, 30],
|
||||
cubicScale: 1.50, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.45, schlegelRot3D: 0.55,
|
||||
e8Origins: [
|
||||
{ x: -0.50, y: 0, scale: 0.40 },
|
||||
{ x: 0.00, y: 0, scale: 0.40 },
|
||||
{ x: 0.50, y: 0, scale: 0.40 },
|
||||
],
|
||||
nautilusTurns: 2.4,
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.08, 0.14, 0.35, 0.42, 0.45, 1.0),
|
||||
schlegel: F(0.08, 0.14, 0.40, 0.38, 0.65, 1.6),
|
||||
e8: F(0.0, 0.0, 0, 0.96, 0.95, 3.0), // pure white THICK nautilus
|
||||
links: F(0.0, 0.0, 0, 0.96, 0.88, 2.6), // white connectors too
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_galaxies-all-same-direction',
|
||||
label: 'Spiral galaxies · all nautilus winding the same way',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 170, 195]), // dusty blue-violet
|
||||
vignOverride: [50, 50, 70], featureOverride: [40, 40, 60],
|
||||
cubicScale: 1.65, schlegelScale: 1.50,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.20,
|
||||
e8Origins: [
|
||||
{ x: -0.45, y: -0.45, scale: 0.32 },
|
||||
{ x: 0.45, y: -0.30, scale: 0.36 },
|
||||
{ x: -0.30, y: 0.45, scale: 0.36 },
|
||||
{ x: 0.50, y: 0.40, scale: 0.32 },
|
||||
],
|
||||
nautilusTurns: 3.0,
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.60, 0.70, 0.40, 0.42, 0.50, 1.0),
|
||||
schlegel: F(0.62, 0.72, 0.50, 0.38, 0.65, 1.4),
|
||||
e8: F(0.55, 0.80, 0.85, 0.55, 0.92, 2.4), // each nautilus its own hue
|
||||
links: F(0.10, 0.18, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_nested-nautilus-mandala',
|
||||
label: 'Nested nautilus at three scales · cubic backdrop',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 170, 175]), // dusky rose-grey
|
||||
vignOverride: [70, 50, 55], featureOverride: [55, 35, 40],
|
||||
cubicScale: 1.45, schlegelScale: 0.95,
|
||||
e8Origins: [
|
||||
{ x: 0, y: 0, scale: 0.95 },
|
||||
{ x: 0, y: 0, scale: 0.55 },
|
||||
{ x: 0, y: 0, scale: 0.25 },
|
||||
],
|
||||
nautilusTurns: 2.8,
|
||||
linkCount: 10,
|
||||
fields: {
|
||||
cubic: F(0.92, 0.05, 0.45, 0.42, 0.45, 0.9),
|
||||
schlegel: F(0.92, 0.05, 0.45, 0.40, 0.55, 1.4),
|
||||
e8: F(0.94, 0.06, 0.85, 0.50, 0.88, 2.0),
|
||||
links: F(0.85, 0.95, 0.90, 0.50, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '11_windblown-biased',
|
||||
label: 'Wind-blown · everything biased to the left · drift',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 165, 145]),
|
||||
vignOverride: [65, 50, 30], featureOverride: [55, 45, 30],
|
||||
cubicScale: 1.55, cubicOriginX: -0.30,
|
||||
schlegelScale: 1.60, schlegelOriginX: -0.25,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.55,
|
||||
compositionOffsetX: -0.10, // whole scene shifted left
|
||||
e8Origins: [
|
||||
{ x: -0.55, y: -0.25, scale: 0.42 },
|
||||
{ x: -0.20, y: 0.35, scale: 0.36 },
|
||||
],
|
||||
linkCount: 11,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.14, 0.50, 0.38, 0.50, 1.0),
|
||||
schlegel: F(0.04, 0.12, 0.55, 0.35, 0.72, 1.8),
|
||||
e8: F(0.08, 0.18, 0.85, 0.50, 0.92, 2.4),
|
||||
links: F(0.95, 0.10, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '12_linked-chain-across',
|
||||
label: 'Linked chain · nautilus across the diagonal, very bright links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 185]), // cool storm-grey
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.40,
|
||||
e8Origins: [
|
||||
{ x: -0.55, y: -0.40, scale: 0.32 },
|
||||
{ x: -0.18, y: -0.10, scale: 0.32 },
|
||||
{ x: 0.18, y: 0.10, scale: 0.32 },
|
||||
{ x: 0.55, y: 0.40, scale: 0.32 },
|
||||
],
|
||||
linkCount: 14,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.65, 0.40, 0.42, 0.50, 1.0),
|
||||
schlegel: F(0.56, 0.66, 0.50, 0.38, 0.70, 1.6),
|
||||
e8: F(0.08, 0.18, 0.85, 0.55, 0.92, 2.4), // amber nautilus
|
||||
links: F(0.06, 0.16, 0.95, 0.60, 0.98, 2.8), // brightest links of the set
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '13_spectral-radial-tangle',
|
||||
label: 'Spectral radial · everything cycling through the spectrum',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 165]),
|
||||
vignOverride: [60, 55, 50], featureOverride: [50, 45, 40],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.55, schlegelScale: 1.45,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.40,
|
||||
e8Origins: [{ x: -0.30, y: -0.30, scale: 0.40 },
|
||||
{ x: 0.30, y: 0.30, scale: 0.40 }],
|
||||
linkCount: 12,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.65, 0.42, 0.55, 1.0),
|
||||
schlegel: F(0.55, 0.05, 0.55, 0.38, 0.70, 1.6),
|
||||
e8: F(0.55, 0.05, 0.85, 0.50, 0.92, 2.2),
|
||||
links: F(0.55, 0.05, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '14_quiet-counterexample',
|
||||
label: 'Quiet counter-example · single nautilus, fewer links · contemplative',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([195, 190, 185]),
|
||||
vignOverride: [55, 50, 45], featureOverride: [55, 50, 45],
|
||||
cubicScale: 1.40, schlegelScale: 1.20,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.40,
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.65 }],
|
||||
linkCount: 5, // quiet
|
||||
fields: {
|
||||
cubic: F(0.60, 0.68, 0.30, 0.42, 0.40, 0.9),
|
||||
schlegel: F(0.62, 0.70, 0.40, 0.40, 0.60, 1.4),
|
||||
e8: F(0.06, 0.12, 0.65, 0.50, 0.85, 1.8),
|
||||
links: F(0.06, 0.12, 0.70, 0.50, 0.80, 1.8),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '15_heavy-weight-contrast',
|
||||
label: 'Weight contrast · thin cubic · THICK schlegel · medium nautilus',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 170, 175]),
|
||||
vignOverride: [55, 45, 50], featureOverride: [40, 35, 40],
|
||||
cubicScale: 1.65, schlegelScale: 1.55,
|
||||
schlegelInnerR: 0.32, schlegelRot3D: 0.60,
|
||||
e8Origins: [{ x: -0.30, y: 0.10, scale: 0.42 },
|
||||
{ x: 0.35, y: -0.15, scale: 0.42 }],
|
||||
linkCount: 11,
|
||||
fields: {
|
||||
cubic: F(0.85, 0.95, 0.40, 0.45, 0.45, 0.6), // very thin
|
||||
schlegel: F(0.05, 0.12, 0.55, 0.30, 0.85, 3.4), // very thick
|
||||
e8: F(0.05, 0.15, 0.85, 0.55, 0.92, 2.0), // medium
|
||||
links: F(0.50, 0.10, 0.95, 0.55, 0.95, 2.8), // thick links
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
466
tools/qft-variations-wild.mjs
Normal file
466
tools/qft-variations-wild.mjs
Normal file
@@ -0,0 +1,466 @@
|
||||
/* ============================================================
|
||||
qft-variations-wild.mjs — sketch 09 · running wild.
|
||||
|
||||
New mechanics this sketch:
|
||||
- VORTEX perturbations (swirling rotation around a centre)
|
||||
- STANDING WAVES (global plane-wave modulation; Chladni)
|
||||
- CURVED Feynman links (bezier-curved propagators)
|
||||
|
||||
Plus everything earlier: wavepackets, ripples, dense cubic,
|
||||
per-field weights, mid-tone substrates.
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch09';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity, stroke) => {
|
||||
const f = { hueStart, hueEnd, saturation, lightness, opacity };
|
||||
if (stroke != null) f.stroke = stroke;
|
||||
return f;
|
||||
};
|
||||
const paper = (flat, glowInDelta = [16, 14, 12], glowOutDelta = [-22, -20, -18]) => ({
|
||||
flat,
|
||||
glowIn: [flat[0] + glowInDelta[0], flat[1] + glowInDelta[1], flat[2] + glowInDelta[2]],
|
||||
glowOut: [flat[0] + glowOutDelta[0], flat[1] + glowOutDelta[1], flat[2] + glowOutDelta[2]],
|
||||
});
|
||||
|
||||
const W = (x, y, amplitude, sigma) => ({ x, y, amplitude, sigma });
|
||||
const VX = (x, y, strength, sigma) => ({ x, y, strength, sigma }); // vortex
|
||||
const SW = (kx, ky, amplitude, phase = 0) => ({ kx, ky, amplitude, phase });
|
||||
const R = (x, y, count = 6, r0 = 0.06, dR = 0.09, propagator = 'photon') =>
|
||||
({ x, y, count, r0, dR, propagator });
|
||||
|
||||
const BASE = {
|
||||
cubicN: 2,
|
||||
photonCyclesPerUnit: 14,
|
||||
segmentsPerEdge: 8,
|
||||
linkCount: 10,
|
||||
linkCurvature: 0.0, // overridden per-variation
|
||||
e8Style: 'nautilus',
|
||||
nautilusTurns: 2.4, nautilusPerTurn: 14, nautilusGrowth: 0.22,
|
||||
};
|
||||
|
||||
const variations = [
|
||||
// ─── VORTEX block ───────────────────────────────────────────────────────────
|
||||
{
|
||||
name: '01_single-vortex-cubic',
|
||||
label: 'Single vortex · cubic mesh swirls around a centred angular-momentum core',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 175, 195]),
|
||||
vignOverride: [55, 55, 70], featureOverride: [40, 40, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.45,
|
||||
vortices: [VX(0, 0, 1.20, 0.22)],
|
||||
e8Origins: [], linkCount: 6, linkCurvature: 0.25,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.68, 0.50, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.58, 0.72, 0.55, 0.36, 0.70, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.05, 0.13, 0.90, 0.55, 0.92, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_dipole-counter-vortices',
|
||||
label: 'Counter-rotating vortices · dipole · Kármán-street feel',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 175, 165]),
|
||||
vignOverride: [55, 55, 45], featureOverride: [45, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.35,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
vortices: [VX(-0.30, 0, 1.20, 0.18), VX(0.30, 0, -1.20, 0.18)],
|
||||
e8Origins: [], linkCount: 8, linkCurvature: 0.40,
|
||||
fields: {
|
||||
cubic: F(0.05, 0.18, 0.55, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.08, 0.18, 0.55, 0.36, 0.72, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.55, 0.08, 0.92, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_vortex-with-spinning-ripples',
|
||||
label: 'Vortex + ripples at same centre · spinning waves',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 175, 165]),
|
||||
vignOverride: [60, 55, 45], featureOverride: [50, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
vortices: [VX(0, 0, 0.85, 0.30)],
|
||||
ripples: [R(0, 0, 5, 0.10, 0.10)],
|
||||
e8Origins: [], linkCount: 8, linkCurvature: 0.35,
|
||||
fields: {
|
||||
cubic: F(0.08, 0.18, 0.55, 0.40, 0.50, 1.0),
|
||||
schlegel: F(0.06, 0.16, 0.55, 0.36, 0.70, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.05, 0.18, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.95, 0.08, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_vortex-particle-spin',
|
||||
label: 'Vortex + wavepacket at same centre · particle with spin',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 170, 190]),
|
||||
vignOverride: [50, 50, 70], featureOverride: [40, 40, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
vortices: [VX(0, 0, 0.95, 0.20)],
|
||||
wavepackets: [W(0, 0, 0.060, 0.16)],
|
||||
e8Origins: [], linkCount: 7, linkCurvature: 0.35,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.72, 0.55, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.58, 0.78, 0.60, 0.34, 0.78, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.05, 0.16, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ─── STANDING WAVE block ────────────────────────────────────────────────────
|
||||
{
|
||||
name: '05_horizontal-standing-wave',
|
||||
label: 'Horizontal standing wave · cubic ripples like a drum membrane',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 175, 195]),
|
||||
vignOverride: [55, 50, 70], featureOverride: [40, 40, 55],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
standingWaves: [SW(7.0, 0.0, 0.045)],
|
||||
e8Origins: [], linkCount: 7, linkCurvature: 0.20,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.62, 0.50, 0.42, 0.55, 1.0),
|
||||
schlegel: F(0.58, 0.68, 0.55, 0.38, 0.72, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.06, 0.16, 0.95, 0.55, 0.95, 2.2),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_chladni-interference',
|
||||
label: 'Two crossed standing waves · Chladni-plate interference',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 175, 165]),
|
||||
vignOverride: [55, 50, 45], featureOverride: [45, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
standingWaves: [SW(8.0, 1.0, 0.038), SW(1.0, 8.0, 0.038)],
|
||||
e8Origins: [], linkCount: 8, linkCurvature: 0.30,
|
||||
fields: {
|
||||
cubic: F(0.04, 0.16, 0.60, 0.38, 0.60, 1.0),
|
||||
schlegel: F(0.06, 0.18, 0.60, 0.34, 0.75, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.95, 0.06, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_standing-wave-plus-wavepacket',
|
||||
label: 'Standing wave background · wavepacket on top · oscillating quantum state',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 180, 165]), // sage
|
||||
vignOverride: [50, 65, 45], featureOverride: [40, 55, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
standingWaves: [SW(6.0, 2.0, 0.035)],
|
||||
wavepackets: [W(0.10, -0.10, 0.060, 0.18)],
|
||||
e8Origins: [], linkCount: 9, linkCurvature: 0.30,
|
||||
fields: {
|
||||
cubic: F(0.40, 0.50, 0.55, 0.38, 0.55, 1.0),
|
||||
schlegel: F(0.42, 0.52, 0.60, 0.34, 0.75, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.08, 0.16, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ─── CURVED LINKS block ─────────────────────────────────────────────────────
|
||||
{
|
||||
name: '08_heavily-curved-links',
|
||||
label: 'Heavily curved Feynman links · organic tangle',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 170, 175]),
|
||||
vignOverride: [55, 45, 50], featureOverride: [40, 35, 40],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.50,
|
||||
e8Origins: [{ x: -0.35, y: 0.30, scale: 0.32 },
|
||||
{ x: 0.35, y: -0.30, scale: 0.32 }],
|
||||
linkCount: 14, linkCurvature: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.85, 0.96, 0.50, 0.40, 0.50, 1.0),
|
||||
schlegel: F(0.88, 0.00, 0.55, 0.36, 0.70, 1.6),
|
||||
e8: F(0.06, 0.16, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.04, 0.14, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_curved-links-and-nautilus-chain',
|
||||
label: 'Curved-link cradle around a nautilus chain · synaptic',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 185]),
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
e8Origins: [
|
||||
{ x: -0.40, y: -0.30, scale: 0.32 },
|
||||
{ x: 0.00, y: 0.00, scale: 0.32 },
|
||||
{ x: 0.40, y: 0.30, scale: 0.32 },
|
||||
],
|
||||
linkCount: 14, linkCurvature: 0.50,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.68, 0.45, 0.40, 0.50, 1.0),
|
||||
schlegel: F(0.58, 0.70, 0.55, 0.36, 0.72, 1.6),
|
||||
e8: F(0.05, 0.18, 0.85, 0.55, 0.92, 2.2),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.06, 0.16, 0.95, 0.55, 0.95, 2.4),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ─── MULTI-MECHANIC plates (combining wildly) ───────────────────────────────
|
||||
{
|
||||
name: '10_full-turbulence',
|
||||
label: 'Full turbulence · vortex + standing wave + ripples + curved links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 175]),
|
||||
vignOverride: [55, 50, 60], featureOverride: [45, 40, 50],
|
||||
cubicScale: 1.60, schlegelScale: 1.45,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.55,
|
||||
vortices: [VX(-0.20, 0.20, 0.70, 0.30)],
|
||||
standingWaves: [SW(5.0, 3.0, 0.025)],
|
||||
ripples: [R(0.30, -0.20, 4, 0.08, 0.10)],
|
||||
e8Origins: [], linkCount: 12, linkCurvature: 0.45,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.85, 0.50, 0.40, 0.55, 0.9),
|
||||
schlegel: F(0.60, 0.88, 0.55, 0.36, 0.72, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.50, 0.80, 0.95, 0.55, 0.90, 2.2),
|
||||
links: F(0.95, 0.06, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '11_molecular-vibration',
|
||||
label: 'Molecular vibration · two wavepackets + standing wave + curved bonds',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([185, 175, 175]),
|
||||
vignOverride: [60, 50, 55], featureOverride: [45, 40, 45],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
wavepackets: [W(-0.30, 0, 0.075, 0.16), W(0.30, 0, 0.075, 0.16)],
|
||||
standingWaves: [SW(6.0, 0.0, 0.028)],
|
||||
e8Origins: [], linkCount: 14, linkCurvature: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.85, 0.00, 0.50, 0.42, 0.55, 1.0),
|
||||
schlegel: F(0.88, 0.05, 0.55, 0.38, 0.72, 1.6),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.05, 0.16, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '12_orbital-with-spin',
|
||||
label: 'Orbital with spin · vortex + ripples + nautilus, curved links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 165, 145]),
|
||||
vignOverride: [65, 50, 30], featureOverride: [55, 45, 30],
|
||||
cubicScale: 1.55, schlegelScale: 1.35,
|
||||
schlegelInnerR: 0.38, schlegelRot3D: 0.50,
|
||||
vortices: [VX(0, 0, 0.80, 0.30)],
|
||||
ripples: [R(0, 0, 5, 0.12, 0.12)],
|
||||
e8Origins: [{ x: 0, y: 0, scale: 0.60 }],
|
||||
linkCount: 11, linkCurvature: 0.40,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.14, 0.55, 0.38, 0.55, 1.0),
|
||||
schlegel: F(0.04, 0.13, 0.60, 0.34, 0.75, 1.8),
|
||||
e8: F(0.10, 0.18, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0.10, 0.04, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.50, 0.10, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '13_field-gradient-shear',
|
||||
label: 'Field gradient · a single SLOW standing wave deforming the whole canvas',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 175, 195]),
|
||||
vignOverride: [50, 55, 70], featureOverride: [40, 45, 60],
|
||||
cubicScale: 1.60, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.45,
|
||||
standingWaves: [SW(1.8, 0.0, 0.080)], // single low-frequency big amp = gradient-like shear
|
||||
e8Origins: [{ x: -0.40, y: 0, scale: 0.32 },
|
||||
{ x: 0.40, y: 0, scale: 0.32 }],
|
||||
linkCount: 10, linkCurvature: 0.40,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.68, 0.50, 0.42, 0.55, 1.0),
|
||||
schlegel: F(0.58, 0.72, 0.55, 0.36, 0.70, 1.8),
|
||||
e8: F(0.08, 0.16, 0.85, 0.55, 0.92, 2.0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.05, 0.16, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '14_multi-vortex-chaos',
|
||||
label: 'Multi-vortex chaos · 4 spinning centres + dense curved-link tangle',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 175, 165]),
|
||||
vignOverride: [55, 55, 45], featureOverride: [45, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.30,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.50,
|
||||
vortices: [
|
||||
VX(-0.30, -0.30, 0.85, 0.18),
|
||||
VX( 0.30, -0.30, -0.85, 0.18),
|
||||
VX(-0.30, 0.30, -0.85, 0.18),
|
||||
VX( 0.30, 0.30, 0.85, 0.18),
|
||||
],
|
||||
e8Origins: [], linkCount: 13, linkCurvature: 0.50,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.16, 0.55, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.04, 0.14, 0.55, 0.36, 0.72, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.95, 0.06, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '15_perturbation-cascade',
|
||||
label: 'Perturbation cascade · 3 wavepackets at different scales + ripples + curved links',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([180, 175, 165]),
|
||||
vignOverride: [60, 55, 45], featureOverride: [50, 45, 35],
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
wavepackets: [
|
||||
W(-0.45, 0.30, 0.040, 0.10),
|
||||
W(-0.05, -0.05, 0.075, 0.18),
|
||||
W( 0.40, -0.30, 0.060, 0.14),
|
||||
],
|
||||
ripples: [R(-0.45, 0.30, 3, 0.05, 0.06),
|
||||
R(-0.05, -0.05, 5, 0.07, 0.09),
|
||||
R(0.40, -0.30, 4, 0.06, 0.08)],
|
||||
e8Origins: [], linkCount: 12, linkCurvature: 0.40,
|
||||
fields: {
|
||||
cubic: F(0.06, 0.16, 0.55, 0.40, 0.55, 1.0),
|
||||
schlegel: F(0.04, 0.14, 0.55, 0.36, 0.72, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.10, 0.05, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.95, 0.08, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// ─── BOLD experiments ───────────────────────────────────────────────────────
|
||||
{
|
||||
name: '16_asymmetric-riot',
|
||||
label: 'Asymmetric riot · everything happening everywhere · one mind-storm plate',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([175, 170, 175]),
|
||||
vignOverride: [55, 50, 60], featureOverride: [45, 40, 50],
|
||||
cubicScale: 1.65, cubicOriginX: -0.05,
|
||||
schlegelScale: 1.55, schlegelOriginX: 0.10,
|
||||
schlegelInnerR: 0.42, schlegelRot3D: 0.60,
|
||||
vortices: [VX(-0.30, 0.20, 0.95, 0.20)],
|
||||
wavepackets: [W(0.25, -0.25, 0.075, 0.16)],
|
||||
ripples: [R(-0.30, 0.20, 4, 0.07, 0.08),
|
||||
R(0.25, -0.25, 5, 0.05, 0.08),
|
||||
R(0.0, 0.0, 3, 0.10, 0.10)],
|
||||
standingWaves: [SW(4.0, 1.5, 0.025)],
|
||||
e8Origins: [{ x: 0.45, y: 0.40, scale: 0.30 },
|
||||
{ x: -0.45, y: -0.40, scale: 0.30 }],
|
||||
linkCount: 14, linkCurvature: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.85, 0.55, 0.40, 0.55, 0.9),
|
||||
schlegel: F(0.60, 0.88, 0.55, 0.36, 0.75, 1.8),
|
||||
e8: F(0.05, 0.16, 0.85, 0.55, 0.92, 2.2),
|
||||
ripple: F(0.50, 0.85, 0.95, 0.55, 0.92, 2.2),
|
||||
links: F(0.95, 0.10, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '17_spectral-vortex-storm',
|
||||
label: 'Spectral vortex storm · radial gradient · full spectrum in every element',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([170, 170, 175]),
|
||||
vignOverride: [55, 50, 55], featureOverride: [40, 40, 45],
|
||||
gradientMode: 'radial',
|
||||
cubicScale: 1.55, schlegelScale: 1.40,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.50,
|
||||
vortices: [VX(0, 0, 1.10, 0.30)],
|
||||
ripples: [R(0, 0, 5, 0.13, 0.10)],
|
||||
e8Origins: [], linkCount: 12, linkCurvature: 0.45,
|
||||
fields: {
|
||||
cubic: F(0.55, 0.05, 0.70, 0.42, 0.55, 1.0),
|
||||
schlegel: F(0.55, 0.05, 0.60, 0.36, 0.72, 1.8),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0.55, 0.05, 0.95, 0.55, 0.92, 2.4),
|
||||
links: F(0.55, 0.05, 0.95, 0.55, 0.95, 2.6),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '18_quiet-single-vortex',
|
||||
label: 'Quiet · single small vortex + few curved links · contemplative counter',
|
||||
overrides: {
|
||||
...BASE,
|
||||
paperOverride: paper([195, 188, 178]),
|
||||
vignOverride: [55, 50, 45], featureOverride: [50, 45, 40],
|
||||
cubicScale: 1.40, schlegelScale: 1.20,
|
||||
schlegelInnerR: 0.40, schlegelRot3D: 0.45,
|
||||
vortices: [VX(0, 0, 0.50, 0.25)],
|
||||
e8Origins: [], linkCount: 4, linkCurvature: 0.40,
|
||||
fields: {
|
||||
cubic: F(0.60, 0.68, 0.30, 0.42, 0.40, 0.9),
|
||||
schlegel: F(0.62, 0.70, 0.40, 0.40, 0.55, 1.4),
|
||||
e8: F(0, 0, 0, 0.5, 0),
|
||||
ripple: F(0, 0, 0, 0.5, 0),
|
||||
links: F(0.06, 0.14, 0.80, 0.50, 0.85, 1.8),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
169
tools/qft-variations.mjs
Normal file
169
tools/qft-variations.mjs
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ============================================================
|
||||
qft-variations.mjs — render a curated set of variations.
|
||||
Single base seed (geometry held constant); each variation
|
||||
overrides per-field hue / sat / light / opacity + gradient mode
|
||||
+ substrate (or arbitrary paperOverride RGB) + cross-field
|
||||
link colours.
|
||||
Output → output/qft/sketch02/
|
||||
============================================================ */
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const BASE_SEED = 'FEYNMAN-7167';
|
||||
const OUT_DIR = 'output/qft/sketch02';
|
||||
const SIZE = 1800;
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
|
||||
const F = (hueStart, hueEnd, saturation, lightness, opacity) =>
|
||||
({ hueStart, hueEnd, saturation, lightness, opacity });
|
||||
|
||||
const variations = [
|
||||
{
|
||||
name: '01_anchor-vintage', label: 'Anchor · warm vintage muted',
|
||||
overrides: {
|
||||
substrate: 'vintage', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.08, 0.05, 0.30, 0.52, 0.65),
|
||||
schlegel: F(0.10, 0.10, 0.20, 0.48, 0.55),
|
||||
e8: F(0.10, 0.16, 0.65, 0.60, 0.92),
|
||||
links: F(0.10, 0.04, 0.90, 0.62, 0.95), // bright amber
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '02_ember-triad', label: 'Ember triad · warm fire band',
|
||||
overrides: {
|
||||
substrate: 'vintage', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.04, 0.10, 0.65, 0.55, 0.75),
|
||||
schlegel: F(0.96, 0.03, 0.55, 0.50, 0.65),
|
||||
e8: F(0.12, 0.18, 0.85, 0.62, 0.90),
|
||||
links: F(0.02, 0.10, 0.95, 0.62, 0.95), // deep red→orange
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '03_aurora-void', label: 'Aurora · cool spectral on void',
|
||||
overrides: {
|
||||
substrate: 'void', gradientMode: 'along-edge', vign: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.50, 0.72, 0.70, 0.60, 0.85),
|
||||
schlegel: F(0.40, 0.55, 0.55, 0.58, 0.75),
|
||||
e8: F(0.78, 0.92, 0.85, 0.65, 0.90),
|
||||
links: F(0.55, 0.85, 0.95, 0.70, 0.95), // cyan → violet bright
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '04_spectrum-cream', label: 'Spectrum · one rainbow field on cream',
|
||||
overrides: {
|
||||
substrate: 'cream', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.00, 0.95, 0.80, 0.48, 0.80),
|
||||
schlegel: F(0.0, 0.0, 0.05, 0.30, 0.50),
|
||||
e8: F(0.0, 0.16, 0.55, 0.42, 0.75),
|
||||
links: F(0.55, 0.05, 0.85, 0.45, 0.95), // cyan → red — spans the spectrum too
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '05_verdigris', label: 'Verdigris · oxidised copper / patina',
|
||||
overrides: {
|
||||
substrate: 'vintage', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.42, 0.50, 0.50, 0.55, 0.75),
|
||||
schlegel: F(0.06, 0.02, 0.45, 0.45, 0.65),
|
||||
e8: F(0.32, 0.45, 0.55, 0.55, 0.85),
|
||||
links: F(0.04, 0.10, 0.85, 0.58, 0.95), // copper highlights
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '06_radial-sunrise', label: 'Radial · cool centre → warm edges',
|
||||
overrides: {
|
||||
substrate: 'vintage', gradientMode: 'radial',
|
||||
fields: {
|
||||
cubic: F(0.55, 0.06, 0.60, 0.55, 0.78),
|
||||
schlegel: F(0.55, 0.06, 0.50, 0.55, 0.65),
|
||||
e8: F(0.55, 0.06, 0.70, 0.60, 0.88),
|
||||
links: F(0.55, 0.06, 0.90, 0.62, 0.95), // shares the radial gradient
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '07_magenta-family', label: 'Magenta family on cream',
|
||||
overrides: {
|
||||
substrate: 'cream', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.85, 0.93, 0.50, 0.45, 0.75),
|
||||
schlegel: F(0.78, 0.88, 0.42, 0.42, 0.65),
|
||||
e8: F(0.92, 0.00, 0.60, 0.48, 0.88),
|
||||
links: F(0.92, 0.78, 0.85, 0.40, 0.95), // saturated pink → purple
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '08_per-field-mono', label: 'Per-field monochrome',
|
||||
overrides: {
|
||||
substrate: 'vintage', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.55, 0.55, 0.55, 0.55, 0.70),
|
||||
schlegel: F(0.88, 0.88, 0.55, 0.55, 0.70),
|
||||
e8: F(0.12, 0.12, 0.75, 0.60, 0.92),
|
||||
links: F(0.34, 0.34, 0.80, 0.55, 0.95), // mono green accent — a 4th distinct hue
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '09_cyanotype', label: 'Cyanotype · Anna Atkins',
|
||||
overrides: {
|
||||
substrate: 'cyanotype', gradientMode: 'along-edge',
|
||||
fields: {
|
||||
cubic: F(0.55, 0.50, 0.30, 0.80, 0.85),
|
||||
schlegel: F(0.55, 0.55, 0.20, 0.85, 0.75),
|
||||
e8: F(0.48, 0.42, 0.50, 0.78, 0.92),
|
||||
links: F(0.55, 0.50, 0.30, 0.92, 0.95), // near-white connectors
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '10_single-bright-void', label: 'Single bright · E8 rainbow on void',
|
||||
overrides: {
|
||||
substrate: 'void', gradientMode: 'along-edge', vign: 0.55,
|
||||
fields: {
|
||||
cubic: F(0.0, 0.0, 0.05, 0.40, 0.45),
|
||||
schlegel: F(0.0, 0.0, 0.05, 0.42, 0.40),
|
||||
e8: F(0.0, 0.95, 0.95, 0.62, 0.98),
|
||||
links: F(0.0, 0.95, 0.95, 0.70, 0.98), // bright rainbow connectors
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '11_mauve-fog-custom', label: 'Bonus · custom mauve paper',
|
||||
overrides: {
|
||||
gradientMode: 'along-edge',
|
||||
paperOverride: { flat: [82, 76, 92], glowIn: [108, 98, 118], glowOut: [58, 52, 70] },
|
||||
vignOverride: [22, 18, 28],
|
||||
featureOverride: [200, 190, 215],
|
||||
fields: {
|
||||
cubic: F(0.00, 0.95, 0.50, 0.72, 0.80),
|
||||
schlegel: F(0.0, 0.0, 0.05, 0.85, 0.55),
|
||||
e8: F(0.55, 0.85, 0.65, 0.72, 0.92),
|
||||
links: F(0.55, 0.85, 0.85, 0.78, 0.95), // pastel cyan → violet
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const base = paramsFromSeed(BASE_SEED);
|
||||
for (const v of variations) {
|
||||
const params = { ...base, ...v.overrides };
|
||||
if (v.overrides.fields) params.fields = v.overrides.fields;
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, SIZE);
|
||||
const path = `${OUT_DIR}/${v.name}.svg`;
|
||||
writeFileSync(path, svg);
|
||||
console.log(`ok ${v.name} · ${v.label}`);
|
||||
}
|
||||
console.log(`\nrendered ${variations.length} variations → ${OUT_DIR}/`);
|
||||
32
tools/render-qft-svg.mjs
Normal file
32
tools/render-qft-svg.mjs
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Render one QFT plate to SVG from the CLI.
|
||||
Usage:
|
||||
node tools/render-qft-svg.mjs --seed SEED [out.svg] [size] [k=v ...]
|
||||
Modular sibling of tools/render-svg.mjs and render-milkweed-svg.mjs.
|
||||
*/
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import { generateQFTScene } from '../src/qft/scene.js';
|
||||
import { paramsFromSeed } from '../src/qft/params.js';
|
||||
import { renderQFTSVG } from '../src/qft/renderer.js';
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
if (argv[0] !== '--seed') {
|
||||
console.error('usage: node tools/render-qft-svg.mjs --seed SEED [out.svg] [size] [k=v ...]');
|
||||
process.exit(1);
|
||||
}
|
||||
const seed = argv[1] || 'QFT-001';
|
||||
const out = argv[2] || `/tmp/qft-${seed}.svg`;
|
||||
let size = 4800;
|
||||
if (argv[3] && !argv[3].includes('=')) size = +argv[3];
|
||||
|
||||
const params = paramsFromSeed(seed);
|
||||
for (const a of argv) {
|
||||
if (!a.includes('=')) continue;
|
||||
const [k, ...rest] = a.split('=');
|
||||
const v = rest.join('=');
|
||||
params[k] = v === 'true' ? true : v === 'false' ? false
|
||||
: (v.trim() !== '' && !isNaN(+v) ? +v : v);
|
||||
}
|
||||
|
||||
const svg = renderQFTSVG(generateQFTScene(params), params, size);
|
||||
writeFileSync(out, svg);
|
||||
console.log(`QFT SVG -> ${out} (${(svg.length / 1024).toFixed(0)} KB, archetype=${params.archetype})`);
|
||||
Reference in New Issue
Block a user