In case anybody is interested:
I created a collection of helper functions to do vectore computations some time ago.
Those functions operator on generic objects with "x" and "y" member. Event if the object does not contain any of those members, they simply assume the value 0.
Most functions have the option to generate a new object or modify one of the given vectors.
The way those methods are used is not the most convenient (there are not nice to chain), however, there are two advantages:
1. They can be efficently inlined using closure compiler(or rather a variant of closure compiler that supports forced inline:
https://github.com/bramstein/closure-compiler-inline )
2. They are not bound to any vector class and can be applied to generic objects, things you usually get from assets (in JSON format) etc.
Anyway, here's the code:
// Vector tools
var Vec2 = {};
/**
* @inline
* @param otherVec
*/
Vec2.create = function(otherVec){
var res = {};
res.x = (otherVec && otherVec.x || 0);
res.y = (otherVec && otherVec.y || 0);
return res;
};
/**
* @inline
* @param x
* @param y
*/
Vec2.createC = function(x,y){
var res = {};
res.x = (x || 0);
res.y = (y || 0);
return res;
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.assign = function(v1, v2){
v1.x = (v2.x || 0);
v1.y = (v2.y || 0);
return v1;
};
/**
* @inline
* @param v
* @param x
* @param y
*/
Vec2.assignC = function(v, x, y){
v.x = (x || 0);
v.y = (y || 0);
return v;
};
/**
* @inline
* @param v1
* @param v2
* @param {boolean=} copy
*/
Vec2.add = function(v1, v2, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0) + (v2.x || 0);
res.y = (v1.y || 0) + (v2.y || 0);
return res;
};
/**
* @inline
* @param v1
* @param x
* @param y
* @param {boolean=} copy
*/
Vec2.addC = function(v1, x, y, copy){
var res = copy || false ? {} : v1;
y = y === undefined || y === null ? x: y;
res.x = (v1.x || 0) + (x || 0);
res.y = (v1.y || 0) + (y || 0);
return res;
};
/**
* @inline
* @param v1
* @param v2
* @param {boolean=} copy
*/
Vec2.sub = function(v1, v2, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0) - (v2.x || 0);
res.y = (v1.y || 0) - (v2.y || 0);
return res;
};
/**
* @inline
* @param v1
* @param x
* @param y
* @param {boolean=} copy
*/
Vec2.subC = function(v1, x, y, copy){
var res = copy ? {} : v1;
y = y === undefined || y === null ? x: y;
res.x = (v1.x || 0) - (x || 0);
res.y = (v1.y || 0) - (y || 0);
return res;
};
/**
* @inline
* @param v1
* @param v2
* @param {boolean=} copy
*/
Vec2.mul = function(v1, v2, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0) * (v2.x || 0);
res.y = (v1.y || 0) * (v2.y || 0);
return res;
};
/**
* @inline
* @param v1
* @param x
* @param y
* @param {boolean=} copy
*/
Vec2.mulC = function(v1, x, y, copy){
var res = copy || false ? {} : v1;
y = y === undefined || y === null ? x: y;
res.x = (v1.x || 0) * (x || 0);
res.y = (v1.y || 0) * (y || 0);
return res;
};
/**
* @inline
* @param v1
* @param f
* @param {boolean=} copy
*/
Vec2.mulF = function(v1, f, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0) * (f || 0);
res.y = (v1.y || 0) * (f || 0);
return res;
};
/**
* @inline
* @param v1
* @param v2
* @param {boolean=} copy
*/
Vec2.div = function(v1, v2, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0) / (v2.x || 0);
res.y = (v1.y || 0) / (v2.y || 0);
return res;
};
/**
* @inline
* @param v1
* @param x
* @param y
* @param {boolean=} copy
*/
Vec2.divC = function(v1, x, y, copy){
var res = copy || false ? {} : v1;
y = y === undefined || y === null ? x: y;
res.x = (v1.x || 0) / (x || 0);
res.y = (v1.y || 0) / (y || 0);
return res;
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.dot = function(v1, v2){
return (v1.x || 0)* (v2.x || 0) + (v1.y || 0)*(v2.y || 0);
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.dotR = function(v1, v2){
return -(v1.y || 0) * (v2.x || 0) + (v1.x || 0) * (v2.y || 0);
};
/**
* @inline
* @param v
* @param newLength
* @param {boolean=} copy
*/
Vec2.length = function(v, newLength, copy){
var oldLength = Math.sqrt((v.x || 0)*(v.x || 0) + (v.y || 0)* (v.y || 0));
if(newLength){
return Vec2.mulC(v, oldLength ? newLength / oldLength : 1, null, copy);
}
else
return oldLength;
};
/**
* @inline
* @param v
* @param min
* @param max
* @param {boolean=} copy
*/
Vec2.limit = function(v, min, max, copy){
var length = Vec2.length(v);
if(length > max){
return Vec2.mulC(v, max / length, null, copy);
}
else if(length < min){
return Vec2.mulC(v, min / length, null, copy);
}
else{
return copy || false ? Vec2.create(v) : v;
}
};
/**
* @inline
* @param v
* @param {boolean=} copy
*/
Vec2.normalize = function(v, copy){
return Vec2.length(v, 1, copy);
};
/**
* @inline
* @param v
*/
Vec2.clockangle = function(v){
var result = Math.acos(-(v.y || 0) / Vec2.length(v) );
if(v.x < 0) result = 2*Math.PI - result;
return result || 0;
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.angle = function(v1, v2)
{
var result = Math.acos( Vec2.dot(v1,v2) / ( Vec2.length(v1)*Vec2.length(v2) ));
return result || 0;
};
/**
* @inline
* @param v
* @param angle
* @param {boolean=} copy
*/
Vec2.rotate = function(v, angle, copy){
var res = copy || false ? {} : v;
var x = v.x || 0;
res.x = Math.cos(angle) * x + Math.sin(angle) * (v.y || 0);
res.y = Math.sin(-angle) * x + Math.cos(angle) * (v.y || 0);
return res;
};
/**
* @inline
* @param v
* @param {boolean=} copy
*/
Vec2.rotate90CW = function(v, copy)
{
var res = copy || false ? {} : v;
var x = (v.x || 0);
res.x = (v.y || 0);
res.y = -x ;
return res;
};
/**
* @inline
* @param v
* @param {boolean=} copy
*/
Vec2.rotate90CCW = function(v, copy)
{
var res = copy || false ? {} : v;
var x = (v.x || 0);
res.x = -(v.y || 0);
res.y = x;
return res;
};
/**
* @inline
* @param v
* @param {boolean=} copy
*/
Vec2.flip = function(v, copy){
var res = copy || false ? {} : v;
res.x = -v.x;
res.y = -v.y;
return res;
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.equal = function(v1,v2){
return v1.x == v2.x && v1.y == v2.y;
};
/**
* @inline
* @param v1
* @param v2
*/
Vec2.distance = function(v1,v2){
var x = ((v1.x - v2.x) || 0);
var y = ((v1.y - v2.y) || 0);
return Math.sqrt( x * x + y * y);
};
/**
* @inline
* @param v1
* @param v2
* @param i
* @param {boolean=} copy
*/
Vec2.lerp = function(v1,v2, i, copy){
var res = copy || false ? {} : v1;
res.x = (v1.x || 0)*(1-i) + (v2.x || 0)*i;
res.y = (v1.y || 0)*(1-i) + (v2.y || 0)*i;
return res;
}