Techniques for Exploring Parameter Spaces
A parameter is a number you can change without rewriting the drawing rule. Find a curve you like, capture its ratio, then reuse that value in code.
Saved for reuse (initial example: ratio = 1.00)
let ratio = 1.00; Complete saved sketch (p5.js)
let ratio = 1.00;
function setup() {
createCanvas(480, 360);
angleMode(DEGREES);
noLoop();
}
function draw() {
background(250);
noFill();
stroke(36, 94, 148);
strokeWeight(2);
beginShape();
const r = min(width, height) * 0.42;
for (let angle = 0; angle <= 720; angle += 0.5) {
const x = width / 2 + r * sin(angle);
const y = height / 2 + r * cos(ratio * angle);
vertex(x, y);
}
endShape();
} Find a value
The drawing is built from sin() and cos(), the same pair that produces a circle. The ratio counts vertical oscillations per horizontal oscillation. At ratio 1 the two motions keep pace and the trace is a circle. At ratio ½ the vertical motion runs at half speed; at ratio 1½ it runs one and a half times as fast. The explorer sweeps ratios from 0.2 to 5.
Connecting a parameter to the pointer like this is called yoking it: the pointer position drives the value while you watch the result, and you read the number off when the drawing looks right.
The explorer sweeps two horizontal cycles. The presets ½, 1, and 1½ each complete a whole number of vertical cycles within those two horizontal cycles, so their traces close. Other ratios may leave an open segment where the trace ends before returning to its start.
These are Lissajous curves, made by combining horizontal and vertical oscillations.
Capture and reuse
The explorer separates the value you are exploring from the value you have decided to keep:
- Find. Move the slider, drag across the drawing, or press a preset until the shape looks right.
- Capture. Press Capture current value. This freezes the current value into the saved declaration next to the button. Further exploring updates the live drawing and readout, but the saved declaration stays fixed. Capture again to replace it.
- Reuse. Press Copy saved sketch and paste the result into the p5.js editor, or copy just the number into your own code.
In your own p5.js sketch, declare let ratio; outside draw(). Inside draw(), before drawing, assign ratio = map(mouseX, 0, width, 0.2, 5); so it follows the pointer each frame. If you start with the saved sketch above, remove noLoop() while exploring.
Once you have captured a number you like, remove the assignment from draw() and initialize the outer declaration with your saved value, for example let ratio = 1.50;. The ratio then stays fixed, with no mouse dependency. If you removed noLoop(), restore it in setup() so the sketch draws once.
The range 0.2 to 5 is a one-dimensional parameter space: each point on that interval is one possible drawing, and exploring means moving along the line.
Print the value from your own sketch
Another way to read a value out of a yoked sketch is to print it. Add this handler to a p5 sketch that declares ratio outside draw():
function mousePressed() {
console.info(ratio);
}
Click the canvas to print the current ratio once. Printing inside draw() instead would flood the console with a new value every frame; a click handler logs deliberately, when you see a shape worth keeping.
Two parameters
Add a second parameter and the parameter space becomes two-dimensional. Phase is an angular offset, measured in degrees, that shifts where the vertical oscillation starts. Each setting is now a point (ratio, phase), and a drag across the pad changes two values at once: horizontal position sets the ratio, vertical position sets the phase.
Saved for reuse (initial example: ratio = 1.00, phase = 0°)
let ratio = 1.00;
let phase = 0; Complete saved sketch (p5.js)
let ratio = 1.00;
let phase = 0;
function setup() {
createCanvas(480, 360);
angleMode(DEGREES);
noLoop();
}
function draw() {
background(250);
noFill();
stroke(36, 94, 148);
strokeWeight(2);
beginShape();
const r = min(width, height) * 0.42;
for (let angle = 0; angle <= 720; angle += 0.5) {
const x = width / 2 + r * sin(angle);
const y = height / 2 + r * cos(ratio * angle + phase);
vertex(x, y);
}
endShape();
} Try it: keep the ratio fixed and drag straight up or down on the pad to change only the phase. Then drag diagonally and watch both readouts change at once. Capture and Copy work as before, but they save both numbers.