| /*! |
| Transformation Matrix v2.0 |
| (c) Epistemex 2014-2015 |
| www.epistemex.com |
| By Ken Fyrstenberg |
| Contributions by leeoniya. |
| License: MIT, header required. |
| */ |
| |
| /** |
| * 2D transformation matrix object initialized with identity matrix. |
| * |
| * The matrix can synchronize a canvas context by supplying the context |
| * as an argument, or later apply current absolute transform to an |
| * existing context. |
| * |
| * All values are handled as floating point values. |
| * |
| * @param {CanvasRenderingContext2D} [context] - Optional context to sync with Matrix |
| * @prop {number} a - scale x |
| * @prop {number} b - shear y |
| * @prop {number} c - shear x |
| * @prop {number} d - scale y |
| * @prop {number} e - translate x |
| * @prop {number} f - translate y |
| * @prop {CanvasRenderingContext2D|null} [context=null] - set or get current canvas context |
| * @constructor |
| */ |
| |
| var Matrix = (function(){ |
| |
| function reset(){ |
| this.props[0] = 1; |
| this.props[1] = 0; |
| this.props[2] = 0; |
| this.props[3] = 0; |
| this.props[4] = 0; |
| this.props[5] = 1; |
| this.props[6] = 0; |
| this.props[7] = 0; |
| this.props[8] = 0; |
| this.props[9] = 0; |
| this.props[10] = 1; |
| this.props[11] = 0; |
| this.props[12] = 0; |
| this.props[13] = 0; |
| this.props[14] = 0; |
| this.props[15] = 1; |
| return this; |
| } |
| |
| function rotate(angle) { |
| if(angle === 0){ |
| return this; |
| } |
| var mCos = Math.cos(angle); |
| var mSin = Math.sin(angle); |
| return this._t(mCos, -mSin, 0, 0 |
| , mSin, mCos, 0, 0 |
| , 0, 0, 1, 0 |
| , 0, 0, 0, 1); |
| } |
| |
| function rotateX(angle){ |
| if(angle === 0){ |
| return this; |
| } |
| var mCos = Math.cos(angle); |
| var mSin = Math.sin(angle); |
| return this._t(1, 0, 0, 0 |
| , 0, mCos, -mSin, 0 |
| , 0, mSin, mCos, 0 |
| , 0, 0, 0, 1); |
| } |
| |
| function rotateY(angle){ |
| if(angle === 0){ |
| return this; |
| } |
| var mCos = Math.cos(angle); |
| var mSin = Math.sin(angle); |
| return this._t(mCos, 0, mSin, 0 |
| , 0, 1, 0, 0 |
| , -mSin, 0, mCos, 0 |
| , 0, 0, 0, 1); |
| } |
| |
| function rotateZ(angle){ |
| if(angle === 0){ |
| return this; |
| } |
| var mCos = Math.cos(angle); |
| var mSin = Math.sin(angle); |
| return this._t(mCos, -mSin, 0, 0 |
| , mSin, mCos, 0, 0 |
| , 0, 0, 1, 0 |
| , 0, 0, 0, 1); |
| } |
| |
| function shear(sx,sy){ |
| return this._t(1, sy, sx, 1, 0, 0); |
| } |
| |
| function skew(ax, ay){ |
| return this.shear(Math.tan(ax), Math.tan(ay)); |
| } |
| |
| function skewFromAxis(ax, angle){ |
| var mCos = Math.cos(angle); |
| var mSin = Math.sin(angle); |
| return this._t(mCos, mSin, 0, 0 |
| , -mSin, mCos, 0, 0 |
| , 0, 0, 1, 0 |
| , 0, 0, 0, 1) |
| ._t(1, 0, 0, 0 |
| , Math.tan(ax), 1, 0, 0 |
| , 0, 0, 1, 0 |
| , 0, 0, 0, 1) |
| ._t(mCos, -mSin, 0, 0 |
| , mSin, mCos, 0, 0 |
| , 0, 0, 1, 0 |
| , 0, 0, 0, 1); |
| //return this._t(mCos, mSin, -mSin, mCos, 0, 0)._t(1, 0, Math.tan(ax), 1, 0, 0)._t(mCos, -mSin, mSin, mCos, 0, 0); |
| } |
| |
| function scale(sx, sy, sz) { |
| sz = isNaN(sz) ? 1 : sz; |
| if(sx == 1 && sy == 1 && sz == 1){ |
| return this; |
| } |
| return this._t(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1); |
| } |
| |
| function setTransform(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) { |
| this.props[0] = a; |
| this.props[1] = b; |
| this.props[2] = c; |
| this.props[3] = d; |
| this.props[4] = e; |
| this.props[5] = f; |
| this.props[6] = g; |
| this.props[7] = h; |
| this.props[8] = i; |
| this.props[9] = j; |
| this.props[10] = k; |
| this.props[11] = l; |
| this.props[12] = m; |
| this.props[13] = n; |
| this.props[14] = o; |
| this.props[15] = p; |
| return this; |
| } |
| |
| function translate(tx, ty, tz) { |
| tz = tz || 0; |
| if(tx !== 0 || ty !== 0 || tz !== 0){ |
| return this._t(1,0,0,0,0,1,0,0,0,0,1,0,tx,ty,tz,1); |
| } |
| return this; |
| } |
| |
| function transform(a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2, l2, m2, n2, o2, p2) { |
| |
| if(a2 === 1 && b2 === 0 && c2 === 0 && d2 === 0 && e2 === 0 && f2 === 1 && g2 === 0 && h2 === 0 && i2 === 0 && j2 === 0 && k2 === 1 && l2 === 0){ |
| if(m2 !== 0 || n2 !== 0 || o2 !== 0){ |
| |
| this.props[12] = this.props[12] * a2 + this.props[13] * e2 + this.props[14] * i2 + this.props[15] * m2 ; |
| this.props[13] = this.props[12] * b2 + this.props[13] * f2 + this.props[14] * j2 + this.props[15] * n2 ; |
| this.props[14] = this.props[12] * c2 + this.props[13] * g2 + this.props[14] * k2 + this.props[15] * o2 ; |
| this.props[15] = this.props[12] * d2 + this.props[13] * h2 + this.props[14] * l2 + this.props[15] * p2 ; |
| } |
| return this; |
| } |
| |
| var a1 = this.props[0]; |
| var b1 = this.props[1]; |
| var c1 = this.props[2]; |
| var d1 = this.props[3]; |
| var e1 = this.props[4]; |
| var f1 = this.props[5]; |
| var g1 = this.props[6]; |
| var h1 = this.props[7]; |
| var i1 = this.props[8]; |
| var j1 = this.props[9]; |
| var k1 = this.props[10]; |
| var l1 = this.props[11]; |
| var m1 = this.props[12]; |
| var n1 = this.props[13]; |
| var o1 = this.props[14]; |
| var p1 = this.props[15]; |
| |
| /* matrix order (canvas compatible): |
| * ace |
| * bdf |
| * 001 |
| */ |
| this.props[0] = a1 * a2 + b1 * e2 + c1 * i2 + d1 * m2; |
| this.props[1] = a1 * b2 + b1 * f2 + c1 * j2 + d1 * n2 ; |
| this.props[2] = a1 * c2 + b1 * g2 + c1 * k2 + d1 * o2 ; |
| this.props[3] = a1 * d2 + b1 * h2 + c1 * l2 + d1 * p2 ; |
| |
| this.props[4] = e1 * a2 + f1 * e2 + g1 * i2 + h1 * m2 ; |
| this.props[5] = e1 * b2 + f1 * f2 + g1 * j2 + h1 * n2 ; |
| this.props[6] = e1 * c2 + f1 * g2 + g1 * k2 + h1 * o2 ; |
| this.props[7] = e1 * d2 + f1 * h2 + g1 * l2 + h1 * p2 ; |
| |
| this.props[8] = i1 * a2 + j1 * e2 + k1 * i2 + l1 * m2 ; |
| this.props[9] = i1 * b2 + j1 * f2 + k1 * j2 + l1 * n2 ; |
| this.props[10] = i1 * c2 + j1 * g2 + k1 * k2 + l1 * o2 ; |
| this.props[11] = i1 * d2 + j1 * h2 + k1 * l2 + l1 * p2 ; |
| |
| this.props[12] = m1 * a2 + n1 * e2 + o1 * i2 + p1 * m2 ; |
| this.props[13] = m1 * b2 + n1 * f2 + o1 * j2 + p1 * n2 ; |
| this.props[14] = m1 * c2 + n1 * g2 + o1 * k2 + p1 * o2 ; |
| this.props[15] = m1 * d2 + n1 * h2 + o1 * l2 + p1 * p2 ; |
| |
| return this; |
| } |
| |
| function clone(matr){ |
| var i; |
| for(i=0;i<16;i+=1){ |
| matr.props[i] = this.props[i]; |
| } |
| } |
| |
| function cloneFromProps(props){ |
| var i; |
| for(i=0;i<16;i+=1){ |
| this.props[i] = props[i]; |
| } |
| } |
| |
| function applyToPoint(x, y, z) { |
| |
| return { |
| x: x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12], |
| y: x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13], |
| z: x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14] |
| }; |
| /*return { |
| x: x * me.a + y * me.c + me.e, |
| y: x * me.b + y * me.d + me.f |
| };*/ |
| } |
| function applyToX(x, y, z) { |
| return x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12]; |
| } |
| function applyToY(x, y, z) { |
| return x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13]; |
| } |
| function applyToZ(x, y, z) { |
| return x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]; |
| } |
| |
| function inversePoint(pt){ |
| //var determinant = this.a * this.d - this.b * this.c; |
| var determinant = this.props[0] * this.props[5] - this.props[1] * this.props[4]; |
| var a = this.props[5]/determinant; |
| var b = - this.props[1]/determinant; |
| var c = - this.props[4]/determinant; |
| var d = this.props[0]/determinant; |
| var e = (this.props[4] * this.props[13] - this.props[5] * this.props[12])/determinant; |
| var f = - (this.props[0] * this.props[13] - this.props[1] * this.props[12])/determinant; |
| return [pt[0] * a + pt[1] * c + e, pt[0] * b + pt[1] * d + f, 0]; |
| } |
| |
| function inversePoints(pts){ |
| var i, len = pts.length, retPts = []; |
| for(i=0;i<len;i+=1){ |
| retPts[i] = inversePoint(pts[i]); |
| } |
| return retPts; |
| } |
| |
| function applyToPointArray(x,y,z,dimensions){ |
| if(dimensions && dimensions === 2) { |
| var arr = point_pool.newPoint(); |
| arr[0] = x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12]; |
| arr[1] = x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13]; |
| return arr; |
| } |
| return [x * this.props[0] + y * this.props[4] + z * this.props[8] + this.props[12],x * this.props[1] + y * this.props[5] + z * this.props[9] + this.props[13],x * this.props[2] + y * this.props[6] + z * this.props[10] + this.props[14]]; |
| } |
| function applyToPointStringified(x, y) { |
| return (bm_rnd(x * this.props[0] + y * this.props[4] + this.props[12]))+','+(bm_rnd(x * this.props[1] + y * this.props[5] + this.props[13])); |
| } |
| |
| function toArray() { |
| return [this.props[0],this.props[1],this.props[2],this.props[3],this.props[4],this.props[5],this.props[6],this.props[7],this.props[8],this.props[9],this.props[10],this.props[11],this.props[12],this.props[13],this.props[14],this.props[15]]; |
| } |
| |
| function toCSS() { |
| if(isSafari){ |
| return "matrix3d(" + roundTo2Decimals(this.props[0]) + ',' + roundTo2Decimals(this.props[1]) + ',' + roundTo2Decimals(this.props[2]) + ',' + roundTo2Decimals(this.props[3]) + ',' + roundTo2Decimals(this.props[4]) + ',' + roundTo2Decimals(this.props[5]) + ',' + roundTo2Decimals(this.props[6]) + ',' + roundTo2Decimals(this.props[7]) + ',' + roundTo2Decimals(this.props[8]) + ',' + roundTo2Decimals(this.props[9]) + ',' + roundTo2Decimals(this.props[10]) + ',' + roundTo2Decimals(this.props[11]) + ',' + roundTo2Decimals(this.props[12]) + ',' + roundTo2Decimals(this.props[13]) + ',' + roundTo2Decimals(this.props[14]) + ',' + roundTo2Decimals(this.props[15]) + ')'; |
| } else { |
| this.cssParts[1] = this.props.join(','); |
| return this.cssParts.join(''); |
| } |
| } |
| |
| function to2dCSS() { |
| return "matrix(" + this.props[0] + ',' + this.props[1] + ',' + this.props[4] + ',' + this.props[5] + ',' + this.props[12] + ',' + this.props[13] + ")"; |
| } |
| |
| function toString() { |
| return "" + this.toArray(); |
| } |
| |
| return function(){ |
| this.reset = reset; |
| this.rotate = rotate; |
| this.rotateX = rotateX; |
| this.rotateY = rotateY; |
| this.rotateZ = rotateZ; |
| this.skew = skew; |
| this.skewFromAxis = skewFromAxis; |
| this.shear = shear; |
| this.scale = scale; |
| this.setTransform = setTransform; |
| this.translate = translate; |
| this.transform = transform; |
| this.applyToPoint = applyToPoint; |
| this.applyToX = applyToX; |
| this.applyToY = applyToY; |
| this.applyToZ = applyToZ; |
| this.applyToPointArray = applyToPointArray; |
| this.applyToPointStringified = applyToPointStringified; |
| this.toArray = toArray; |
| this.toCSS = toCSS; |
| this.to2dCSS = to2dCSS; |
| this.toString = toString; |
| this.clone = clone; |
| this.cloneFromProps = cloneFromProps; |
| this.inversePoints = inversePoints; |
| this.inversePoint = inversePoint; |
| this._t = this.transform; |
| |
| this.props = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]; |
| |
| this.cssParts = ['matrix3d(','',')']; |
| } |
| }()); |
| |
| function Matrix() { |
| |
| |
| } |