Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

add halley piece — Halley's method fractal for z³ + 7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+159
+159
system/public/aesthetic.computer/disks/halley.mjs
··· 1 + // Halley, 2026.3.02 2 + // Halley's method fractal for f(z) = z³ + 7. 3 + 4 + /* 📝 Engineering Notes 5 + Each pixel maps to a point z₀ in the complex plane. 6 + Halley's iteration: z ← z - z(z³+7) / (2z³-7) 7 + Color by which cube root of -7 the orbit converges to. 8 + Drag to pan. Use the on-screen buttons to zoom and reset. 9 + */ 10 + 11 + const { floor, min, cos, sin, PI } = Math; 12 + 13 + // View parameters 14 + let cx = 0, cy = 0, zoom = 2.5; 15 + let maxIter = 24; 16 + let dirty = true; 17 + 18 + // Drag state 19 + let dragging = false, dragX = 0, dragY = 0, dragCx = 0, dragCy = 0; 20 + 21 + // UI buttons 22 + let zoomInBtn, zoomOutBtn, resetBtn; 23 + 24 + // The three cube roots of -7: 7^(1/3) · e^(i(π+2πk)/3), k=0,1,2 25 + const cbrt7 = Math.cbrt(7); 26 + const roots = [ 27 + [cbrt7 * cos(PI / 3), cbrt7 * sin(PI / 3)], 28 + [-cbrt7, 0], 29 + [cbrt7 * cos(5 * PI / 3), cbrt7 * sin(5 * PI / 3)], 30 + ]; 31 + 32 + // Root colors — three distinct hues 33 + const palette = [ 34 + [60, 180, 255], // blue 35 + [255, 80, 120], // rose 36 + [80, 255, 160], // mint 37 + ]; 38 + 39 + function boot({ ui, screen }) { 40 + zoomInBtn = new ui.TextButton("zoom +", { bottom: 8, right: 8, screen }); 41 + zoomOutBtn = new ui.TextButton("zoom -", { bottom: 8, right: 80, screen }); 42 + resetBtn = new ui.TextButton("reset", { top: 8, right: 8, screen }); 43 + } 44 + 45 + function paint({ screen, ink }) { 46 + const { width: w, height: h, pixels } = screen; 47 + 48 + if (dirty) { 49 + dirty = false; 50 + const scale = zoom / min(w, h); 51 + 52 + for (let py = 0; py < h; py++) { 53 + for (let px = 0; px < w; px++) { 54 + let zr = (px - w / 2) * scale * 2 + cx; 55 + let zi = (py - h / 2) * scale * 2 + cy; 56 + 57 + let iter = 0; 58 + let converged = -1; 59 + 60 + for (; iter < maxIter; iter++) { 61 + const r2 = zr * zr, i2 = zi * zi; 62 + if (r2 + i2 < 1e-12) break; 63 + 64 + const z2r = r2 - i2; 65 + const z2i = 2 * zr * zi; 66 + const z3r = z2r * zr - z2i * zi; 67 + const z3i = z2r * zi + z2i * zr; 68 + 69 + const fr = z3r + 7; 70 + const fi = z3i; 71 + const gr = 2 * z3r - 7; 72 + const gi = 2 * z3i; 73 + 74 + const nr = zr * fr - zi * fi; 75 + const ni = zr * fi + zi * fr; 76 + 77 + const denom = gr * gr + gi * gi; 78 + if (denom < 1e-14) break; 79 + 80 + zr -= (nr * gr + ni * gi) / denom; 81 + zi -= (ni * gr - nr * gi) / denom; 82 + 83 + for (let k = 0; k < 3; k++) { 84 + const dr = zr - roots[k][0]; 85 + const di = zi - roots[k][1]; 86 + if (dr * dr + di * di < 1e-6) { 87 + converged = k; 88 + break; 89 + } 90 + } 91 + if (converged >= 0) break; 92 + } 93 + 94 + const idx = (py * w + px) * 4; 95 + 96 + if (converged >= 0) { 97 + const t = 1 - iter / maxIter; 98 + const bright = 0.3 + 0.7 * t * t; 99 + const c = palette[converged]; 100 + pixels[idx] = floor(c[0] * bright); 101 + pixels[idx + 1] = floor(c[1] * bright); 102 + pixels[idx + 2] = floor(c[2] * bright); 103 + } else { 104 + pixels[idx] = 8; 105 + pixels[idx + 1] = 6; 106 + pixels[idx + 2] = 12; 107 + } 108 + pixels[idx + 3] = 255; 109 + } 110 + } 111 + } 112 + 113 + // Draw buttons over the fractal 114 + zoomInBtn.reposition({ bottom: 8, right: 8, screen }, "zoom +"); 115 + zoomOutBtn.reposition({ bottom: 8, right: 80, screen }, "zoom -"); 116 + resetBtn.reposition({ top: 8, right: 8, screen }, "reset"); 117 + 118 + const normal = ["white", "black", "black", "white"]; 119 + const hover = ["yellow", "black", "black", "yellow"]; 120 + 121 + zoomInBtn.paint({ ink }, normal, hover); 122 + zoomOutBtn.paint({ ink }, normal, hover); 123 + resetBtn.paint({ ink }, normal, hover); 124 + } 125 + 126 + function act({ event: e, screen, pens }) { 127 + const zoomFactor = 1.3; 128 + 129 + zoomInBtn.act(e, { 130 + down: () => { zoom /= zoomFactor; dirty = true; }, 131 + }, pens?.()); 132 + 133 + zoomOutBtn.act(e, { 134 + down: () => { zoom *= zoomFactor; dirty = true; }, 135 + }, pens?.()); 136 + 137 + resetBtn.act(e, { 138 + down: () => { cx = 0; cy = 0; zoom = 2.5; dirty = true; }, 139 + }, pens?.()); 140 + 141 + // Drag to pan 142 + if (e.is("touch")) { 143 + dragging = true; 144 + dragX = e.x; dragY = e.y; 145 + dragCx = cx; dragCy = cy; 146 + } 147 + if (e.is("draw") && dragging) { 148 + const scale = (zoom * 2) / min(screen.width, screen.height); 149 + cx = dragCx - (e.x - dragX) * scale; 150 + cy = dragCy - (e.y - dragY) * scale; 151 + dirty = true; 152 + } 153 + if (e.is("lift")) { 154 + dragging = false; 155 + } 156 + } 157 + 158 + export { boot, paint, act }; 159 + export const noBios = true;