a square filling a cube — every colour equally often, no seams
part of the pack · geometry · voronoi · cohomology · kakeya · heilbronn
Pixel (x, y) is coloured by a continuous map from the square onto the RGB cube. That is impossible to do smoothly: a square has two dimensions to spend and a cube costs three, so the best exponent any such map can have is 2/3, and until 2026 nobody knew whether 2/3 itself was reachable (Arnold's problem 1988–5). Badger and Palmer reached it. This page renders their surface, folded so that every colour appears equally often, then bends it with area-preserving maps of the torus so a seed makes a family. Drag to pan, wheel to zoom: it is the same surface at every scale.
Strength 0 is the bare surface of the paper. Every setting lives in the URL, so a good one is a link.
The claims are countable, so count them. The engine renders the current seed on the CPU at a chosen size, quantises to a colour cube whose volume divides the pixel count, and reports how often each colour occurs and how far apart neighbours are. At the sizes marked exact, the bare surface hits every colour precisely the same number of times.
Render the whole torus tile of the current seed as a PNG. At the exact sizes the channels are quantised to the number of levels the count works for, so the file is the census: every colour in it appears the same number of times, and no two neighbours differ by more than a couple of levels.
Rendered on the GPU, so it takes a moment and a 4096² file is about 64 MB of pixels before compression. The print ignores the view: it is always the full tile, which repeats seamlessly in both directions. Exactness holds for the bare surface (strength 0, no cat map); warps keep the histogram flat in the limit but not to the pixel.
Watch it get built. Each pixel is one run of the same four steps: its two coordinates each walk the staircase curve into the X-shaped fractal, Stong's map adds the two x-coordinates and keeps the two y-coordinates, the fold lays the sum flat, and the palette names the channels. Scan paints pixel by pixel with the machinery shown for the pixel in hand. Refine paints the whole square at depth 1, then 2, then 3, then 5: the same algorithm, allowed one more octal digit each pass.
g(u) — the x coordinate walks the X
g(v) — the y coordinate walks the X
L, folded — where the pixel lands in the cube
Uses the seed, strength, cat map, palette and red-channel mode from the surface tab, on a 256² canvas. At depth 1 the staircase has one octal digit and the image is 32 blocks a side; depth 2 is one block per pixel here; deeper passes only move colours by a level or two, which is the Hölder condition again.
A continuous map from the square onto the cube exists by Hahn–Mazurkiewicz, but that argument says nothing about how violently it must tear distances. Measure the violence with a Hölder exponent: ‖f(x)−f(y)‖ ≤ H‖x−y‖α. Larger α means gentler. Cut the square into k² cells; each image has diameter at most Hk−α, and those k² blobs must cover a cube of volume one, so k² · (Hk−α)³ ≥ 1 for every k, which forces α ≤ 2/3. Arnold asked in 1988 whether 2/3 is attained. Shchepin got every exponent below it in 2010. Badger and Palmer's Space-filling surfaces (arXiv:2608.21246, August 2026) attains it, with the explicit constant ‖f(x)−f(y)‖∞ ≤ 48‖x−y‖∞2/3.
For a picture the exponent is a budget, not a style. A square image of side N whose neighbours differ by at most d colour levels can reach at most about (N · d)2/3 distinct values per channel. Hitting all of 256³ colours with every one used equally often, on a square, with small d, is exactly the α = 2/3 case. Anything smoother must miss colours.
The engine in surface.js runs the paper's map in four steps.
The paper needs an onto map with a clean constant, so it takes the image of L, a box of size 3×1×1, clips it to a small central cube, and rescales. For a picture that is a catastrophe: 98% of the square lands on the clipped faces. The paper also never claims measure preservation, and the clipped map has none.
So this page folds instead. The first coordinate P = a₁ + 2a₂ is the sum of two independent uniforms on [0,1] and [0,2], which is a trapezoid on [0,3]: ramp up, plateau at 3/2, ramp down. A triangle wave of period 2 lays the two ramps on top of each other and they add up to the plateau. So (fold P, b₁, b₂) has a flat histogram in the limit, and folding is continuous, so the exponent survives. The joint flatness, not just the marginal, is what the lattice bijection buys: at image sizes aligned to the lattice the count is exact to the pixel, which the selftest holds it to and the census tab lets you check. The fold's phase is not free: any other crease misaligns the ramps and the histogram develops holes.
| image | colour cube | pixels per colour | counted | max neighbour jump |
|---|---|---|---|---|
| 256² | 16³ | 16 | exactly 16, every colour | 2 of 16 |
| 512² | 32³ | 8 | exactly 8, every colour | 2 of 32 |
| 1024² | 64³ | 4 | 0 to 8, 99.9% of colours hit | 2 of 64 |
| 2048² | 64³ | 16 | exactly 16, every colour | 2 of 64 |
| 4096² | 128³ | 8 | exactly 8, every colour | 2 of 128 |
| 8192² | 256³ | 4 | 0 to 8, 99.95% of colours hit (offline, 67M pixels) | 2 of 256 |
The 8192² row is the regime of the image that prompted this page, which was described as every RGB value between 1 and 10 times, average 4, neighbours within 4/255. The surface here does the same job slightly tighter. The rule for exactness is that the image side is 4·8k or twice that and the cube side is 4k or twice that, so every pixel sits inside one lattice square and every lattice square inside one colour cell.
The surface itself is one object. Its symmetries are the symmetries of the image: the parameter curve is closed, so the square is a torus and the image tiles; rotating the X shifts the tile by a quarter; reflecting it flips the tile. Zooming into any cell shows the whole surface again, rotated and linearly recoloured, which is why the zoom never runs out. None of that makes a second image.
Two things do, and both keep the histogram flat by construction.
What does not work: exact-histogram post-processing. Sorting pixels into slices to force every count to 4 moves colours by up to 8 levels and lifts the neighbour jump from 2 to 12. The continuum object is flat; the discrete render is flat exactly where the lattice says so and within a few counts elsewhere. That is the honest statement and it is what the census reports.
The GPU evaluates the map per pixel from a 32-bit fixed-point torus
coordinate: two bits choose which copy of the staircase, ten octal digits
walk the similarities, and the walk finishes at the centre of the last
square, which is exactly where every quarter-triangle's apex is. Warps are
integer adds of a float displacement, so zoom stays precise to about
2−14 of the tile. The CPU engine in
surface.js does the same in doubles; the census uses it, the
selftest imports it, and the GPU = CPU? button compares the two.
References: Badger & Palmer,
arXiv:2608.21246;
R. Stong, Mapping ℤʳ into ℤˢ with maximal contraction, Discrete
Comput. Geom. 20 (1998); V. I. Arnold, Arnold's Problems, 1988–5;
E. V. Shchepin, On Hölder maps of cubes, Math. Notes 87 (2010).
Engine and checks: arnold/surface.js,
node arnold/surface.selftest.mjs.