Skip to the plate
FORMA PUBLIC DOMAIN GENERATIVE ATLAS / ED. 0.28
Plate 09, Clifford Map: a still of the map / iterated plate as the atlas renders it, in the attractors accent.

PL. 09  ·  ATTRACTORS / MAP / ITERATED

Clifford Map

Clifford A. Pickover

OPEN THE LIVE PLATE ▸

DEFINITION

xₙ₊₁ = sin(a·yₙ) + c·cos(a·xₙ)
yₙ₊₁ = sin(b·xₙ) + d·cos(b·yₙ)

NOTES

A sibling of the de Jong map with the cosine terms scaled rather than subtracted. The result tends toward smoke and ribbon rather than veil. Pickover catalogued dozens of these in the late 1980s while looking for what he called "biomorphs".

PROVENANCE

Origin
Clifford A. Pickover, from his work on iterated maps
Standing
Public domain — an iterated map
Constants
Keep |c| and |d| near 1 for the densest structure

HOUDINI · VEX

The same published mathematics as a Detail Wrangle body. Paste it into a Wrangle with Run Over set to Detail; every constant is the published value plus a tweak channel, so Create Spare Parameters gives a slider that starts where the paper does.

// FORMA — PL. 09 · CLIFFORD MAP — Clifford A. Pickover
//   xₙ₊₁ = sin(a·yₙ) + c·cos(a·xₙ)
//   yₙ₊₁ = sin(b·xₙ) + d·cos(b·yₙ)
// Paste into a Detail Wrangle (Run Over: Detail), no inputs needed.
// Written from the published mathematics, not adapted from any code.
// Constants arrive at their published values. Press the node's Create
// Spare Parameters button and every tweak becomes a slider — starting
// at 0, the published figure, and moving in the constant's own units.
// https://forma-gen.com/#plate=clifford

float p_a = -1.4 + chf('a_tweak');    // a · live -3 .. 3
float p_b = 1.6 + chf('b_tweak');     // b · live -3 .. 3
float p_c = 1 + chf('c_tweak');       // c · live -2 .. 2
float p_d = 0.7 + chf('d_tweak');     // d · live -2 .. 2

// The plate's own colour: FORMA's ATTRACTORS accent as a cosine ramp,
// brightest near t = 0 and t = 1, near-black around t = 0.5.
vector forma_ramp(float t){
  return set(
    0.0956 + 0.1039 * cos(6.28318530718 * (t + 0)),
    0.4041 + 0.4392 * cos(6.28318530718 * (t + 0.05)),
    0.46 + 0.5 * cos(6.28318530718 * (t + 0.1)));
}

// The exposure replayed as a point cloud: iterate from (0.1, 0.1) and discard
// the first 20 landings, as the plate's expose() does.
int forma_pts  = 120000;
int forma_skip = 20;

float x = 0.1, y = 0.1;
for (int i = 0; i < forma_pts + forma_skip; i++){
    float nx = sin(p_a * y) + p_c * cos(p_a * x);
    float ny = sin(p_b * x) + p_d * cos(p_b * y);
    x = nx;  y = ny;
    if (i < forma_skip) continue;
    // canvas y runs down; negated so the figure sits as the plate shows it
    int pt = addpoint(0, set(x, -y, 0.0));
    float u = float(i) / float(forma_pts + forma_skip);
    setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
}