Comparing version 1.3.1 to 1.4.0
@@ -8,140 +8,211 @@ | ||
this.ty = ty | ||
} | ||
this.equals = function (t) { | ||
return (s === t.s && r === t.r && tx === t.tx && ty === t.ty) | ||
} | ||
// Default epsilon to use when coping with floating point arithmetics. | ||
// JavaScript floating point numbers have 52 bits in mantissa (IEEE-754). | ||
// That is about 16 base10 numbers. Therefore the epsilon should be | ||
// much larger than 1 * 10^-16. Let say 1 * 10^-10 is a good one. | ||
Transform.EPSILON = 0.0000000001 | ||
this.getMatrix = function () { | ||
// Get the transformation matrix in the format common to | ||
// many APIs, including: | ||
// - kld-affine | ||
// | ||
// Return | ||
// object o, having properties a, b, c, d, e, f: | ||
// [ s -r tx ] [ o.a o.c o.e ] | ||
// [ r s ty ] = [ o.b o.d o.f ] | ||
// [ 0 0 1 ] [ - - - ] | ||
return { a: s, b: r, c: -r, d: s, e: tx, f: ty } | ||
} | ||
var proto = Transform.prototype | ||
this.getRotation = function () { | ||
// in rads | ||
return Math.atan2(r, s) | ||
proto.almostEquals = | ||
proto.almostEqual = function (t, epsilon) { | ||
// Are transforms almost equal? Return true if a matrix norm | ||
// of the difference is smaller than epsilon. We use modified L1 norm | ||
// that values s, r, tx, and ty as equally important. | ||
// | ||
// Parameters: | ||
// t | ||
// Transform | ||
// epsilon | ||
// optional number, default to Transform.EPSILON. | ||
// Set to 0 for strict comparison. | ||
// | ||
// Note: | ||
// We first thought to use Frobenius norm but it felt wrong | ||
// because it exaggerates s and r. Proof: | ||
// We know Frobenius norm for real square matrices: | ||
// Norm(A) = sqrt(sum_i(sum_j(a_ij * a_ij))) | ||
// For a transform it looks like: | ||
// Norm(T) = sqrt(s*s + r*r + x*x + r*r + s*s + y*y + 1) | ||
// Thus s and r have bigger impact. | ||
// | ||
if (typeof epsilon !== 'number') { | ||
epsilon = Transform.EPSILON | ||
} | ||
this.getScale = function () { | ||
// scale multiplier | ||
return Math.sqrt(r * r + s * s) | ||
} | ||
var ds = Math.abs(this.s - t.s) | ||
var dr = Math.abs(this.r - t.r) | ||
var dx = Math.abs(this.tx - t.tx) | ||
var dy = Math.abs(this.ty - t.ty) | ||
this.getTranslation = function () { | ||
// Current translation as a point. | ||
return [tx, ty] | ||
} | ||
// smaller-or-equal instead of smaller-than to make epsilon=0 work. | ||
return ds + dr + dx + dy <= epsilon | ||
} | ||
this.toArray = function () { | ||
// Return an array representation of the transformation. | ||
// | ||
// Together with nudged.createFromArray(...), this method makes an easy | ||
// serialization and deserialization to and from JSON possible. | ||
return [s, r, tx, ty] | ||
proto.equal = | ||
proto.equals = function (t) { | ||
// Are transforms equal? | ||
// | ||
// Parameters: | ||
// t | ||
// Transform | ||
// | ||
return (this.s === t.s && this.r === t.r && | ||
this.tx === t.tx && this.ty === t.ty) | ||
} | ||
proto.getMatrix = function () { | ||
// Get the transformation matrix in the format common to | ||
// many APIs, including: | ||
// - kld-affine | ||
// | ||
// Return | ||
// object o, having properties a, b, c, d, e, f: | ||
// [ s -r tx ] [ o.a o.c o.e ] | ||
// [ r s ty ] = [ o.b o.d o.f ] | ||
// [ 0 0 1 ] [ - - - ] | ||
return { | ||
a: this.s, | ||
b: this.r, | ||
c: -this.r, | ||
d: this.s, | ||
e: this.tx, | ||
f: this.ty | ||
} | ||
} | ||
// Methods that return new points | ||
proto.getRotation = function () { | ||
// in rads | ||
return Math.atan2(this.r, this.s) | ||
} | ||
this.transform = function (p) { | ||
// p | ||
// point [x, y] or array of points [[x1,y1], [x2, y2], ...] | ||
proto.getScale = function () { | ||
// scale multiplier | ||
return Math.sqrt(this.r * this.r + this.s * this.s) | ||
} | ||
if (typeof p[0] === 'number') { | ||
// Single point | ||
return [s * p[0] - r * p[1] + tx, r * p[0] + s * p[1] + ty] | ||
} // else | ||
proto.getTranslation = function () { | ||
// Current translation as a point. | ||
return [this.tx, this.ty] | ||
} | ||
var i | ||
var c = [] | ||
for (i = 0; i < p.length; i += 1) { | ||
c.push([s * p[i][0] - r * p[i][1] + tx, r * p[i][0] + s * p[i][1] + ty]) | ||
} | ||
return c | ||
} | ||
proto.toArray = function () { | ||
// Return an array representation of the transformation. | ||
// | ||
// Together with nudged.createFromArray(...), this method makes an easy | ||
// serialization and deserialization to and from JSON possible. | ||
return [this.s, this.r, this.tx, this.ty] | ||
} | ||
// Methods that return new Transformations | ||
// Methods that return new points | ||
this.inverse = function () { | ||
// Return inversed transform instance | ||
// See note 2015-10-26-16-30 | ||
var det = s * s + r * r | ||
// Test if singular transformation. These might occur when all the range | ||
// points are the same, forcing the scale to drop to zero. | ||
var eps = 0.00000001 | ||
if (Math.abs(det) < eps) { | ||
throw new Error('Singular transformations cannot be inversed.') | ||
} | ||
var shat = s / det | ||
var rhat = -r / det | ||
var txhat = (-s * tx - r * ty) / det | ||
var tyhat = (r * tx - s * ty) / det | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
proto.transform = function (p) { | ||
// p | ||
// point [x, y] or array of points [[x1,y1], [x2, y2], ...] | ||
if (typeof p[0] === 'number') { | ||
// Single point | ||
return [ | ||
this.s * p[0] - this.r * p[1] + this.tx, | ||
this.r * p[0] + this.s * p[1] + this.ty | ||
] | ||
} // else | ||
var i | ||
var c = [] | ||
for (i = 0; i < p.length; i += 1) { | ||
c.push([ | ||
this.s * p[i][0] - this.r * p[i][1] + this.tx, | ||
this.r * p[i][0] + this.s * p[i][1] + this.ty]) | ||
} | ||
return c | ||
} | ||
this.translateBy = function (dx, dy) { | ||
return new Transform(s, r, tx + dx, ty + dy) | ||
// Methods that return new Transformations | ||
proto.inverse = function () { | ||
// Return inversed transform instance | ||
// See note 2015-10-26-16-30 | ||
var det = this.s * this.s + this.r * this.r | ||
// Test if singular transformation. These might occur when all the range | ||
// points are the same, forcing the scale to drop to zero. | ||
if (Math.abs(det) < Transform.EPSILON) { | ||
throw new Error('Singular transformations cannot be inversed.') | ||
} | ||
var shat = this.s / det | ||
var rhat = -this.r / det | ||
var txhat = (-this.s * this.tx - this.r * this.ty) / det | ||
var tyhat = (this.r * this.tx - this.s * this.ty) / det | ||
this.scaleBy = function (multiplier, pivot) { | ||
// Parameter | ||
// multiplier | ||
// pivot | ||
// optional, a [x, y] point | ||
var m, x, y | ||
m = multiplier // alias | ||
if (typeof pivot === 'undefined') { | ||
x = y = 0 | ||
} else { | ||
x = pivot[0] | ||
y = pivot[1] | ||
} | ||
return new Transform(m * s, m * r, m * tx + (1 - m) * x, m * ty + (1 - m) * y) | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
} | ||
proto.translateBy = function (dx, dy) { | ||
return new Transform(this.s, this.r, this.tx + dx, this.ty + dy) | ||
} | ||
proto.scaleBy = function (multiplier, pivot) { | ||
// Parameter | ||
// multiplier | ||
// pivot | ||
// optional, a [x, y] point | ||
var m, x, y | ||
m = multiplier // alias | ||
if (typeof pivot === 'undefined') { | ||
x = y = 0 | ||
} else { | ||
x = pivot[0] | ||
y = pivot[1] | ||
} | ||
return new Transform( | ||
m * this.s, | ||
m * this.r, | ||
m * this.tx + (1 - m) * x, | ||
m * this.ty + (1 - m) * y | ||
) | ||
} | ||
this.rotateBy = function (radians, pivot) { | ||
// Parameter | ||
// radians | ||
// from positive x to positive y axis | ||
// pivot | ||
// optional, a [x, y] point | ||
var co, si, x, y, shat, rhat, txhat, tyhat | ||
co = Math.cos(radians) | ||
si = Math.sin(radians) | ||
if (typeof pivot === 'undefined') { | ||
x = y = 0 | ||
} else { | ||
x = pivot[0] | ||
y = pivot[1] | ||
} | ||
shat = s * co - r * si | ||
rhat = s * si + r * co | ||
txhat = (tx - x) * co - (ty - y) * si + x | ||
tyhat = (tx - x) * si + (ty - y) * co + y | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
proto.rotateBy = function (radians, pivot) { | ||
// Parameter | ||
// radians | ||
// from positive x to positive y axis | ||
// pivot | ||
// optional, a [x, y] point | ||
// | ||
var co, si, x, y, shat, rhat, txhat, tyhat | ||
co = Math.cos(radians) | ||
si = Math.sin(radians) | ||
if (typeof pivot === 'undefined') { | ||
x = y = 0 | ||
} else { | ||
x = pivot[0] | ||
y = pivot[1] | ||
} | ||
shat = this.s * co - this.r * si | ||
rhat = this.s * si + this.r * co | ||
txhat = (this.tx - x) * co - (this.ty - y) * si + x | ||
tyhat = (this.tx - x) * si + (this.ty - y) * co + y | ||
this.multiplyRight = | ||
this.multiplyBy = function (transform) { | ||
// Multiply this transformation matrix A | ||
// from the right with the given transformation matrix B | ||
// and return the result AB | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
} | ||
// For reading aid: | ||
// s -r tx t.s -r tx | ||
// r s ty * r s ty | ||
// 0 0 1 0 0 1 | ||
var t = transform // alias | ||
var shat = s * t.s - r * t.r | ||
var rhat = s * t.r + r * t.s | ||
var txhat = s * t.tx - r * t.ty + tx | ||
var tyhat = r * t.tx + s * t.ty + ty | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
} | ||
proto.multiplyRight = | ||
proto.multiplyBy = function (transform) { | ||
// Multiply this transformation matrix A | ||
// from the right with the given transformation matrix B | ||
// and return the result AB | ||
// For reading aid: | ||
// s -r tx t.s -r tx | ||
// r s ty * r s ty | ||
// 0 0 1 0 0 1 | ||
var t = transform // alias | ||
var shat = this.s * t.s - this.r * t.r | ||
var rhat = this.s * t.r + this.r * t.s | ||
var txhat = this.s * t.tx - this.r * t.ty + this.tx | ||
var tyhat = this.r * t.tx + this.s * t.ty + this.ty | ||
return new Transform(shat, rhat, txhat, tyhat) | ||
} | ||
@@ -148,0 +219,0 @@ |
// generated by genversion | ||
module.exports = '1.3.1' | ||
module.exports = '1.4.0' |
{ | ||
"name": "nudged", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "Affine transformation estimator e.g. for multi-touch gestures and calibration", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -262,4 +262,16 @@ # nudged | ||
### nudged.Transform#equals(tr) | ||
### nudged.Transform#almostEqual(tr, epsilon?) | ||
Compare equality of two transformations and allow small differences that likely occur due to floating point arithmetics. | ||
**Alias** `.almostEquals(tr)` | ||
**Parameter** `tr` is an instance of `nudged.Transform`. Optional parameter `epsilon` is a small number that defines largest allowed difference and defaults to `Transform.EPSILON`. The difference is computed as the sum of absolute differences of the properties s, r, tx, and ty. | ||
**Return** true if the parameters of the two transformations are equal or almost equal and false otherwise. | ||
### nudged.Transform#equal(tr) | ||
**Alias** `.equals(tr)` | ||
**Parameter** `tr` is an instance of `nudged.Transform`. | ||
@@ -346,4 +358,6 @@ | ||
### nudged.Transform#multiplyBy(tr) alias #multiplyRight(tr) | ||
### nudged.Transform#multiplyBy(tr) | ||
**Alias** `.multiplyRight(tr)` | ||
**Parameter** `tr` is an instance of `nudged.Transform`. | ||
@@ -350,0 +364,0 @@ |
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
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
37826
600
423