Live explorable /explain.html — log → bend → exp pipeline#13
Merged
Conversation
Reframe the README around the tententoon idea (same picture, two infinities) rather than implementation: a side-by-side Droste/tententoon visual, a precise one-line definition, the log-polar idea in plain language, and the Escher / de Smit-Lenstra origin. Run and tech details move to a collapsed footer. Add public/explain.html: a standalone 'what is a tententoon' deep-dive styled as an aged-paper dictionary card (syllabified headword, IPA, numbered sense + usage example, bracketed etymology, inline nested-squares SVG mark), flowing into a plain-language account of why the spiral closes seamlessly (the logarithm trick), Escher's hand-drawn blank centre, and the 2003 de Smit-Lenstra completion. Revert the in-app InfoModal copy to the hand-written original and tag it .human-written so it is preserved from future rewrites. Add public/tententoon-demo.gif (spiral demo) for the README + page visuals. docs/screenshots/ holds card previews for this PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fold in the math from the feat/pipeline-explorable-view worktree's 4-panel view: source + rect -> log(z-c) lattice (periods logS, 2pi) -> tilt by beta = arctan(logS/2pi) -> roll back up via w(z) = c + (z-c)^alpha. Turns the 'why doesn't it tear' section from intuition into the concrete four frames the maths passes through, with named parameters. Drops the earlier complex-map aside, now redundant (step 4 carries the exact map). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts: # README.md
explain.html moves from public/ (static) to a Vite entry (added to rollupOptions.input) with src/explain/main.ts. It loads a swappable test image (SOURCE + optional NEST consts at the top of main.ts), builds the Droste geometry with fitCropToNest/buildPanelGeometry, and renders source - log(z-c) - rotated-log - tententoon live via the app's PipelinePanelGLRenderer. No duplicated math: the page reuses the same GPU renderer and geometry helpers the in-app pipeline view uses. Dragging the log panel pans log space: horizontal pan = zoom, vertical pan = rotation, and the tententoon follows with a live readout (verified at 144 deg / x33). Falls back to the four-step prose if WebGL2 is unavailable. Removes the now-superseded static public/explain.html. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per feedback, drop the 2x2 grid and the source panel. The tententoon spiral now replaces the animated GIF in 'Now bend it'. In 'Why doesn't it tear?', the log(z-c) panel becomes a hands-on experiment: drag it and the original picture beside it rotates (vertical) and zooms (horizontal), with a live readout. The rotated-log lattice stands on its own as the 'lean it over' illustration. 'The original' is rendered by the same engine with the twist off (kTwist=0), so it zooms cleanly (mipmapped) and seamlessly. Verified: vertical drag -> 144 deg rotation, horizontal -> x33 zoom. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add two controls to the explorable, both feeding the reused GPU pipeline: a source toggle (picture / grid / polar / overlay) and a twist-angle (beta) slider. src/explain/patterns.ts generates grid + polar sources centred on the limit point c at the photo's pixel size. Polar rings are individually styled (thick / dashed / plain, in ink then red) so you can follow one through the map, and spaced by S^(1/6) so the style cycle is S-periodic = seamless under the Droste fold; in the log panel each ring becomes its own vertical line. The slider overrides beta = atan(logS/2pi): the tententoon twist is tan(beta) and the rotated-log leans by beta. Only at the canonical beta does the spiral close (a 'closed' marker shows it). Verified live: circles -> vertical lines, grid warps, overlay, and a 20deg twist clearly tightens the spiral. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
It was never a theorem. de Smit and Lenstra worked out the exact map (the structure) hiding in Escher's grid, and the missing centre was then filled by computer. That is analysis plus a method/recipe, not a theorem. Rename the heading 'The theorem that filled the hole' -> 'The map that filled the hole', say 'worked out' (not 'wrote down'), and call the distinction out in the text ('this is not a theorem so much as a recipe').
Voice pass over the prose per the writing profile: drop em-dash connectors throughout (colons / parentheses / periods instead) and remove 'seamlessly' from the UI copy. Code comments left untouched (not published prose).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The centrepiece spiral barely bent: the demo photo's honest closing angle is only ~6.8°, so "now bend it" landed flat. Drive the hero from a bold synthetic geometry (S=20 → β≈25.5°, just shy of Escher's 26°) using the scale-invariant ring/grid patterns, which twist hard AND still close seamlessly. The photo keeps its faithful gentle nesting for "photo" mode; switching source switches geometry, and β + the "closed ✓" mark follow. New, all reusing the shared GPU pipeline (no duplicated map math): - unroll: a new shader mode (3) + u_morph that morphs the spiral into the flat leaned-over strip in source log-polar space — exact at both ends, genuinely curling in between. Slider + play (pauses offscreen, honours prefers-reduced-motion). Additive: PipelinePanel + tests untouched. - Droste↔Escher twist slider from 0° (flat Droste) to the closing angle, with a "snap it shut" tween and an accent glow at closed. - a zero-math spiral-staircase analogy (rings ↔ flat lines SVG). Re-paced the whole page for a reader who knows no complex numbers or logs: see the log happen (unroll) before it's ever named, with the formula/β/lattice quarantined into one "for the curious" tier. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reframe the explainer around the real decomposition, as one connected, realtime pipeline: the original → we log it → we bend it → we exponentiate it. Four panels in a row on desktop, stacked on mobile; one bend (lean) control leans the strip and twists the spiral together, dragging the flat strip pans all of them, and a roll control rolls the bent strip up into the spiral. Source switcher (ring/grid/photo/overlay) under every panel, one global state. Live, value-bearing math under each step instead of an abstract formula dump: S and log S at the log step, α = 1 − k·i at the bend step (updating as you drag the lean), w = c + (z−c)^α at exp. Removed the standalone "For the curious: the actual map" section. Prose pass for a reader who knows no complex numbers or logs: - slower opening — start from the pre-Droste photo (empty frame) and build the Droste by dropping the picture into its own frame; - the circle → repeating-line bit gets its own diagram (angular periodicity), and the point is now WHY it works: the logged image is periodic, so a one-tile step lands on an identical region — that's the seamless close, not "it just repeats forever"; - cut filler/false claims (no "needs no mathematics", no "recipe not a theorem"), name the logarithm only after the mechanism is shown. UX per review: default source = overlay; spiral shown by default at exp with no auto-play and no play button; drag now follows the pointer (inverted both axes). Vendored a local 3Blue1Brown thumbnail (Escher → log(Escher)) into "See it move". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
Redeployed latest to staging: https://silvio-tententoon.pgs.sh/explain.html (4-panel log→bend→exp pipeline, live math, overlay default; console clean). |
Collaborator
Author
|
Correction: staging serves extensionless URLs — the live page is https://silvio-tententoon.pgs.sh/explain (not /explain.html). Verified live: 4-panel log→bend→exp pipeline, live math (S, log S, α), overlay default, console clean. |
Add a free complex-function explorer (input plane | selector | output plane) that runs before the log -> bend -> exp construction, so the reader learns to read a function as a machine that moves the plane before the spiral panels assume that language. - src/explain/playground.ts: self-contained Canvas-2D visualiser. Drag a point, switch f(z) among z, 2z, iz, z^2, exp, log, toggle grid/rings/ photo, scrub a continuous identity->f interpolation. Grid/ring lines are sampled and stroked through the map (broken at branch cuts); the photo is forward-warped through a triangle mesh. - explain.html: 'First, what is a function?' + 'The function we need' + 'Why the picture still looks like a picture' sections, plus CSS. - main.ts: boot the playground alongside the pipeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Boot the function playground from a ResizeObserver plus a deferred rAF pass, and make resize()/draw() no-op until the canvas actually has a laid-out width. This keeps the explorer from drawing into a zero-size canvas when the module evaluates before CSS layout, and removes the temporary init logging added while diagnosing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The output plane auto-fit its viewport to the mapped image, so f(z)=2z
doubled both the content and the frame — the two cancelled and the grid
looked untouched ("the function did nothing"). Pin the output to the
input's half-extent (D) for the linear maps z, 2z, iz, so doubling now
reads as a visibly coarser grid with the point flung outward, and the
quarter-turn is unmistakable. Nonlinear maps (z², exp, log) still
auto-fit, since for them the lesson is the shape change, not scale, and
they need the room to stay framed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The input plane was 4.8 rad tall (D = 2.4), but exp(z) maps the imaginary part to the output angle — so a 4.8-rad strip only swept 4.8/2π ≈ 76% of a lap and the rings stopped short, leaving "exp rolls the plane around the origin" visibly false. Set D = π so the vertical span is exactly 2π and exp closes into full circles. Align GRID_STEP to π/8 so the grid divides D evenly (no edge sliver). Same 2π periodicity that closes the tententoon spiral. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #10. A standalone, GPU-rendered explorable at
/explain.htmlthat walks from the everyday Droste effect to Escher's closed spiral and the de Smit–Lenstra map — built for someone who knows no complex numbers or logs.Staging: https://silvio-tententoon.pgs.sh/explain.html
Function playground (new)
Before the
log → bend → expconstruction, a free function playground teaches readers to read a complex function as "a machine that moves the plane."src/explain/playground.ts— self-contained Canvas-2D explorer (no WebGL, independent of the Droste pipeline). Drag a point on the input plane, watch wheref(z)lands on the output plane.z,2z,iz,z²,exp(z),log(z). Toggle grid / rings / photo (all forward-warped). Continuous identity → function slider (f_t(z) = (1−t)z + t·f(z)).The spine: one pipeline, four live panels
the original → we log it → we bend it → we exponentiate it, connected in realtime (horizontal row on desktop, stacked on mobile):S,log S,α = 1 − k·i— updates as you pick a source or drag the lean.Pedagogy & prose
Engine
unrollmode +u_morph, fully additive (the main app's PipelinePanel and all existing tests are untouched).🤖 Generated with Claude Code