Walldye

Dragon quartet

A paper strip folded in half repeatedly and opened to right angles at each crease forms a Heighway dragon.

Made with Claude Opus 5.5

Technique
line art, flat shapes
Shape
Any screen
Added
27 September 2026

Export

Shape
cropped from 16:9
Across
Down
Scale
Crop
Size
Format

Colors

  • #1C1B1Abackground
  • #DAD8CEforeground
  • #CF6A4Caccent

Notes

Ten folds give a dragon of 1,024 steps. Here each step becomes a small square with the step as its diagonal. Four copies, each a quarter turn from the next around their shared start, fit together without overlapping.

Sources

  1. Dragon curve.
  2. Chandler Davis and Donald Knuth, Number representations and dragon curves, 1970.

Source code

wallpapers/dragon-quartet/design.py, 56 lines

"""Four Heighway dragons around one point, built from square cells."""

import numpy as np
import shapely
from numpy.typing import NDArray
from shapely.geometry.base import BaseGeometry

from walldye import ACCENT, ACCENT_2, BG_ALT, UI, Canvas, P, Rect, design
from walldye.geom import Affine

LEVEL = 10  # 2**LEVEL steps per dragon
UNIT = 18  # px per lattice step; an even number keeps every cell edge on the pixel grid
GLOW = 25  # lattice steps from the shared origin to the glow's outer stop
OUTLINES = ((1, BG_ALT), (3, BG_ALT), (2, UI))  # quarter turns from the filled dragon, and tone


def dragon() -> NDArray[np.complex128]:
    """The vertices of the Heighway dragon of 2**LEVEL unit steps, starting at 0 heading +x."""
    n = np.arange(1, 2**LEVEL)
    right = (((n & -n) << 1) & n) != 0
    heading = np.concatenate([[0], np.cumsum(np.where(right, -1, 1))]) % 4
    step = np.array([1, 1j, -1, -1j])[heading]
    return np.concatenate([[0], np.cumsum(step)])


def region(z: NDArray[np.complex128]) -> BaseGeometry:
    """Union of the squares having each step of `z` as diagonal; every lattice edge owns one
    square, so the four rotated dragons tile without overlapping."""
    a, b = z[:-1], z[1:]
    m, h = (a + b) / 2, (b - a) * 0.5j
    quads = np.stack([a, m + h, b, m - h], axis=1)
    return shapely.union_all(
        shapely.polygons(np.stack([quads.real, quads.imag], axis=-1))
    ).simplify(0)


@design(aspects="any")
def draw(s: Canvas) -> None:
    # the pinwheel is symmetric about its shared origin, so that point is its center
    c = s.pick(landscape=(1250 / 1920, 500 / 1080), portrait=(0.5, 0.55), snap=1)
    to_local = Affine.scale(UNIT)
    # diagonal steps make the cells axis-aligned squares half a lattice step wide
    z = dragon() * (1 + 1j) / 2
    regions = [region(z * 1j**k) for k in range(4)]
    # outline strokes reach 1 unit past the cells
    x0, y0, x1, y1 = (v * UNIT for v in shapely.union_all(regions).bounds)
    with s.motif(c, Rect(x0 - 1, y0 - 1, x1 - x0 + 2, y1 - y0 + 2), cell=UNIT // 2):
        # outline edges stop short of the filled dragon, so they butt against it rather than
        # trace it
        keep_out = regions[0].buffer(0.02)
        for k, tone in OUTLINES:
            edge = shapely.transform(regions[k].boundary.difference(keep_out), to_local.apply)
            s.stroke(P().shape(edge), tone, 1.2, join="round", cap="round")
        # brightest at the shared origin, cooling toward the tail
        glow = s.radial_gradient([(0, ACCENT), (1, ACCENT_2)], (0, 0), GLOW * UNIT)
        s.fill(P().shape(shapely.transform(regions[0], to_local.apply)), glow)

Run it yourself

$ git clone https://github.com/nickolaj-jepsen/walldye && cd walldye$ uv run walldye render dragon-quartet --theme fireproof -o dragon-quartet-fireproof-16x9.svg