Have a heart! ❤️

Have a Heart

  // heart
  float x = 16 * pow(sin(angle), 3);
  float y = 13 * cos(angle)
          - 5 * cos(2 * angle)
          - 2 * cos(3 * angle)
          -     cos(4 * angle);
Code
// glv
// 2026-02-14
// Have a heart

void setup()
{
  size(600, 600);
  noStroke();
  frameRate(30);
}

void draw()
{
  background(0);
  translate(width/2, height/2);

  fill(255, 0, 0);
  sequence(2, 50);
  
  // Optional for creating animated gif
  //saveFrame("/data/line-######.png");
}

// framesPerStep: how many frames to wait before increasing the heart detail
// maxSteps: stop once stepIndex exceeds this value

void sequence(int framesPerStep, int maxSteps)
{
  int frameIndex = frameCount - 1;
  int stepIndex  = frameIndex / framesPerStep;  // advances every N frames
  println(stepIndex);

  makeHeart(stepIndex, 15);

  if (stepIndex > maxSteps)
  {
    makeHeart(150, 15);
    fill(255, 255, 0);
    textSize(60);
    textAlign(CENTER, CENTER);
    text("Happy Valentine's Day!", 0, -240);
    noLoop();
  }
}

void makeHeart(int sampleCount, int scale)
{
  beginShape();

  for (int sampleIndex = 0; sampleIndex < sampleCount - 1; sampleIndex++)
  {
    strokeWeight(2);

    PVector p = heartPoint(sampleCount, sampleIndex, scale);
    vertex(p.x, p.y);
  }
  endShape(CLOSE);
}

PVector heartPoint(int sampleCount, int sampleIndex, int scale)
{
  float angle = sampleIndex * (TAU / (sampleCount - 1));

  // heart
  float x = 16 * pow(sin(angle), 3);
  float y = 13 * cos(angle)
          - 5 * cos(2 * angle)
          - 2 * cos(3 * angle)
          -     cos(4 * angle);

  float xScaled =  scale * x;
  float yScaled = -scale * y;
  return new PVector(xScaled, yScaled);
}

Reference:
Valentine's Day - Wikipedia
Parametric equation - Wikipedia
Heart symbol - Wikipedia

:heart:

6 Likes