← All projects

Cobweb Plots

Cobweb plot visualiser, built in p5.js.

Apr 2026 JavaScript (p5.js) GitHub ↗
dynamical systems p5.js visualisation

Overview

A cobweb plot is a tool for visualsing the behaviour of discrete 1D iterated functions, functions of the form \(x_{n+1}=f(x_n)\). Going forward we will be using the logistic map as an example, with

\[x_{n+1}=rx_n(1-x_n) \]

This implementation uses a brute-force per-pixel approach: for every pixel \((x, y)\), compute the Euclidean distance to each seed and assign the pixel to the nearest one.

Demo

Cobweb plot of logistic map

Implementation notes

Complexity

For \(N\) seeds and a \(W \times H\) canvas, the brute-force approach runs in \(O(N \cdot W \cdot H)\). Here (\(N = 24\), \(560 \times 340\)) that is around 4.6 million distance computations per frame. This is fine for a one-shot render but does not scale. Fortune's algorithm constructs the diagram in \(O(N \log N)\).

Edge detection

Edges are detected per-pixel rather than traced geometrically. A pixel at \((x,y)\) is classified as a boundary pixel when the difference between its nearest and second-nearest seed distances falls below a threshold \(\varepsilon\):

\[ \text{edge}(x,y) \iff d_2(x,y) - d_1(x,y) < \varepsilon \]

With \(\varepsilon = 2.5\) px this gives clean single-pixel-wide edges without any geometric boundary tracing.

Pixel density

pixelDensity(1) must be called in setup(). On HiDPI displays the default density is 2, so the pixel buffer is four times larger than expected and index arithmetic silently produces a corrupted image.

Implementation

Entire code found on Github

The cobweb loop:


  let x0 = 0.1;
  let y0 = 0;
  for (let i = 0; i < n_iters; i++) {
    let fx = r * x0 * (1 - x0);
    line(cx(x0), cy(y0), cx(x0), cy(fx));
    line(cx(x0), cy(fx), cx(fx), cy(fx));
    y0 = fx;
    x0 = fx;
  }