openprocessing_p5js · PolarCurves
Mathematical Rose (Rhodonea) Patterns
Overlay of multiple rose (rhodonea) curves in the canonical polar form r = a * cos((n/d) * theta + phase), parametrised by the rational multiplier k = n/d. Several curves with different (n, d, scale, phase) are layered onto the same canvas, each in its own hue. step(n) advances the per-curve phase, slowly rotating the petals.
Original: https://thecodingtrain.com/challenges/55-mathematical-rose-patterns/
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
x = scale * cos(n/d * theta + phase) * cos(theta); y = scale * sin(n/d * theta + phase) * sin(theta). Ploidy: k odd -> k petals, k even -> 2k petals. With irrational k the curve is dense in the disk and never closes (Wikipedia, Rhodonea curve).
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 512 | 200–1200 | Square canvas side length. |
num_curves | int | 9 | 1–24 | Number of overlaid rose curves. |
samples | int | 1200 | 200–6000 | Sample count per curve (closed polyline vertices). |
radius | float | 215 | 30–600 | Base radius in pixels. |
phase_step | float | 0.012 | 0–0.2 | Per-tick phase increment (radians) per curve. |
bg_color | tuple | 8,10,24 | — | Background canvas color. |
seed | int | null | 0–999999 |
Reference
First 60 lines of reference.py. Full source:
library_external/openprocessing_p5js/PolarCurves/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
def _rose_xy(
theta: np.ndarray, n: int, d: int, scale: float, phase: float
) -> tuple[np.ndarray, np.ndarray]:
"""Rhodonea / rose curve sampled at ``theta``.
x = scale * cos(n/d * theta + phase) * cos(theta)
y = scale * sin(n/d * theta + phase) * sin(theta)
Petal count:
n/d = k rational:
- k odd -> k petals
- k even -> 2*k petals
- k integer -> 2*k petals (closes after one revolution)
"""
k = n / d
r = np.cos(k * theta + phase)
x = scale * r * np.cos(theta)
y = scale * r * np.sin(theta)
return x, y
class PolarCurves:
"""Overlay of multiple rose (rhodonea) curves in the canonical polar form.
This is the classic *Coding Train* Mathematical Rose Patterns sketch
(challenge #55, <https://thecodingtrain.com/challenges/55-mathematical-rose-patterns/>)
and a long-running OpenProcessing favourite. The signature identity is the
polar equation ``r = a + b * cos((n/d) * theta + phase)``, parametrised by
a slider-controlled ``k = n / d`` and rendered as a closed polyline.
Several curves with different ``(n, d, scale, phase)`` are layered onto the
same canvas, each in its own hue. ``step(n)`` advances the per-curve phase
by ``phase_step`` ticks, slowly rotating the petals. ``reset()`` re-seeds
the phase schedule. ``render()`` rasterises all curves into the running
canvas and returns it as ``H x W x 3`` uint8.
"""
family: ClassVar[str] = "openprocessing_p5js"
sketch: ClassVar[str] = "polarCurves"
def __init__(
self,
dim: int = 512,
num_curves: int = 9,
samples: int = 1200,
radius: float | None = None,
phase_step: float = 0.012,
bg_color: tuple[int, int, int] = (8, 10, 24),
seed: int | None = None,
) -> None:
self.dim = dim
self.num_curves = num_curves
self.samples = samples Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/openprocessing_p5js/PolarCurves/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from openprocessing · p5.js
Additive Synthesis Waveform Visualisation
openprocessing_p5js · SoundWaveform
Visualisation of additive synthesis: y(t) = A * sum_{i=0..N-1} a_i * sin(2π f_i t + phi_i).
Inverse-distance Attractor Network
openprocessing_p5js · AttractorNetwork
A population of point-agents, each carrying a position and a velocity, mutually attracted by an inverse-distance force F = G / max(d, d_min)^alpha along the displacement vector.
Kaleidoscope Mirror Mandala
openprocessing_p5js · KaleidoscopeMirror
Draws a single wandering line and reflects it across N rotational mirrors around the canvas centre.
Poincaré Disk Hyperbolic Tessellation
openprocessing_p5js · HyperbolicTiling
Escher-style regular hyperbolic tessellation in the Poincaré disk.
Tron Lightcycle Trails
openprocessing_p5js · TronLightcycle
Tron-style lightcycle trails.