text: function setup() {
    createCanvas(windowWidth, windowHeight);
    enableVectorArguments();
  }
  
  function draw() {
    background(220, 220, 255);
  
    translate(width / 2, height / 2);
    rotate(-PI / 2);
  
    let ratio = 5 * sin(millis() / 8000);
  
    rotate(radians(millis() / 100));
    rot = 0;
    pattern('blue');
  
    rotate(sin(millis() / 2000) / 50);
    pattern('red');
  
    function pattern(c) {
      stroke(c);
      for (let angle = 0; angle < 180; angle += 2) {
        let p1 = pointAlongRect(radians(ratio * angle), map(angle, 0, 180, 200, 100));
        let p2 = pointAlongRect(radians(angle), map(angle, 0, 180, 100, 200));
        fill(c);
        circle(p1, 3);
        noFill();
        circle(p2, 5);
        line(p1, p2);
      }
    }
  }
  
  // These are spaced evenly by angle not distance
  function pointAlongRect(angle, radius) {
    let pt = p5.Vector.fromAngle(angle);
    let { x, y } = pt;
    return pt.mult(radius / (abs(x) > abs(y) ? abs(x) : abs(y)));
  }
  
  const sign = n => (n > 0) - (n < 0);
  