buddhabrot-try1

an attempt to draw a buddhabrot without bunching points into pixels.

Slightly less 'haze' by ignoring the first few points generated by Mandelbrot iterations.

Log in to post a comment.

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(0.25);

// these are separated so that you can place more points per redraw.
// I am using a discrete sampling rather than a random one but maybe that's not a great idea?
// I like determinism in images though
const sqrt_iters = 3;
const lattice_size = 450;

const iters = sqrt_iters ** 2;

const nmax = 200;
function iterate(x0, y0, out){
  let x = x0, y = y0, limit = 2*nmax;
  for (let i = 0; i < limit; i += 2) {
    const xnew = x * x - y * y + x0;
    const ynew = 2 * x * y + y0;
    out[i] = x = xnew;
    out[i+1] = y = ynew;
    if (x*x + y*y > 10) {
      return i + 2;
    }
  }
  return -1;
}
const zoom_x = 300;
const zoom_y = 300;

const turtle = new Turtle();
// The walk function will be called until it returns false.
turtle.penup();

const grid = [];
for (let i = 0; i < lattice_size; i++) {
    for (let j = 0; j < lattice_size; j++) {
        grid.push(i/lattice_size - 0.5, j/lattice_size - 0.5);
    }
}

function walk(k) {
  if (k >= iters) {
    return false;
  }
  const i = k % sqrt_iters;
  const j = (k - i) / sqrt_iters;
  // we want to uniformly sample the box 0 < x,y < 1/lattice_size,
  // preferably not lining up on either edge. So first we transform {0, 1, 2, 3} to {0.5, 1.5, 2.5, 3.5}
  // and then we divide to {0.125, 0.375, 0.625, 0.875} and then we use this grid on [0, 1]^2 to hit
  // the smaller space. Then we shift to -0.5 so that this is not going to uniformly sample 
  const offset_x = ((i + 0.5) / sqrt_iters)/lattice_size;
  const offset_y = ((j + 0.5) / sqrt_iters)/lattice_size;
  
  for (let n = 0; n < grid.length; n += 2) {
    const x = 4*(grid[n] + offset_x);
    const y = 4*(grid[n + 1] + offset_y);
    const vals = [];
    const len = iterate(x, y, vals);
    for (let i = 4; i < len; i += 2) {
      const ix = 0.3 * zoom_x * (vals[i] + 0.5);
      const iy = 0.3 * zoom_y * vals[i+1];
      if (Math.max(ix, iy) < -100 || Math.min(ix, iy) > 100) {
        continue;
      }
      turtle.goto(iy, ix);
      turtle.pendown();
      turtle.forward(0.125);
      turtle.penup();
    }
  }
  console.log('iter', k + 1);
  return true
}