/*
Helper methods for Geometry and collision detection.
*/
var Geometry = (function(){
  var g = {};



  // rotates point p (in format [x, y]) counterclockwise by angle.
  // does not mutate point.
  var rotatePoint = function(p, angle){
    var x = p[0], y = p[1];
    var q = [x, y];
    
    /*
     To rotate x, y by A,
     x' = x*cos(A) - y*sin(A)
     y' = x*sin(A) + y*cos(A)
    */
    var c = Math.cos(angle);
    var s = Math.sin(-angle);
    q[0] = x * c - y * s; // x'
    q[1] = x * s + y * c; // y'
    
    return q;
  };



  // translates point p by dx and dy.
  // does not mutate point.
  var translatePoint = function(p, dx, dy){
    return [p[0] + dx, p[1] + dy];
  };



  /*
   Determines whether p3 lies to the left (ccw) of line p1, p2.
   Each point (p1, p2, p3) is an array [x, y].
   
   Returns > 0 if p3 lies to the left,
       = 0 if p3 is colinear,
       < 0 if p3 lies to the right.
  */
  var ccw = function(p1, p2, p3){
    return (p2[0] - p1[0]) * (p3[1] - p1[1]) - (p2[1] - p1[1]) * (p3[0] - p1[0]);
  };



  /*
   Determines whether two finite length lines intersect.
   Each line is an array of points, [p1, p2].
   
   Returns true if they intersect, false otherwise.
  */
  var linesIntersect = function(l1, l2){
    var p1 = l1[0], p2 = l1[1];
    var p3 = l2[0], p4 = l2[1];
    return ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
           ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0;
  };



  /*
   Determines whether two polygons intersect.
   Brute algorithm, determine whether any lines intersect.
   
   Each polygon is expected to be an array of points. Polygons are
   assumed to not self-intersect.
   
   Time complexity O(mn), for number of vertices m and n.
  */
  var polygonsIntersect = function(poly1, poly2){
    var n = poly1.length;
    for(var i = 0; i < poly1.length; i++){
      var line1 = [poly1[i], poly1[(i + 1) % n]];
      
      if(linePolygonIntersect(line1, poly2)){
        return true;
      }
    }
    
    return false;
  };



  var linePolygonIntersect = function(line, poly){
    var n = poly.length;
    for(var i = 0; i < poly.length; i++){
      line2 = [poly[i], poly[(i + 1) % n]];
      
      if(linesIntersect(line, line2)){
        return true;
      }
    }
    
    return false;
  }



  g.rotatePoint = rotatePoint;
  g.translatePoint = translatePoint;
  g.ccw = ccw;
  g.linesIntersect = linesIntersect;
  g.linePolygonIntersect = linePolygonIntersect;
  g.polygonsIntersect = polygonsIntersect;

  return g;
}());






global.Geometry = Geometry;