kld-affine
Advanced tools
Comparing version 2.0.4 to 2.1.0
24
index.js
@@ -0,5 +1,23 @@ | ||
/** | ||
* @module kld-affine | ||
*/ | ||
// expose classes | ||
exports.Point2D = require('./lib/Point2D'); | ||
exports.Vector2D = require('./lib/Vector2D'); | ||
exports.Matrix2D = require('./lib/Matrix2D'); | ||
/** | ||
* @namespace Point2D | ||
* @implements {module:Point2D~Point2D} | ||
*/ | ||
export {default as Point2D} from "./lib/Point2D.js"; | ||
/** | ||
* @namespace Vector2D | ||
* @implements {module:Vector2D~Vector2D} | ||
*/ | ||
export {default as Vector2D} from "./lib/Vector2D.js"; | ||
/** | ||
* @namespace Matrix2D | ||
* @implements {module:Matrix2D~Matrix2D} | ||
*/ | ||
export {default as Matrix2D} from "./lib/Matrix2D.js"; |
1105
lib/Matrix2D.js
/** | ||
* Matrix2D.js | ||
* | ||
* copyright 2001-2002, 2013, 2017 Kevin Lindsey | ||
* Matrix2D.js | ||
* @module Matrix2D | ||
* @copyright 2001-2019 Kevin Lindsey | ||
*/ | ||
function setReadonlyProperty(object, property, value) { | ||
Object.defineProperty(object, property, { | ||
value: value, | ||
writable: false, | ||
enumerable: true, | ||
configurable: false | ||
}); | ||
} | ||
/** | ||
* Identity matrix | ||
* Matrix2D | ||
* | ||
* @returns {Matrix2D} | ||
* @memberof module:kld-affine | ||
*/ | ||
setReadonlyProperty(Matrix2D, "IDENTITY", new Matrix2D(1, 0, 0, 1, 0, 0)); | ||
setReadonlyProperty(Matrix2D.IDENTITY, "isIdentity", function () { return true; }); | ||
class Matrix2D { | ||
/** | ||
* Matrix2D | ||
* | ||
* [a c e] | ||
* [b d f] | ||
* [0 0 1] | ||
* | ||
* @param {number} a | ||
* @param {number} b | ||
* @param {number} c | ||
* @param {number} d | ||
* @param {number} e | ||
* @param {number} f | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
constructor(a, b, c, d, e, f) { | ||
this.a = (a !== undefined) ? a : 1; | ||
this.b = (b !== undefined) ? b : 0; | ||
this.c = (c !== undefined) ? c : 0; | ||
this.d = (d !== undefined) ? d : 1; | ||
this.e = (e !== undefined) ? e : 0; | ||
this.f = (f !== undefined) ? f : 0; | ||
} | ||
/** | ||
* translation | ||
* | ||
* @param {number} tx | ||
* @param {number} ty | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static translation(tx, ty) { | ||
return new Matrix2D(1, 0, 0, 1, tx, ty); | ||
} | ||
/** | ||
* Matrix2D | ||
* | ||
* [a c e] | ||
* [b d f] | ||
* [0 0 1] | ||
* | ||
* @param {Number} a | ||
* @param {Number} b | ||
* @param {Number} c | ||
* @param {Number} d | ||
* @param {Number} e | ||
* @param {Number} f | ||
* @returns {Matrix2D} | ||
*/ | ||
function Matrix2D(a, b, c, d, e, f) { | ||
setReadonlyProperty(this, "a", (a !== undefined) ? a : 1); | ||
setReadonlyProperty(this, "b", (b !== undefined) ? b : 0); | ||
setReadonlyProperty(this, "c", (c !== undefined) ? c : 0); | ||
setReadonlyProperty(this, "d", (d !== undefined) ? d : 1); | ||
setReadonlyProperty(this, "e", (e !== undefined) ? e : 0); | ||
setReadonlyProperty(this, "f", (f !== undefined) ? f : 0); | ||
} | ||
/** | ||
* scaling | ||
* | ||
* @param {number} scale | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static scaling(scale) { | ||
return new Matrix2D(scale, 0, 0, scale, 0, 0); | ||
} | ||
/** | ||
* scalingAt | ||
* | ||
* @param {number} scale | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static scalingAt(scale, center) { | ||
return new Matrix2D( | ||
scale, | ||
0, | ||
0, | ||
scale, | ||
center.x - center.x * scale, | ||
center.y - center.y * scale | ||
); | ||
} | ||
// *** STATIC METHODS | ||
/** | ||
* translation | ||
* | ||
* @param {Number} tx | ||
* @param {Number} ty | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.translation = function(tx, ty) { | ||
return new Matrix2D(1, 0, 0, 1, tx, ty); | ||
}; | ||
/** | ||
* nonUniformScaling | ||
* | ||
* @param {number} scaleX | ||
* @param {number} scaleY | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static nonUniformScaling(scaleX, scaleY) { | ||
return new Matrix2D(scaleX, 0, 0, scaleY, 0, 0); | ||
} | ||
/** | ||
* scaling | ||
* | ||
* @param {Number} scale | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.scaling = function(scale) { | ||
return new Matrix2D(scale, 0, 0, scale, 0, 0); | ||
}; | ||
/** | ||
* nonUniformScalingAt | ||
* | ||
* @param {number} scaleX | ||
* @param {number} scaleY | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static nonUniformScalingAt(scaleX, scaleY, center) { | ||
return new Matrix2D( | ||
scaleX, | ||
0, | ||
0, | ||
scaleY, | ||
center.x - center.x * scaleX, | ||
center.y - center.y * scaleY | ||
); | ||
} | ||
/** | ||
* scalingAt | ||
* | ||
* @param {Number} scale | ||
* @param {Point2D} center | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.scalingAt = function(scale, center) { | ||
return new Matrix2D( | ||
scale, | ||
0, | ||
0, | ||
scale, | ||
center.x - center.x * scale, | ||
center.y - center.y * scale | ||
); | ||
} | ||
/** | ||
* rotation | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static rotation(radians) { | ||
const c = Math.cos(radians); | ||
const s = Math.sin(radians); | ||
return new Matrix2D(c, s, -s, c, 0, 0); | ||
} | ||
/** | ||
* nonUniformScaling | ||
* | ||
* @param {Number} scaleX | ||
* @param {Number} scaleY | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.nonUniformScaling = function(scaleX, scaleY) { | ||
return new Matrix2D(scaleX, 0, 0, scaleY, 0, 0); | ||
}; | ||
/** | ||
* rotationAt | ||
* | ||
* @param {number} radians | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static rotationAt(radians, center) { | ||
const c = Math.cos(radians); | ||
const s = Math.sin(radians); | ||
/** | ||
* nonUniformScalingAt | ||
* | ||
* @param {Number} scaleX | ||
* @param {Number} scaleY | ||
* @param {Point2D} center | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.nonUniformScalingAt = function(scaleX, scaleY, center) { | ||
return new Matrix2D( | ||
scaleX, | ||
0, | ||
0, | ||
scaleY, | ||
center.x - center.x * scaleX, | ||
center.y - center.y * scaleY | ||
); | ||
}; | ||
return new Matrix2D( | ||
c, | ||
s, | ||
-s, | ||
c, | ||
center.x - center.x * c + center.y * s, | ||
center.y - center.y * c - center.x * s | ||
); | ||
} | ||
/** | ||
* rotation | ||
* | ||
* @param {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.rotation = function(radians) { | ||
let c = Math.cos(radians); | ||
let s = Math.sin(radians); | ||
/** | ||
* rotationFromVector | ||
* | ||
* @param {module:kld-affine.Vector2D} vector | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static rotationFromVector(vector) { | ||
const unit = vector.unit(); | ||
const c = unit.x; // cos | ||
const s = unit.y; // sin | ||
return new Matrix2D(c, s, -s, c, 0, 0); | ||
}; | ||
return new Matrix2D(c, s, -s, c, 0, 0); | ||
} | ||
/** | ||
* rotationAt | ||
* | ||
* @param {Number} radians | ||
* @param {Point2D} center | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.rotationAt = function(radians, center) { | ||
let c = Math.cos(radians); | ||
let s = Math.sin(radians); | ||
/** | ||
* xFlip | ||
* | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static xFlip() { | ||
return new Matrix2D(-1, 0, 0, 1, 0, 0); | ||
} | ||
return new Matrix2D( | ||
c, | ||
s, | ||
-s, | ||
c, | ||
center.x - center.x * c + center.y * s, | ||
center.y - center.y * c - center.x * s | ||
); | ||
}; | ||
/** | ||
* yFlip | ||
* | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static yFlip() { | ||
return new Matrix2D(1, 0, 0, -1, 0, 0); | ||
} | ||
/** | ||
* rotationFromVector | ||
* | ||
* @param {Vector2D} | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.rotationFromVector = function(vector) { | ||
var unit = vector.unit(); | ||
var c = unit.x; // cos | ||
var s = unit.y; // sin | ||
/** | ||
* xSkew | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static xSkew(radians) { | ||
const t = Math.tan(radians); | ||
return new Matrix2D(c, s, -s, c, 0, 0); | ||
}; | ||
return new Matrix2D(1, 0, t, 1, 0, 0); | ||
} | ||
/** | ||
* xFlip | ||
* | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.xFlip = function() { | ||
return new Matrix2D(-1, 0, 0, 1, 0, 0); | ||
}; | ||
/** | ||
* ySkew | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
static ySkew(radians) { | ||
const t = Math.tan(radians); | ||
/** | ||
* yFlip | ||
* | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.yFlip = function() { | ||
return new Matrix2D(1, 0, 0, -1, 0, 0); | ||
}; | ||
return new Matrix2D(1, t, 0, 1, 0, 0); | ||
} | ||
/** | ||
* xSkew | ||
* | ||
* @param {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.xSkew = function(radians) { | ||
var t = Math.tan(radians); | ||
/** | ||
* multiply | ||
* | ||
* @param {module:kld-affine.Matrix2D} that | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
multiply(that) { | ||
if (this.isIdentity()) { | ||
return that; | ||
} | ||
return new Matrix2D(1, 0, t, 1, 0, 0); | ||
}; | ||
if (that.isIdentity()) { | ||
return this; | ||
} | ||
/** | ||
* ySkew | ||
* | ||
* @param {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.ySkew = function(radians) { | ||
var t = Math.tan(radians); | ||
return new this.constructor( | ||
this.a * that.a + this.c * that.b, | ||
this.b * that.a + this.d * that.b, | ||
this.a * that.c + this.c * that.d, | ||
this.b * that.c + this.d * that.d, | ||
this.a * that.e + this.c * that.f + this.e, | ||
this.b * that.e + this.d * that.f + this.f | ||
); | ||
} | ||
return new Matrix2D(1, t, 0, 1, 0, 0); | ||
}; | ||
/** | ||
* inverse | ||
* | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
inverse() { | ||
if (this.isIdentity()) { | ||
return this; | ||
} | ||
const det1 = this.a * this.d - this.b * this.c; | ||
// *** METHODS | ||
if (det1 === 0.0) { | ||
throw new Error("Matrix is not invertible"); | ||
} | ||
/** | ||
* multiply | ||
* | ||
* @pararm {Matrix2D} that | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.multiply = function (that) { | ||
if (this.isIdentity()) { | ||
return that; | ||
const idet = 1.0 / det1; | ||
const det2 = this.f * this.c - this.e * this.d; | ||
const det3 = this.e * this.b - this.f * this.a; | ||
return new this.constructor( | ||
this.d * idet, | ||
-this.b * idet, | ||
-this.c * idet, | ||
this.a * idet, | ||
det2 * idet, | ||
det3 * idet | ||
); | ||
} | ||
if (that.isIdentity()) { | ||
return this; | ||
/** | ||
* translate | ||
* | ||
* @param {number} tx | ||
* @param {number} ty | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
translate(tx, ty) { | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
this.c, | ||
this.d, | ||
this.a * tx + this.c * ty + this.e, | ||
this.b * tx + this.d * ty + this.f | ||
); | ||
} | ||
return new this.constructor( | ||
this.a * that.a + this.c * that.b, | ||
this.b * that.a + this.d * that.b, | ||
this.a * that.c + this.c * that.d, | ||
this.b * that.c + this.d * that.d, | ||
this.a * that.e + this.c * that.f + this.e, | ||
this.b * that.e + this.d * that.f + this.f | ||
); | ||
}; | ||
/** | ||
* inverse | ||
* | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.inverse = function () { | ||
if (this.isIdentity()) { | ||
return this; | ||
/** | ||
* scale | ||
* | ||
* @param {number} scale | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
scale(scale) { | ||
return new this.constructor( | ||
this.a * scale, | ||
this.b * scale, | ||
this.c * scale, | ||
this.d * scale, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
var det1 = this.a * this.d - this.b * this.c; | ||
/** | ||
* scaleAt | ||
* | ||
* @param {number} scale | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
scaleAt(scale, center) { | ||
const dx = center.x - scale * center.x; | ||
const dy = center.y - scale * center.y; | ||
if ( det1 === 0.0 ) { | ||
throw("Matrix is not invertible"); | ||
return new this.constructor( | ||
this.a * scale, | ||
this.b * scale, | ||
this.c * scale, | ||
this.d * scale, | ||
this.a * dx + this.c * dy + this.e, | ||
this.b * dx + this.d * dy + this.f | ||
); | ||
} | ||
var idet = 1.0 / det1; | ||
var det2 = this.f * this.c - this.e * this.d; | ||
var det3 = this.e * this.b - this.f * this.a; | ||
/** | ||
* scaleNonUniform | ||
* | ||
* @param {number} scaleX | ||
* @param {number} scaleY | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
scaleNonUniform(scaleX, scaleY) { | ||
return new this.constructor( | ||
this.a * scaleX, | ||
this.b * scaleX, | ||
this.c * scaleY, | ||
this.d * scaleY, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
return new this.constructor( | ||
this.d * idet, | ||
-this.b * idet, | ||
-this.c * idet, | ||
this.a * idet, | ||
det2 * idet, | ||
det3 * idet | ||
); | ||
}; | ||
/** | ||
* scaleNonUniformAt | ||
* | ||
* @param {number} scaleX | ||
* @param {number} scaleY | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
scaleNonUniformAt(scaleX, scaleY, center) { | ||
const dx = center.x - scaleX * center.x; | ||
const dy = center.y - scaleY * center.y; | ||
/** | ||
* translate | ||
* | ||
* @param {Number} tx | ||
* @param {Number} ty | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.translate = function(tx, ty) { | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
this.c, | ||
this.d, | ||
this.a * tx + this.c * ty + this.e, | ||
this.b * tx + this.d * ty + this.f | ||
); | ||
}; | ||
return new this.constructor( | ||
this.a * scaleX, | ||
this.b * scaleX, | ||
this.c * scaleY, | ||
this.d * scaleY, | ||
this.a * dx + this.c * dy + this.e, | ||
this.b * dx + this.d * dy + this.f | ||
); | ||
} | ||
/** | ||
* scale | ||
* | ||
* @param {Number} scale | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.scale = function(scale) { | ||
return new this.constructor( | ||
this.a * scale, | ||
this.b * scale, | ||
this.c * scale, | ||
this.d * scale, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
/** | ||
* rotate | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
rotate(radians) { | ||
const c = Math.cos(radians); | ||
const s = Math.sin(radians); | ||
/** | ||
* scaleAt | ||
* | ||
* @param {Number} scale | ||
* @param {Point2D} center | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.scaleAt = function(scale, center) { | ||
var dx = center.x - scale * center.x; | ||
var dy = center.y - scale * center.y; | ||
return new this.constructor( | ||
this.a * c + this.c * s, | ||
this.b * c + this.d * s, | ||
this.a * -s + this.c * c, | ||
this.b * -s + this.d * c, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
return new this.constructor( | ||
this.a * scale, | ||
this.b * scale, | ||
this.c * scale, | ||
this.d * scale, | ||
this.a * dx + this.c * dy + this.e, | ||
this.b * dx + this.d * dy + this.f | ||
); | ||
}; | ||
/** | ||
* rotateAt | ||
* | ||
* @param {number} radians | ||
* @param {module:kld-affine.Point2D} center | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
rotateAt(radians, center) { | ||
const cos = Math.cos(radians); | ||
const sin = Math.sin(radians); | ||
const cx = center.x; | ||
const cy = center.y; | ||
/** | ||
* scaleNonUniform | ||
* | ||
* @param {Number} scaleX | ||
* @param {Number} scaleY | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.scaleNonUniform = function(scaleX, scaleY) { | ||
return new this.constructor( | ||
this.a * scaleX, | ||
this.b * scaleX, | ||
this.c * scaleY, | ||
this.d * scaleY, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
const a = this.a * cos + this.c * sin; | ||
const b = this.b * cos + this.d * sin; | ||
const c = this.c * cos - this.a * sin; | ||
const d = this.d * cos - this.b * sin; | ||
/** | ||
* scaleNonUniformAt | ||
* | ||
* @param {Number} scaleX | ||
* @param {Number} scaleY | ||
* @param {Point2D} center | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.scaleNonUniformAt = function(scaleX, scaleY, center) { | ||
var dx = center.x - scaleX * center.x; | ||
var dy = center.y - scaleY * center.y; | ||
return new this.constructor( | ||
a, | ||
b, | ||
c, | ||
d, | ||
(this.a - a) * cx + (this.c - c) * cy + this.e, | ||
(this.b - b) * cx + (this.d - d) * cy + this.f | ||
); | ||
} | ||
return new this.constructor( | ||
this.a * scaleX, | ||
this.b * scaleX, | ||
this.c * scaleY, | ||
this.d * scaleY, | ||
this.a * dx + this.c * dy + this.e, | ||
this.b * dx + this.d * dy + this.f | ||
); | ||
}; | ||
/** | ||
* rotateFromVector | ||
* | ||
* @param {module:kld-affine.Vector2D} vector | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
rotateFromVector(vector) { | ||
const unit = vector.unit(); | ||
const c = unit.x; // cos | ||
const s = unit.y; // sin | ||
/** | ||
* rotate | ||
* | ||
* @param {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.rotate = function(radians) { | ||
var c = Math.cos(radians); | ||
var s = Math.sin(radians); | ||
return new this.constructor( | ||
this.a * c + this.c * s, | ||
this.b * c + this.d * s, | ||
this.a * -s + this.c * c, | ||
this.b * -s + this.d * c, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
return new this.constructor( | ||
this.a * c + this.c * s, | ||
this.b * c + this.d * s, | ||
this.a * -s + this.c * c, | ||
this.b * -s + this.d * c, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
/** | ||
* flipX | ||
* | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
flipX() { | ||
return new this.constructor( | ||
-this.a, | ||
-this.b, | ||
this.c, | ||
this.d, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
/** | ||
* rotateAt | ||
* | ||
* @param {Number} radians | ||
* @param {Point2D} center | ||
* @result {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.rotateAt = function(radians, center) { | ||
var cos = Math.cos(radians); | ||
var sin = Math.sin(radians); | ||
var cx = center.x; | ||
var cy = center.y; | ||
/** | ||
* flipY | ||
* | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
flipY() { | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
-this.c, | ||
-this.d, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
var a = this.a * cos + this.c * sin; | ||
var b = this.b * cos + this.d * sin; | ||
var c = this.c * cos - this.a * sin; | ||
var d = this.d * cos - this.b * sin; | ||
/** | ||
* skewX | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
skewX(radians) { | ||
const t = Math.tan(radians); | ||
return new this.constructor( | ||
a, | ||
b, | ||
c, | ||
d, | ||
(this.a - a) * cx + (this.c - c) * cy + this.e, | ||
(this.b - b) * cx + (this.d - d) * cy + this.f | ||
); | ||
}; | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
this.c + this.a * t, | ||
this.d + this.b * t, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
/** | ||
* rotateFromVector | ||
* | ||
* @param {Vector2D} | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.rotateFromVector = function(vector) { | ||
var unit = vector.unit(); | ||
var c = unit.x; // cos | ||
var s = unit.y; // sin | ||
// TODO: skewXAt | ||
return new this.constructor( | ||
this.a * c + this.c * s, | ||
this.b * c + this.d * s, | ||
this.a * -s + this.c * c, | ||
this.b * -s + this.d * c, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
/** | ||
* skewY | ||
* | ||
* @param {number} radians | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
skewY(radians) { | ||
const t = Math.tan(radians); | ||
/** | ||
* flipX | ||
* | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.flipX = function() { | ||
return new this.constructor( | ||
-this.a, | ||
-this.b, | ||
this.c, | ||
this.d, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
return new this.constructor( | ||
this.a + this.c * t, | ||
this.b + this.d * t, | ||
this.c, | ||
this.d, | ||
this.e, | ||
this.f | ||
); | ||
} | ||
/** | ||
* flipY | ||
* | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.flipY = function() { | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
-this.c, | ||
-this.d, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
// TODO: skewYAt | ||
/** | ||
* skewX | ||
* | ||
* @pararm {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.skewX = function(radians) { | ||
var t = Math.tan(radians); | ||
/** | ||
* isIdentity | ||
* | ||
* @returns {boolean} | ||
*/ | ||
isIdentity() { | ||
return ( | ||
this.a === 1.0 && | ||
this.b === 0.0 && | ||
this.c === 0.0 && | ||
this.d === 1.0 && | ||
this.e === 0.0 && | ||
this.f === 0.0 | ||
); | ||
} | ||
return new this.constructor( | ||
this.a, | ||
this.b, | ||
this.c + this.a * t, | ||
this.d + this.b * t, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
/** | ||
* isInvertible | ||
* | ||
* @returns {boolean} | ||
*/ | ||
isInvertible() { | ||
return this.a * this.d - this.b * this.c !== 0.0; | ||
} | ||
// TODO: skewXAt | ||
/** | ||
* getScale | ||
* | ||
* @returns {{ scaleX: number, scaleY: number }} | ||
*/ | ||
getScale() { | ||
return { | ||
scaleX: Math.sqrt(this.a * this.a + this.c * this.c), | ||
scaleY: Math.sqrt(this.b * this.b + this.d * this.d) | ||
}; | ||
} | ||
/** | ||
* skewY | ||
* | ||
* @pararm {Number} radians | ||
* @returns {Matrix2D} | ||
*/ | ||
Matrix2D.prototype.skewY = function(radians) { | ||
var t = Math.tan(radians); | ||
/** | ||
* getDecomposition | ||
* | ||
* Calculates matrix Singular Value Decomposition | ||
* | ||
* The resulting matrices, translation, rotation, scale, and rotation0, return | ||
* this matrix when they are muliplied together in the listed order | ||
* | ||
* @see Jim Blinn's article {@link http://dx.doi.org/10.1109/38.486688} | ||
* @see {@link http://math.stackexchange.com/questions/861674/decompose-a-2d-arbitrary-transform-into-only-scaling-and-rotation} | ||
* | ||
* @returns {{ translation: module:kld-affine.Matrix2D, rotation: module:kld-affine.Matrix2D, scale: module:kld-affine.Matrix2D, rotation0: module:kld-affine.Matrix2D }} | ||
*/ | ||
getDecomposition() { | ||
const E = (this.a + this.d) * 0.5; | ||
const F = (this.a - this.d) * 0.5; | ||
const G = (this.b + this.c) * 0.5; | ||
const H = (this.b - this.c) * 0.5; | ||
return new this.constructor( | ||
this.a + this.c * t, | ||
this.b + this.d * t, | ||
this.c, | ||
this.d, | ||
this.e, | ||
this.f | ||
); | ||
}; | ||
const Q = Math.sqrt(E * E + H * H); | ||
const R = Math.sqrt(F * F + G * G); | ||
const scaleX = Q + R; | ||
const scaleY = Q - R; | ||
// TODO: skewYAt | ||
const a1 = Math.atan2(G, F); | ||
const a2 = Math.atan2(H, E); | ||
const theta = (a2 - a1) * 0.5; | ||
const phi = (a2 + a1) * 0.5; | ||
/** | ||
* isIdentity | ||
* | ||
* @returns {Boolean} | ||
*/ | ||
Matrix2D.prototype.isIdentity = function() { | ||
return ( | ||
this.a === 1.0 && | ||
this.b === 0.0 && | ||
this.c === 0.0 && | ||
this.d === 1.0 && | ||
this.e === 0.0 && | ||
this.f === 0.0 | ||
); | ||
}; | ||
return { | ||
translation: this.constructor.translation(this.e, this.f), | ||
rotation: this.constructor.rotation(phi), | ||
scale: this.constructor.nonUniformScaling(scaleX, scaleY), | ||
rotation0: this.constructor.rotation(theta) | ||
}; | ||
} | ||
/** | ||
* isInvertible | ||
* | ||
* @returns {Boolean} | ||
*/ | ||
Matrix2D.prototype.isInvertible = function() { | ||
return this.a * this.d - this.b * this.c !== 0.0; | ||
}; | ||
/** | ||
* equals | ||
* | ||
* @param {module:kld-affine.Matrix2D} that | ||
* @returns {boolean} | ||
*/ | ||
equals(that) { | ||
return ( | ||
this.a === that.a && | ||
this.b === that.b && | ||
this.c === that.c && | ||
this.d === that.d && | ||
this.e === that.e && | ||
this.f === that.f | ||
); | ||
} | ||
/** | ||
* getScale | ||
* | ||
* @returns {{ scaleX: Number, scaleY: Number }} | ||
*/ | ||
Matrix2D.prototype.getScale = function() { | ||
return { | ||
scaleX: Math.sqrt(this.a * this.a + this.c * this.c), | ||
scaleY: Math.sqrt(this.b * this.b + this.d * this.d) | ||
}; | ||
}; | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {module:kld-affine.Matrix2D} that | ||
* @param {number} precision | ||
* @returns {boolean} | ||
*/ | ||
precisionEquals(that, precision) { | ||
return ( | ||
Math.abs(this.a - that.a) < precision && | ||
Math.abs(this.b - that.b) < precision && | ||
Math.abs(this.c - that.c) < precision && | ||
Math.abs(this.d - that.d) < precision && | ||
Math.abs(this.e - that.e) < precision && | ||
Math.abs(this.f - that.f) < precision | ||
); | ||
} | ||
/** | ||
* getDecomposition | ||
* | ||
* Calculates matrix Singular Value Decomposition | ||
* | ||
* The resulting matrices, translation, rotation, scale, and rotation0, return | ||
* this matrix when they are muliplied together in the listed order | ||
* | ||
* @see Jim Blinn's article {@link http://dx.doi.org/10.1109/38.486688} | ||
* @see {@link http://math.stackexchange.com/questions/861674/decompose-a-2d-arbitrary-transform-into-only-scaling-and-rotation} | ||
* | ||
* @returns {{ translation: Matrix2D, rotation: Matrix2D, scale: Matrix2D, rotation0: Matrix2D }} | ||
*/ | ||
Matrix2D.prototype.getDecomposition = function () { | ||
var E = (this.a + this.d) * 0.5; | ||
var F = (this.a - this.d) * 0.5; | ||
var G = (this.b + this.c) * 0.5; | ||
var H = (this.b - this.c) * 0.5; | ||
/** | ||
* toString | ||
* | ||
* @returns {string} | ||
*/ | ||
toString() { | ||
return "matrix(" + [this.a, this.b, this.c, this.d, this.e, this.f].join(",") + ")"; | ||
} | ||
} | ||
var Q = Math.sqrt(E * E + H * H); | ||
var R = Math.sqrt(F * F + G * G); | ||
var scaleX = Q + R; | ||
var scaleY = Q - R; | ||
var a1 = Math.atan2(G, F); | ||
var a2 = Math.atan2(H, E); | ||
var theta = (a2 - a1) * 0.5; | ||
var phi = (a2 + a1) * 0.5; | ||
// TODO: Add static methods to generate translation, rotation, etc. | ||
// matrices directly | ||
return { | ||
translation: new this.constructor(1, 0, 0, 1, this.e, this.f), | ||
rotation: this.constructor.IDENTITY.rotate(phi), | ||
scale: new this.constructor(scaleX, 0, 0, scaleY, 0, 0), | ||
rotation0: this.constructor.IDENTITY.rotate(theta) | ||
}; | ||
}; | ||
/** | ||
* equals | ||
* Identity matrix | ||
* | ||
* @param {Matrix2D} that | ||
* @returns {Boolean} | ||
* @returns {module:kld-affine.Matrix2D} | ||
*/ | ||
Matrix2D.prototype.equals = function(that) { | ||
return ( | ||
this.a === that.a && | ||
this.b === that.b && | ||
this.c === that.c && | ||
this.d === that.d && | ||
this.e === that.e && | ||
this.f === that.f | ||
); | ||
}; | ||
Matrix2D.IDENTITY = new Matrix2D(); | ||
Matrix2D.IDENTITY.isIdentity = () => true; | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {Matrix2D} that | ||
* @param {Number} precision | ||
* @returns {Boolean} | ||
*/ | ||
Matrix2D.prototype.precisionEquals = function(that, precision) { | ||
return ( | ||
Math.abs(this.a - that.a) < precision && | ||
Math.abs(this.b - that.b) < precision && | ||
Math.abs(this.c - that.c) < precision && | ||
Math.abs(this.d - that.d) < precision && | ||
Math.abs(this.e - that.e) < precision && | ||
Math.abs(this.f - that.f) < precision | ||
); | ||
}; | ||
/** | ||
* toString | ||
* | ||
* @returns {String} | ||
*/ | ||
Matrix2D.prototype.toString = function() { | ||
return "matrix(" + [this.a, this.b, this.c, this.d, this.e, this.f].join(",") + ")"; | ||
}; | ||
if (typeof module !== "undefined") { | ||
module.exports = Matrix2D; | ||
} | ||
export default Matrix2D; |
/** | ||
* | ||
* Point2D.js | ||
* | ||
* copyright 2001-2002, 2013, 2017 Kevin Lindsey | ||
* | ||
* Point2D.js | ||
* @module Point2D | ||
* @copyright 2001-2019 Kevin Lindsey | ||
*/ | ||
@@ -12,177 +10,170 @@ | ||
* | ||
* @param {Number} x | ||
* @param {Number} y | ||
* @returns {Point2D} | ||
* @memberof module:kld-affine | ||
*/ | ||
function Point2D(x, y) { | ||
Object.defineProperties(this, { | ||
"x": { | ||
value: x !== undefined ? x : 0.0, | ||
writable: false, | ||
enumerable: true, | ||
configurable: false | ||
}, | ||
"y": { | ||
value: y !== undefined ? y : 0.0, | ||
writable: false, | ||
enumerable: true, | ||
configurable: false | ||
} | ||
}); | ||
} | ||
class Point2D { | ||
/** | ||
* Point2D | ||
* | ||
* @param {number} x | ||
* @param {number} y | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
constructor(x, y) { | ||
this.x = x !== undefined ? x : 0.0; | ||
this.y = y !== undefined ? y : 0.0; | ||
} | ||
/** | ||
* clone | ||
* | ||
* @returns {Point2D} | ||
*/ | ||
Point2D.prototype.clone = function() { | ||
return new this.constructor(this.x, this.y); | ||
}; | ||
/** | ||
* clone | ||
* | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
clone() { | ||
return new this.constructor(this.x, this.y); | ||
} | ||
/** | ||
* add | ||
* | ||
* @param {Point2D|Vector2D} that | ||
* @returns {Point2D} | ||
*/ | ||
Point2D.prototype.add = function(that) { | ||
return new this.constructor(this.x+that.x, this.y+that.y); | ||
}; | ||
/** | ||
* add | ||
* | ||
* @param {Point2D|Vector2D} that | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
add(that) { | ||
return new this.constructor(this.x + that.x, this.y + that.y); | ||
} | ||
/** | ||
* subtract | ||
* | ||
* @param { Vector2D | Point2D } that | ||
* @returns {Point2D} | ||
*/ | ||
Point2D.prototype.subtract = function(that) { | ||
return new this.constructor(this.x-that.x, this.y-that.y); | ||
}; | ||
/** | ||
* subtract | ||
* | ||
* @param { Vector2D | Point2D } that | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
subtract(that) { | ||
return new this.constructor(this.x - that.x, this.y - that.y); | ||
} | ||
/** | ||
* multiply | ||
* | ||
* @param {Number} scalar | ||
* @returns {Point2D} | ||
*/ | ||
Point2D.prototype.multiply = function(scalar) { | ||
return new this.constructor(this.x*scalar, this.y*scalar); | ||
}; | ||
/** | ||
* multiply | ||
* | ||
* @param {number} scalar | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
multiply(scalar) { | ||
return new this.constructor(this.x * scalar, this.y * scalar); | ||
} | ||
/** | ||
* divide | ||
* | ||
* @param {Number} scalar | ||
* @returns {Point2D} | ||
*/ | ||
Point2D.prototype.divide = function(scalar) { | ||
return new this.constructor(this.x/scalar, this.y/scalar); | ||
}; | ||
/** | ||
* divide | ||
* | ||
* @param {number} scalar | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
divide(scalar) { | ||
return new this.constructor(this.x / scalar, this.y / scalar); | ||
} | ||
/** | ||
* equals | ||
* | ||
* @param {Point2D} that | ||
* @returns {Boolean} | ||
*/ | ||
Point2D.prototype.equals = function(that) { | ||
return ( this.x === that.x && this.y === that.y ); | ||
}; | ||
/** | ||
* equals | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @returns {boolean} | ||
*/ | ||
equals(that) { | ||
return (this.x === that.x && this.y === that.y); | ||
} | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {Point2D} that | ||
* @param {Number} precision | ||
* @returns {Boolean} | ||
*/ | ||
Point2D.prototype.precisionEquals = function(that, precision) { | ||
return ( | ||
Math.abs(this.x - that.x) < precision && | ||
Math.abs(this.y - that.y) < precision | ||
); | ||
}; | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @param {number} precision | ||
* @returns {boolean} | ||
*/ | ||
precisionEquals(that, precision) { | ||
return ( | ||
Math.abs(this.x - that.x) < precision && | ||
Math.abs(this.y - that.y) < precision | ||
); | ||
} | ||
// utility methods | ||
// utility methods | ||
/** | ||
* lerp | ||
* | ||
* @param { Vector2D | Point2D } that | ||
* @param {Number} t | ||
@ @returns {Point2D} | ||
*/ | ||
Point2D.prototype.lerp = function(that, t) { | ||
var omt = 1.0 - t; | ||
/** | ||
* lerp | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @param {number} t | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
lerp(that, t) { | ||
const omt = 1.0 - t; | ||
return new this.constructor( | ||
this.x * omt + that.x * t, | ||
this.y * omt + that.y * t | ||
); | ||
}; | ||
return new this.constructor( | ||
this.x * omt + that.x * t, | ||
this.y * omt + that.y * t | ||
); | ||
} | ||
/** | ||
* distanceFrom | ||
* | ||
* @param {Point2D} that | ||
* @returns {Number} | ||
*/ | ||
Point2D.prototype.distanceFrom = function(that) { | ||
var dx = this.x - that.x; | ||
var dy = this.y - that.y; | ||
/** | ||
* distanceFrom | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @returns {number} | ||
*/ | ||
distanceFrom(that) { | ||
const dx = this.x - that.x; | ||
const dy = this.y - that.y; | ||
return Math.sqrt(dx*dx + dy*dy); | ||
}; | ||
return Math.sqrt(dx * dx + dy * dy); | ||
} | ||
/** | ||
* min | ||
* | ||
* @param {Point2D} that | ||
* @returns {Number} | ||
*/ | ||
Point2D.prototype.min = function(that) { | ||
return new this.constructor( | ||
Math.min( this.x, that.x ), | ||
Math.min( this.y, that.y ) | ||
); | ||
}; | ||
/** | ||
* min | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @returns {number} | ||
*/ | ||
min(that) { | ||
return new this.constructor( | ||
Math.min(this.x, that.x), | ||
Math.min(this.y, that.y) | ||
); | ||
} | ||
/** | ||
* max | ||
* | ||
* @param {Point2D} that | ||
* @returns {Number} | ||
*/ | ||
Point2D.prototype.max = function(that) { | ||
return new this.constructor( | ||
Math.max( this.x, that.x ), | ||
Math.max( this.y, that.y ) | ||
); | ||
}; | ||
/** | ||
* max | ||
* | ||
* @param {module:kld-affine.Point2D} that | ||
* @returns {number} | ||
*/ | ||
max(that) { | ||
return new this.constructor( | ||
Math.max(this.x, that.x), | ||
Math.max(this.y, that.y) | ||
); | ||
} | ||
/** | ||
* transform | ||
* | ||
* @param {Matrix2D} | ||
* @result {Point2D} | ||
*/ | ||
Point2D.prototype.transform = function(matrix) { | ||
return new this.constructor( | ||
matrix.a * this.x + matrix.c * this.y + matrix.e, | ||
matrix.b * this.x + matrix.d * this.y + matrix.f | ||
); | ||
}; | ||
/** | ||
* transform | ||
* | ||
* @param {module:kld-affine.Matrix2D} matrix | ||
* @returns {module:kld-affine.Point2D} | ||
*/ | ||
transform(matrix) { | ||
return new this.constructor( | ||
matrix.a * this.x + matrix.c * this.y + matrix.e, | ||
matrix.b * this.x + matrix.d * this.y + matrix.f | ||
); | ||
} | ||
/** | ||
* toString | ||
* | ||
* @returns {String} | ||
*/ | ||
Point2D.prototype.toString = function() { | ||
return "point(" + this.x + "," + this.y + ")"; | ||
}; | ||
/** | ||
* toString | ||
* | ||
* @returns {string} | ||
*/ | ||
toString() { | ||
return "point(" + this.x + "," + this.y + ")"; | ||
} | ||
} | ||
if (typeof module !== "undefined") { | ||
module.exports = Point2D; | ||
} | ||
export default Point2D; |
/** | ||
* | ||
* Vector2D.js | ||
* | ||
* copyright 2001-2002, 2013, 2017 Kevin Lindsey | ||
* | ||
* Vector2D.js | ||
* @module Vector2D | ||
* @copyright 2001-2019 Kevin Lindsey | ||
*/ | ||
@@ -12,231 +10,224 @@ | ||
* | ||
* @param {Number} x | ||
* @param {Number} y | ||
* @returns {Vector2D} | ||
* @memberof module:kld-affine | ||
*/ | ||
function Vector2D(x, y) { | ||
Object.defineProperties(this, { | ||
"x": { | ||
value: x !== undefined ? x : 0.0, | ||
writable: false, | ||
enumerable: true, | ||
configurable: false | ||
}, | ||
"y": { | ||
value: y !== undefined ? y : 0.0, | ||
writable: false, | ||
enumerable: true, | ||
configurable: false | ||
} | ||
}); | ||
} | ||
class Vector2D { | ||
/** | ||
* Vector2D | ||
* | ||
* @param {number} x | ||
* @param {number} y | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
constructor(x, y) { | ||
this.x = x !== undefined ? x : 0.0; | ||
this.y = y !== undefined ? y : 0.0; | ||
} | ||
/** | ||
* fromPoints | ||
* | ||
* @param {Point2D} p1 | ||
* @param {Point2D} p2 | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.fromPoints = function(p1, p2) { | ||
return new Vector2D( | ||
p2.x - p1.x, | ||
p2.y - p1.y | ||
); | ||
}; | ||
/** | ||
* fromPoints | ||
* | ||
* @param {module:kld-affine.Point2D} p1 | ||
* @param {module:kld-affine.Point2D} p2 | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
static fromPoints(p1, p2) { | ||
return new Vector2D( | ||
p2.x - p1.x, | ||
p2.y - p1.y | ||
); | ||
} | ||
/** | ||
* length | ||
* | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.length = function() { | ||
return Math.sqrt(this.x*this.x + this.y*this.y); | ||
}; | ||
/** | ||
* length | ||
* | ||
* @returns {number} | ||
*/ | ||
length() { | ||
return Math.sqrt(this.x * this.x + this.y * this.y); | ||
} | ||
/** | ||
* magnitude | ||
* | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.magnitude = function() { | ||
return this.x*this.x + this.y*this.y; | ||
}; | ||
/** | ||
* magnitude | ||
* | ||
* @returns {number} | ||
*/ | ||
magnitude() { | ||
return this.x * this.x + this.y * this.y; | ||
} | ||
/** | ||
* dot | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.dot = function(that) { | ||
return this.x*that.x + this.y*that.y; | ||
}; | ||
/** | ||
* dot | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {number} | ||
*/ | ||
dot(that) { | ||
return this.x * that.x + this.y * that.y; | ||
} | ||
/** | ||
* cross | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.cross = function(that) { | ||
return this.x*that.y - this.y*that.x; | ||
}; | ||
/** | ||
* cross | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {number} | ||
*/ | ||
cross(that) { | ||
return this.x * that.y - this.y * that.x; | ||
} | ||
/** | ||
* determinant | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.determinant = function(that) { | ||
return this.x*that.y - this.y*that.x; | ||
}; | ||
/** | ||
* determinant | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {number} | ||
*/ | ||
determinant(that) { | ||
return this.x * that.y - this.y * that.x; | ||
} | ||
/** | ||
* unit | ||
* | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.unit = function() { | ||
return this.divide( this.length() ); | ||
}; | ||
/** | ||
* unit | ||
* | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
unit() { | ||
return this.divide(this.length()); | ||
} | ||
/** | ||
* add | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.add = function(that) { | ||
return new this.constructor(this.x + that.x, this.y + that.y); | ||
}; | ||
/** | ||
* add | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
add(that) { | ||
return new this.constructor(this.x + that.x, this.y + that.y); | ||
} | ||
/** | ||
* subtract | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.subtract = function(that) { | ||
return new this.constructor(this.x - that.x, this.y - that.y); | ||
}; | ||
/** | ||
* subtract | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
subtract(that) { | ||
return new this.constructor(this.x - that.x, this.y - that.y); | ||
} | ||
/** | ||
* multiply | ||
* | ||
* @param {Number} scalar | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.multiply = function(scalar) { | ||
return new this.constructor(this.x * scalar, this.y * scalar); | ||
}; | ||
/** | ||
* multiply | ||
* | ||
* @param {number} scalar | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
multiply(scalar) { | ||
return new this.constructor(this.x * scalar, this.y * scalar); | ||
} | ||
/** | ||
* divide | ||
* | ||
* @param {Number} scalar | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.divide = function(scalar) { | ||
return new this.constructor(this.x / scalar, this.y / scalar); | ||
}; | ||
/** | ||
* divide | ||
* | ||
* @param {number} scalar | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
divide(scalar) { | ||
return new this.constructor(this.x / scalar, this.y / scalar); | ||
} | ||
/** | ||
* angleBetween | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Number} | ||
*/ | ||
Vector2D.prototype.angleBetween = function(that) { | ||
var cos = this.dot(that) / (this.length() * that.length()); | ||
cos = Math.max(-1, Math.min(cos, 1)); | ||
var radians = Math.acos(cos); | ||
/** | ||
* angleBetween | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {number} | ||
*/ | ||
angleBetween(that) { | ||
let cos = this.dot(that) / (this.length() * that.length()); | ||
cos = Math.max(-1, Math.min(cos, 1)); | ||
const radians = Math.acos(cos); | ||
return (this.cross(that) < 0.0) ? -radians : radians; | ||
}; | ||
return (this.cross(that) < 0.0) ? -radians : radians; | ||
} | ||
/** | ||
* Find a vector is that is perpendicular to this vector | ||
* | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.perp = function() { | ||
return new this.constructor(-this.y, this.x); | ||
}; | ||
/** | ||
* Find a vector is that is perpendicular to this vector | ||
* | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
perp() { | ||
return new this.constructor(-this.y, this.x); | ||
} | ||
/** | ||
* Find the component of the specified vector that is perpendicular to | ||
* this vector | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.perpendicular = function(that) { | ||
return this.subtract(this.project(that)); | ||
}; | ||
/** | ||
* Find the component of the specified vector that is perpendicular to | ||
* this vector | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
perpendicular(that) { | ||
return this.subtract(this.project(that)); | ||
} | ||
/** | ||
* project | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.project = function(that) { | ||
var percent = this.dot(that) / that.dot(that); | ||
/** | ||
* project | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
project(that) { | ||
const percent = this.dot(that) / that.dot(that); | ||
return that.multiply(percent); | ||
}; | ||
return that.multiply(percent); | ||
} | ||
/** | ||
* transform | ||
* | ||
* @param {Matrix2D} | ||
* @returns {Vector2D} | ||
*/ | ||
Vector2D.prototype.transform = function(matrix) { | ||
return new this.constructor( | ||
matrix.a * this.x + matrix.c * this.y, | ||
matrix.b * this.x + matrix.d * this.y | ||
); | ||
}; | ||
/** | ||
* transform | ||
* | ||
* @param {module:kld-affine.Matrix2D} matrix | ||
* @returns {module:kld-affine.Vector2D} | ||
*/ | ||
transform(matrix) { | ||
return new this.constructor( | ||
matrix.a * this.x + matrix.c * this.y, | ||
matrix.b * this.x + matrix.d * this.y | ||
); | ||
} | ||
/** | ||
* equals | ||
* | ||
* @param {Vector2D} that | ||
* @returns {Boolean} | ||
*/ | ||
Vector2D.prototype.equals = function(that) { | ||
return ( | ||
this.x === that.x && | ||
this.y === that.y | ||
); | ||
}; | ||
/** | ||
* equals | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @returns {boolean} | ||
*/ | ||
equals(that) { | ||
return ( | ||
this.x === that.x && | ||
this.y === that.y | ||
); | ||
} | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {Vector2D} that | ||
* @param {Number} precision | ||
* @returns {Boolean} | ||
*/ | ||
Vector2D.prototype.precisionEquals = function(that, precision) { | ||
return ( | ||
Math.abs(this.x - that.x) < precision && | ||
Math.abs(this.y - that.y) < precision | ||
); | ||
}; | ||
/** | ||
* precisionEquals | ||
* | ||
* @param {module:kld-affine.Vector2D} that | ||
* @param {number} precision | ||
* @returns {boolean} | ||
*/ | ||
precisionEquals(that, precision) { | ||
return ( | ||
Math.abs(this.x - that.x) < precision && | ||
Math.abs(this.y - that.y) < precision | ||
); | ||
} | ||
/** | ||
* toString | ||
* | ||
* @returns {String} | ||
*/ | ||
Vector2D.prototype.toString = function() { | ||
return "vector(" + this.x + "," + this.y + ")"; | ||
}; | ||
/** | ||
* toString | ||
* | ||
* @returns {string} | ||
*/ | ||
toString() { | ||
return "vector(" + this.x + "," + this.y + ")"; | ||
} | ||
} | ||
if (typeof module !== "undefined") { | ||
module.exports = Vector2D; | ||
} | ||
export default Vector2D; |
{ | ||
"name": "kld-affine", | ||
"version": "2.0.4", | ||
"version": "2.1.0", | ||
"description": "A collection of classes used in affine geometry", | ||
@@ -9,3 +9,8 @@ "author": { | ||
}, | ||
"contributors": [ | ||
"Brett Zamir" | ||
], | ||
"license": "BSD-3-Clause", | ||
"bugs": "https://github.com/thelonious/kld-affine/issues", | ||
"homepage": "https://github.com/thelonious/kld-affine", | ||
"repository": { | ||
@@ -15,5 +20,14 @@ "type": "git", | ||
}, | ||
"main": "index.js", | ||
"main": "dist/index-umd.js", | ||
"module": "index.js", | ||
"browserslist": [ | ||
"cover 100%" | ||
], | ||
"scripts": { | ||
"test": "mocha" | ||
"eslint": "eslint .", | ||
"rollup": "rollup -c", | ||
"test": "npm run eslint && npm run rollup && mocha --require @babel/register", | ||
"start": "static -p 8055", | ||
"build-docs": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.js .", | ||
"open-docs": "opn http://localhost:8055/docs/jsdoc/ && npm start" | ||
}, | ||
@@ -26,8 +40,33 @@ "keywords": [ | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"mocha": "^3.4.2" | ||
"@babel/core": "^7.4.4", | ||
"@babel/preset-env": "^7.4.4", | ||
"@babel/register": "^7.4.4", | ||
"@mysticatea/eslint-plugin": "^10.0.3", | ||
"eslint": "^5.16.0", | ||
"eslint-config-ash-nazg": "^4.0.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint-plugin-compat": "^3.1.1", | ||
"eslint-plugin-eslint-comments": "^3.1.1", | ||
"eslint-plugin-import": "^2.17.2", | ||
"eslint-plugin-jsdoc": "^4.8.3", | ||
"eslint-plugin-markdown": "^1.0.0", | ||
"eslint-plugin-no-use-extend-native": "^0.4.0", | ||
"eslint-plugin-node": "^9.0.1", | ||
"eslint-plugin-promise": "^4.1.1", | ||
"eslint-plugin-standard": "^4.0.0", | ||
"eslint-plugin-unicorn": "^8.0.2", | ||
"jsdoc": "^3.6.1", | ||
"mocha": "^6.1.4", | ||
"node-static": "^0.7.11", | ||
"opn-cli": "^4.1.0", | ||
"rollup": "^1.11.3", | ||
"rollup-plugin-babel": "^4.3.2", | ||
"rollup-plugin-terser": "^4.0.4", | ||
"typescript": "^3.4.5" | ||
}, | ||
"engines": { | ||
"node": ">= 6.4.0" | ||
"node": ">= 10.15.3" | ||
} | ||
} |
@@ -13,3 +13,5 @@ # kld-affine | ||
npm install kld-affine | ||
``` | ||
npm install kld-affine | ||
``` | ||
@@ -16,0 +18,0 @@ ## Point2D |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
182362
32
2976
0
97
25
2