(function() {
  // noprotect;
  var BLUR, CX, CY, MAX_D, R, canvas_left, canvas_right, ctx_left, ctx_right, cx_tool, cy_tool, df, dist, dist_tool, edit, height, pixel_x, pixel_y, r_tool, redraw, side, svg, tool, width;

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

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

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

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

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

  ctx_left = canvas_left.node().getContext('2d');

  ctx_right = canvas_right.node().getContext('2d');

  /* define the distance function for the original circle
  */


  CX = 0.5;

  CY = 0.5;

  R = 0.25;

  dist = function(x, y) {
    return R - (Math.pow(x - CX, 2) + Math.pow(y - CY, 2)) / R;
  };

  /* compute the field
  */


  df = (function() {
    var _i, _results;

    _results = [];
    for (pixel_x = _i = 0; 0 <= side ? _i < side : _i > side; pixel_x = 0 <= side ? ++_i : --_i) {
      _results.push((function() {
        var _j, _results1;

        _results1 = [];
        for (pixel_y = _j = 0; 0 <= side ? _j < side : _j > side; pixel_y = 0 <= side ? ++_j : --_j) {
          _results1.push(dist(pixel_x / side, pixel_y / side));
        }
        return _results1;
      })());
    }
    return _results;
  })();

  /* edit tool
  */


  svg = d3.select('svg');

  cx_tool = 0;

  cy_tool = 0;

  r_tool = 0.125;

  dist_tool = function(x, y) {
    return r_tool - (Math.pow(x - cx_tool, 2) + Math.pow(y - cy_tool, 2)) / r_tool;
  };

  tool = svg.append('circle').attr({
    id: 'tool',
    r: r_tool * side
  });

  svg.on('mousemove', function() {
    var x, y, _ref, _ref1;

    _ref = d3.mouse(this), x = _ref[0], y = _ref[1];
    _ref1 = [x / side, y / side], cx_tool = _ref1[0], cy_tool = _ref1[1];
    return tool.attr({
      cx: x + 0.5,
      cy: y + 0.5
    });
  });

  svg.on('click', function() {
    return edit('union');
  });

  svg.on('contextmenu', function() {
    edit('sub');
    return d3.event.preventDefault();
  });

  svg.on('mousewheel', function() {
    if (d3.event.wheelDelta > 0) {
      r_tool *= 1.2;
    } else {
      r_tool /= 1.2;
    }
    return tool.attr({
      r: r_tool * side
    });
  });

  edit = function(op) {
    var _i, _j;

    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) {
        if (op === 'union') {
          df[pixel_x][pixel_y] = Math.max(df[pixel_x][pixel_y], dist_tool(pixel_x / side, pixel_y / side));
        } else if (op === 'intersection') {
          df[pixel_x][pixel_y] = Math.min(df[pixel_x][pixel_y], dist_tool(pixel_x / side, pixel_y / side));
        } else if (op === 'sub') {
          df[pixel_x][pixel_y] = Math.min(df[pixel_x][pixel_y], -dist_tool(pixel_x / side, pixel_y / side));
        }
      }
    }
    return window.requestAnimationFrame(function() {
      return redraw();
    });
  };

  MAX_D = Math.sqrt(2) / 4;

  BLUR = 3;

  redraw = function() {
    /* Draw the distance field...
    */

    var Fxy, a, b, g, image_left, image_right, pixel_i, r, value, _i, _j, _ref;

    image_left = ctx_left.createImageData(side, side);
    /* ...and the reconstructed shape
    */

    image_right = ctx_right.createImageData(side, side);
    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];
        Fxy = df[pixel_x][pixel_y];
        image_left.data[r] = -Fxy / MAX_D * 255;
        image_left.data[g] = 0;
        image_left.data[b] = Fxy / MAX_D * 255;
        image_left.data[a] = 255;
        value = Math.min(1 + Fxy / (BLUR / side), 1);
        image_right.data[r] = 255;
        image_right.data[g] = 255;
        image_right.data[b] = 255;
        image_right.data[a] = value * 255;
      }
    }
    ctx_left.putImageData(image_left, (width - side) / 2, (height - side) / 2);
    return ctx_right.putImageData(image_right, (width - side) / 2, (height - side) / 2);
  };

  redraw();

}).call(this);