Source: Point.js

/**
 * Represents a point
 *
 * @alias Point
 * @constructor
 */
function Point(x,y) {
    this.x = x;
    this.y = y;
}

/**
 * Returns a clone of this point
 * @return {Point} a clone of this point
 */
Point.prototype.clone = function(){
    return new Point(this.x, this.y);
}

/**
 * Reverses this point (x,y) -> (-x,-y)
 * @return {Point} this for chaining
 */
Point.prototype.reverse = function(){
    return Point.scale(this, -1);
}

/**
 * Returns the Euclidian length auf this point
 * @return {number} the length
 */
Point.prototype.len = function(){
    return Math.sqrt(this.x*this.x + this.y*this.y);
}

/**
 * Scales this Point
 * @return {Point} this for chaining
 */
Point.prototype.scale = function(scale){
    this.x = this.x * scale;
    this.y = this.y * scale;
    return this; //For chaining
}

/**
 * Normalizes this point (when interpreted as 2D vector)
 * @return {Point} this for chaining
 */
Point.prototype.normalize = function(){
    var len = this.len();
    if (len == 0) return;
    this.scale(1.0/len);
	return this;
}

/**
 * Rotates this arrow by phi radians
 * @param {number} phi angle in radians
 * @return {Point} this for chaining
 */
Point.prototype.rotate = function(phi){
	var x = this.x;
	var y = this.y;

	this.x = x * Math.cos(phi) - y * Math.sin(phi);
	this.y = x * Math.sin(phi) + y * Math.cos(phi);
	return this;
}

/**
 * Returns this arrow as SATVector represenation
 * @return {SAT.Vector} this as SAT Vector
 */
Point.prototype.toSATVector = function(){
    return new SAT.Vector(this.x, this.y);
}

/**
 * Adds two points
 * @static
 * @param {Point} p1 Point 1
 * @param {Point} p2 Point 2
 * @return {Point} p1 + p2
 */
Point.add = function(p1, p2){
    return new Point(p1.x+p2.x, p1.y+p2.y);
}

/**
 * Subtracts one point of another
 * @static
 * @param {Point} p1 Point 1
 * @param {Point} p2 Point to be substracted
 * @return {Point} p1 - p2
 */
Point.sub = function(p1, p2){
    return new Point(p1.x-p2.x, p1.y-p2.y);
}

/**
 * Scales a point by a scalar value
 * @static
 * @param {Point} point The point
 * @param {number} scale The value for scaling
 * @param {number} [scaley] The value for scaling in y
 * @return {Point} point*scale
 */
Point.scale = function(point, scale, scaley){
    scaley = scaley || scale;
    return new Point(point.x*scale, point.y*scaley);
}

/**
 * Interpolates two points
 * @param {Point} p1 Point 1
 * @param {Point} p2 Point 2
 * @param {number} [amount] the influence of the secound point, default: 0.5
 * @return {Point} p1*(1-amount) + p2*amount;
 */
Point.interpolate = function(p1, p2, amount){
    var t = amount || 0.5;
    return Point.add(Point.scale(p1,1-t),Point.scale(p2,t));
}

/**
 * Returns the angle between two points (interpreted as Vector)
 * @param {Point} p1 Point 1
 * @param {Point} p2 Point 2
 * @return {number} Angle between points in radians
 */
Point.angle = function(p1, p2){
	p1c = p1.clone().normalize();
	p2c = p2.clone().normalize();

	p1p2dot = p1c.x * p2c.x + p1c.y * p2c.y;

	return Math.acos(p1p2dot / (p1c.len() * p2c.len()));
}