function sqr(x){ return x * x; }

function circle_intersection(x, y){
    if(this.minX <= x && this.maxX){
	    return sqr(Math.abs(this.x - x)) + sqr(Math.abs(this.y - y)) <= sqr(this.rad);
    }return false;
}
    
function Circle(x, y, rad){
    this.x = x;
    this.y = y;
    this.rad = rad;
    this.minX = x - rad;
    this.maxX = x + rad;
    this.minY = y - rad;
    this.maxY = y + rad;
    
    this.intersects = circle_intersection;
}

function is_between(val, minVal, maxVal){ return minVal < val && maxVal >= val; }

function poly_intersection(x, y){
  return poly_interior_intersection(this.points, x, y); 
}

function poly_edge_intersection(points, x, y){
    var prevPoint = points[points.length - 1];
    for(var i = 0; i < points.length; i++){
      var curPoint = points[i];
      var slope = (curPoint[1] - prevPoint[1])/(curPoint[0] - prevPoint[0]);
      var yForXOnEdge = (x - prevPoint[0]) * slope + prevPoint[1];
      if(yForXOnEdge == y){ return true; }
      prevPoint = curPoint;
    }
    return false;
}

function poly_interior_intersection(points, x, y){
    var j = 0;
    var oddNodes = false;
    for(var i = 0; i < points.length; i++){
      j++; 
      if(j == points.length){
        j = 0;
      }
      var yOfJ = points[j][1];
      var yOfI = points[i][1];
      if(is_between(y, yOfJ, yOfI) || is_between(y, yOfI, yOfJ)){
          var xOfI = points[i][0];
          var xOfJ = points[j][0];
          if(xOfI + (y - yOfI)/(yOfJ - yOfI) * (xOfJ-xOfI) < x){
              oddNodes = !oddNodes;
          }
      }
    }
    return oddNodes
}

function rect_intersection(x, y){
    var points = this.points;
    return is_between(x, points[0], points[0] + points[2]) &&
           is_between(y, points[1], points[1] + points[3]);
}

function Poly(points){
  this.points = points;
  
  this.intersects = poly_intersection;
}

function Rect(points){
	this.points = points
	
	this.intersects = rect_intersection;
}
