<!-- A simple spiral-growing algorithm to make pretty images.
// Thanks to Darius Bacon for very helpful suggestions.
/* --><!DOCTYPE html><meta charset="utf-8" />
<title>spirals growing on a canvas</title>
<canvas width=512 height=512></canvas>
<script>
/**/
var cvs = document.getElementsByTagName('canvas')[0]
  , ctx = cvs.getContext('2d')
  , scale = 5
  , thickness = 1/128
  , ww = cvs.width*scale
  , hh = cvs.height*scale
  , pix = new Array(ww*hh)      // Booleans for which pixels are full
;

for (var ii = 0; ii < ww*hh; ii++) pix[ii] = false;
setInterval(addSpiral, 16.7);

// A thing I was originally thinking of but haven’t figured out how to
// do yet is, when reaching the spiral that ends the growth of the
// current one, adjust the spiral pitch (“slope”) and draw a different
// spiral from there to the same center point, but one that is
// *tangent* to the older spiral.

function addSpiral() {
  var cx = Math.floor(rand() * ww) // center
    , cy = Math.floor(rand() * hh)
    , θ = rand() * 2 * Math.PI
    , r = 1
    , slope = scale * Math.exp(2*(rand()+rand())) // Δr = slope * Δθ
    , spiral = []
    , neg = rand() > 0.5
  ;

  // Spiral outwards until we hit the edge of the canvas or another spiral.
  for (;;) {
    var xx = Math.round(cx + r * Math.cos(θ))
      , yy = Math.round(cy + r * Math.sin(θ))
    ;
    if (xx <= 0) break;
    if (xx >= ww-1) break;
    if (yy <= 0) break;
    if (yy >= hh-1) break;
    if (pix[yy*ww + xx]) break; // We hit another spiral.
    spiral.push([xx, yy, r*thickness]); // Postpone drawing to avoid false 
collisions.

    // If we add 1/r radians, we should move one pixel tangentially,
    // right?  Just in case, we’ll go for half that.  Or,
    // alternatively, we’ll go for half a pixel of increased radius.
    var Δθ = 1/r/2
      , Δr = slope * Δθ
    ;
    if (Δr > 0.5) {
      Δr = 0.5;
      Δθ = Δr / slope;
    }
    if (neg) Δθ = -Δθ;

    r += Δr;
    θ += Δθ;
  }

  for (var ii = 0; ii < spiral.length; ii++) {
    var xx = spiral[ii][0]
      , yy = spiral[ii][1]
      , dd = Math.max(1, spiral[ii][2])
    ;
    pix[yy*ww + xx] = true;
    ctx.fillRect(xx/scale, yy/scale, dd/scale, dd/scale);
  }
}

function rand() { return Math.random(); }

// </script>
-- 
To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-hacks

Reply via email to