PL. 79 · ATTRACTORS / MAP / PIECEWISE LINEAR
Gingerbreadman Map
Robert L. Devaney, 1984
OPEN THE LIVE PLATE ▸DEFINITION
xₙ₊₁ = 1 − yₙ + |xₙ| yₙ₊₁ = xₙ area-preserving · piecewise linear
NOTES
One absolute value is the entire nonlinearity — no multiplication anywhere — and it is enough for chaos. The map preserves area, so nothing contracts onto a thin attractor; instead the plane divides into six hexagonal islands where every orbit has period six, set in a chaotic sea that orbits wander forever without escaping. The figure is named for its outline. Because no single orbit sees more than its own region, the plate seeds many and lets each run a while, which is the only honest way to draw a map that has no attractor to fall onto.
PROVENANCE
- Origin
- R. L. Devaney, studied from 1984; the widely cited published account is "Fractal patterns arising in chaotic dynamical systems", in H.-O. Peitgen & D. Saupe (eds.), The Science of Fractal Images, Springer, 1988
- Standing
- Public domain — an iterated map
- Constants
- Orbit length is the strongest lever on the reading: short runs give scattered dust across many regions, long ones close the hexagonal islands into solid rings. Both are true pictures of the same map
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. 79 · GINGERBREADMAN MAP — Robert L. Devaney, 1984
// xₙ₊₁ = 1 − yₙ + |xₙ|
// yₙ₊₁ = xₙ
// area-preserving · piecewise linear
// 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=gingerbread
float p_run = 150 + chf('run_tweak'); // orbit length · live 30 .. 500
float p_spread = 6 + chf('spread_tweak'); // seed spread · live 2 .. 9
// 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)));
}
// Area-preserving, so no orbit ever shows more than its own region —
// the figure is the union of many short orbits from scattered seeds,
// the same treatment mira and the standard map need for the same reason.
int forma_pts = 120000;
float x = 0.0, y = 0.0;
int run = int(p_run) + 1, si = 0; // force a seed on the first step
for (int i = 0; i < forma_pts; i++){
if (++run > int(p_run)){
run = 0;
// deterministic scattered restarts, mirroring the plate's seeded rng
x = 1.0 + (random(si * 2) - 0.5) * p_spread;
y = 1.0 + (random(si * 2 + 1) - 0.5) * p_spread;
si++;
}
float nx = 1.0 - y + abs(x);
y = x;
x = nx;
// 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);
setpointattrib(0, "Cd", pt, forma_ramp(0.8 + 0.3 * u));
}