(function() {
  // noprotect;
  /* BEGIN
  */

  var BLUR, CX1, CX2, CY1, CY2, Fxy, MAX_D, R1, R2, a, b, canvas, color, colorize_inner, colorize_outer, ctx, dist1, dist2, g, hcl_linear_rainbow, height, image, pixel_i, pixel_x, pixel_y, r, side, value, width, x, y, _i, _j, _k, _l, _ref, _ref1, _ref2, _ref3;

  hcl_linear_rainbow = function() {
    var chroma_range, domain, hue_range, luminance_range, scale;

    domain = [0, 1];
    hue_range = [340, 340 - 480];
    chroma_range = [0, 40];
    luminance_range = [0, 100];
    scale = function(x) {
      var c, ext, h, l, xn;

      ext = domain[1] - domain[0];
      xn = (x - domain[0]) / ext;
      h = hue_range[0] + (hue_range[1] - hue_range[0]) * xn;
      c = chroma_range[0] + (chroma_range[1] - chroma_range[0]) * (1 - Math.pow(1 - 2 * xn, 2));
      l = luminance_range[0] + (luminance_range[1] - luminance_range[0]) * xn;
      h = Math.max(Math.min(h, d3.max(hue_range)), d3.min(hue_range));
      c = Math.max(Math.min(c, d3.max(chroma_range)), d3.min(chroma_range));
      l = Math.max(Math.min(l, d3.max(luminance_range)), d3.min(luminance_range));
      return d3.hcl(h, c, l);
    };
    scale.domain = function(x) {
      if (!arguments.length) {
        return domain;
      }
      domain = x;
      return scale;
    };
    scale.hue_range = function(x) {
      if (!arguments.length) {
        return hue_range;
      }
      hue_range = x;
      return scale;
    };
    scale.chroma_range = function(x) {
      if (!arguments.length) {
        return chroma_range;
      }
      chroma_range = x;
      return scale;
    };
    scale.luminance_range = function(x) {
      if (!arguments.length) {
        return luminance_range;
      }
      luminance_range = x;
      return scale;
    };
    return scale;
  };

  /* END
  */


  /* define the distance function for two circles
  */


  CX1 = 0.5;

  CY1 = 0.5;

  R1 = 0.25;

  dist1 = function(x, y) {
    return R1 - (Math.pow(x - CX1, 2) + Math.pow(y - CY1, 2)) / R1;
  };

  CX2 = 0.5;

  CY2 = 0.5;

  R2 = 0.4;

  dist2 = function(x, y) {
    return R2 - (Math.pow(x - CX2, 2) + Math.pow(y - CY2, 2)) / R2;
  };

  /* Draw the distance function
  */


  canvas = d3.select('#left');

  width = canvas.node().getBoundingClientRect().width;

  height = canvas.node().getBoundingClientRect().height;

  side = Math.min(width, height) - 20;

  ctx = canvas.node().getContext('2d');

  image = ctx.createImageData(side, side);

  /* define a default cubehelix-style hcl linear rainbow scale
  */


  MAX_D = Math.sqrt(2) / 4;

  colorize_inner = hcl_linear_rainbow().domain([MAX_D, 0]).hue_range([200, 200 + 90]);

  colorize_outer = hcl_linear_rainbow().domain([-MAX_D, 0]).hue_range([200 - 180, 200 - 180 + 90]);

  console.debug('Coloring...');

  for (pixel_x = _i = 0; 0 <= side ? _i < side : _i > side; pixel_x = 0 <= side ? ++_i : --_i) {
    for (pixel_y = _j = 0; 0 <= side ? _j < side : _j > side; pixel_y = 0 <= side ? ++_j : --_j) {
      pixel_i = (pixel_y * side + pixel_x) * 4;
      _ref = [pixel_i + 0, pixel_i + 1, pixel_i + 2, pixel_i + 3], r = _ref[0], g = _ref[1], b = _ref[2], a = _ref[3];
      _ref1 = [pixel_x / side, pixel_y / side], x = _ref1[0], y = _ref1[1];
      Fxy = Math.min(dist1(x, y), -dist2(x, y));
      if (Fxy > 0) {
        color = d3.rgb(colorize_inner(Fxy));
      } else {
        color = d3.rgb(colorize_outer(Fxy));
      }
      image.data[r] = color.r;
      image.data[g] = color.g;
      image.data[b] = color.b;
      image.data[a] = 255;
    }
  }

  ctx.putImageData(image, (width - side) / 2, (height - side) / 2);

  /* Draw the reconstructed shape
  */


  canvas = d3.select('#right');

  width = canvas.node().getBoundingClientRect().width;

  height = canvas.node().getBoundingClientRect().height;

  side = Math.min(width, height) - 20;

  ctx = canvas.node().getContext('2d');

  image = ctx.createImageData(side, side);

  BLUR = 3;

  for (pixel_x = _k = 0; 0 <= side ? _k < side : _k > side; pixel_x = 0 <= side ? ++_k : --_k) {
    for (pixel_y = _l = 0; 0 <= side ? _l < side : _l > side; pixel_y = 0 <= side ? ++_l : --_l) {
      pixel_i = (pixel_y * side + pixel_x) * 4;
      _ref2 = [pixel_i + 0, pixel_i + 1, pixel_i + 2, pixel_i + 3], r = _ref2[0], g = _ref2[1], b = _ref2[2], a = _ref2[3];
      _ref3 = [pixel_x / side, pixel_y / side], x = _ref3[0], y = _ref3[1];
      Fxy = Math.min(dist1(x, y), -dist2(x, y));
      value = Math.min(1 + Fxy / (BLUR / side), 1);
      image.data[r] = 255;
      image.data[g] = 255;
      image.data[b] = 255;
      image.data[a] = value * 255;
    }
  }

  ctx.putImageData(image, (width - side) / 2, (height - side) / 2);

}).call(this);