Heart Spiral
Nested hearts, each a little smaller and rotated a bit more than the last, spiraling inward.
Log in to post a comment.
// Turtletoy sketch: a heart, with a smaller heart nested inside the
// previous one, repeated `numHearts` times, rotating a bit more with
// each successive heart.
// Paste this directly into https://turtletoy.net
// The block below becomes sliders in the Turtletoy UI (Adjustable Variables).
Canvas.setpenopacity(1);
const turtle = new Turtle();
const numHearts = 100; // min=1, max=1000, step=1, how many nested hearts to draw
const startScale = 5.5; // min=1, max=15, step=.5, size of the outermost heart
const scaleStep = 0.985; // min=.8, max=.999, step=.001, each heart's size as a fraction of the last
const steps = 120; // min=10, max=100, step=10, points sampled per heart outline
const rotationStep = 4; // min=0, max=45, step=.5, degrees each successive heart rotates by
// Classic parametric heart curve.
function heartPoint(t, scale) {
const x = 16 * Math.pow(Math.sin(t), 3);
const y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
return [x * scale, -y * scale]; // flip y so the heart points up on screen
}
function rotate(x, y, degrees) {
const a = degrees * Math.PI / 180;
const c = Math.cos(a), s = Math.sin(a);
return [x * c - y * s, x * s + y * c];
}
function walk(i) {
const scale = startScale * Math.pow(scaleStep, i);
const angle = i * rotationStep;
for (let j = 0; j <= steps; j++) {
const t = (j / steps) * Math.PI * 2;
let [x, y] = heartPoint(t, scale);
[x, y] = rotate(x, y, angle);
if (j === 0) {
turtle.penup();
turtle.goto(x, y);
turtle.pendown();
} else {
turtle.goto(x, y);
}
}
return i < numHearts - 1; // keep going until we've drawn numHearts hearts
}