/*
 Copyright 2008 Conan Dalton.

 ellipse.js is free software: you can redistribute it and/or modify
 it under the terms of version 3 of the GNU Lesser General Public License as published by
 the Free Software Foundation

 ellipse.js is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
*/


/**
 * represent an ellipse
 * @param x origin of ellipse
 * @param y origin of ellipse
 * @param a small axis of ellipse
 * @param b large axis of ellipse
 * @param theta rotation of ellipse in radians
 */
var Ellipse = function(x, y, a, b, theta) {
  this.x = x;
  this.y = y;
  this.a = a;
  this.b = b;
  this.theta = theta;
};

/**
 * determines whether a point p,q is inside this ellipse
 * returns 1 if inside, 0 if outside
 * @param p x-coordinate of point to consider
 * @param q y-coordinate of point to consider
 */
Ellipse.prototype.inside = function(p, q) {
  var dx = (p - this.x) / this.a;
  var dy = (q - this.y) / this.b;
  var distance = dx * dx + dy * dy;
  return (distance < 1.0) ? 1 : 0;
};

/**
 * determines what proportion of a square (p,q) - (p+side, q+side) is covered by this
 * ellipse. If side < threshold, returns an approximate result.
 *
 * returns: a value in the range [0.0, 1.0]
 *
 * @param p x-coordinate of point to consider
 * @param q y-coordinate of point to consider
 * @param side the length of the edge of the square to sample
 * @param threshold do not recurse if side is less than this value
 */
Ellipse.prototype.insideness = function(p, q, side, threshold) {
  var i1 = this.inside(p, q);
  var i2 = this.inside(p + side, q);
  var i3 = this.inside(p + side, q + side);
  var i4 = this.inside(p, q + side);
  var total = i1 + i2 + i3 + i4;
  if (total == 4 || total == 0 || side < threshold) {
    return total / 4.0;
  }

  side = side / 2;
  var j1 = this.insideness(p, q, side, threshold);
  var j2 = this.insideness(p + side, q, side, threshold);
  var j3 = this.insideness(p + side, q + side, side, threshold);
  var j4 = this.insideness(p, q + side, side, threshold);
  return (j1 + j2 + j3 + j4) / 4.0;
};

Ellipse.prototype.draw = function(height, width) {
  var result = new Array();
  for (var i = 0; i < height; i++) {
    result[i] = new Array();
    for (var j = 0; j < width; j++) {
      result[i][j] = this.insideness(j, i, 1.0, 0.1);
    }
  }

  return result;
};

