228

Gerstner Ocean Waves

František Gerstner's exact nonlinear trochoidal ocean wave equation, exhibiting physically accurate sharpened wave crests and broad, flat troughs.

Playground
60 FPS Canvas 2D
Click + Drag to interact with field
</>

Full Executable Algorithm Code

// 033 - Gerstner Ocean Waves (botany)
// 1:1 Original algorithm engine source
function createGerstnerOceanWaves() {
  const WAVE_LINES = 32;
  const POINTS_PER_LINE = 160;
  return {
    setup() {
    },
    render(context, timeState, params) {
      const { ctx, width, height } = context;
      const speed = Number(params.waveSpeed || 1.2);
      const steepness = Number(params.steepness || 0.65);
      const t = timeState.time * speed;
      ctx.fillStyle = "#050a12";
      ctx.fillRect(0, 0, width, height);
      const waves = [
        { dx: 1, dy: 0.1, length: 140, amp: 26, s: 1 },
        { dx: 0.8, dy: 0.6, length: 85, amp: 14, s: 1.4 },
        { dx: 0.5, dy: -0.8, length: 50, amp: 8, s: 1.8 },
        { dx: -0.7, dy: 0.7, length: 30, amp: 4, s: 2.2 }
      ];
      for (let l = 0; l < WAVE_LINES; l++) {
        const normL = l / WAVE_LINES;
        const originY = height * 0.25 + normL * (height * 0.65);
        ctx.beginPath();
        for (let i = 0; i <= POINTS_PER_LINE; i++) {
          const normX = i / POINTS_PER_LINE;
          const x0 = normX * width;
          const y0 = originY;
          let displacedX = x0;
          let displacedY = y0;
          for (let w = 0; w < waves.length; w++) {
            const wv = waves[w];
            const k = 2 * Math.PI / wv.length;
            const wSpeed = Math.sqrt(9.8 * k) * wv.s;
            const phase = k * (wv.dx * x0 + wv.dy * y0) - wSpeed * t;
            const q = steepness / (k * wv.amp * waves.length);
            displacedX -= wv.dx / k * (q * Math.sin(phase));
            displacedY -= wv.amp * Math.cos(phase);
          }
          if (i === 0) ctx.moveTo(displacedX, displacedY);
          else ctx.lineTo(displacedX, displacedY);
        }
        const hue = (195 + normL * 35) % 360;
        const lightness = 40 + (1 - normL) * 35;
        ctx.strokeStyle = hsla(hue, 90, lightness, 0.75);
        ctx.lineWidth = 1.6 - normL * 0.6;
        ctx.stroke();
      }
    }
  };
}

// Default parameters from content metadata
const defaultParams = [
  {
    "key": "waveSpeed",
    "label": "Wave Swell Velocity",
    "type": "range",
    "min": 0.4,
    "max": 3,
    "step": 0.1,
    "defaultValue": 1.2,
    "description": "Ocean current propagation rate"
  },
  {
    "key": "steepness",
    "label": "Trochoidal Steepness (Q)",
    "type": "range",
    "min": 0.2,
    "max": 1,
    "step": 0.05,
    "defaultValue": 0.65,
    "description": "Crest sharpness & horizontal pinching"
  }
];

if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['gerstner-ocean-waves']) {
  const inst = typeof createGerstnerOceanWaves === 'function' ? createGerstnerOceanWaves() : null;
  if (inst && inst.setup) {
    inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
  }
  window.__art_instances['gerstner-ocean-waves'] = inst;
}

const instance = window.__art_instances['gerstner-ocean-waves'];
if (instance && instance.render) {
  instance.render(
    { ctx, width, height, dpr: 1, aspectRatio: width / height },
    { time, deltaTime: dt, frameCount: Math.floor(time * 60), fps: 60 },
    defaultParams
  );
}
Edit in Interactive Playground Zero Dependencies • Standalone Canvas 2D
ƒ

Mathematical Formulation

medium
Analytical Equation
x=x0i=1NkikiQiAisin(kix0ωit),y=y0+i=1NAicos(kix0ωit)\mathbf{x} = \mathbf{x}_0 - \sum_{i=1}^{N} \frac{\mathbf{k}_i}{k_i} Q_i A_i \sin(\mathbf{k}_i \cdot \mathbf{x}_0 - \omega_i t), \quad y = y_0 + \sum_{i=1}^{N} A_i \cos(\mathbf{k}_i \cdot \mathbf{x}_0 - \omega_i t)
Click to expand
Compact Formula
x = x0 - (dx/k)*Q*sin(phase), y = y0 - A*cos(phase), phase = k*(dx*x0 + dy*y0) - ωt

Mathematical Tags

#ocean #gerstner #waves #hydrodynamics #nature #water #physics
Author: Math Art Core Target: 60 FPS

Export & Embed: Gerstner Ocean Waves

4K PNG Snapshot

High-resolution single frame render

WebM Video (5s Loop)

60 FPS browser-captured stream

Standalone JS Script

Complete executable Canvas 2D algorithm

HTML Iframe Embed

<iframe src="https://art.fazleyrabbi.xyz/embed/gerstner-ocean-waves" width="500" height="500" frameborder="0" loading="lazy"></iframe>
ESC
↑↓ Navigate Select
110 Mathematical Artworks
Made by Fazley Rabbi

Support the Project

Keep mathematical creative coding alive & open source

Or via Direct Payoneer ($0 Fee)
Payoneer Customer ID: $0 Fee Direct
24076084

💡 Payoneer app: Go to Pay → Pay to recipient → Enter ID 24076084.

Thank you for supporting generative mathematical animations! ✨