Created
March 16, 2012 19:58
-
-
Save fwextensions/2052247 to your computer and use it in GitHub Desktop.
Decomposing a 2D transformation matrix to find the skew
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This code takes a 2D transformation matrix described as a one-dimensional array | |
(in column order, top to bottom and left to right) and decomposes it using the dojo | |
matrix library. This input matrix should produce a 45-deg X skew: | |
1 1 0 | |
0 1 0 | |
0 0 1 | |
The output of decompose() looks like this: | |
{ | |
angle1: -58.282525588538995, | |
angle2: 31.71747441146101, | |
dx: 0, | |
dy: 0, | |
sx: 1.6180339887498953, | |
sy: 0.618033988749895 | |
} | |
So two rotations and two scales presumably produce the skew, but there's no obvious way | |
to go from this to the 45-deg angle that could then be used in CSS3 skew transform, like | |
transform:skew(45deg); | |
*/ | |
dojo.require("dojox.gfx.decompose"); | |
function decompose( | |
inMatrix) | |
{ | |
var matrix = new dojox.gfx.matrix.Matrix2D({ | |
xx: inMatrix[0], | |
yx: inMatrix[1], | |
xy: inMatrix[3], | |
yy: inMatrix[4], | |
dx: inMatrix[6], | |
dy: inMatrix[7] | |
}); | |
var decomposed = dojox.gfx.decompose(matrix); | |
decomposed.angle1 *= 180 / Math.PI; | |
decomposed.angle2 *= 180 / Math.PI; | |
return decomposed; | |
} | |
log(decompose([1, 0, 0, 1, 1, 0, 0, 0, 1])); | |
/* | |
Here's Aaron's ActionScript decomposition code, converted to JS so it can run in | |
Fireworks. You can do something like asDecompose(fw.selection[0].transform.matrix) to | |
decompose the transform of the current selection. | |
*/ | |
function Point(x, y) | |
{ | |
return { x: x, y: y }; | |
} | |
function matrixTransforms(matrix) { | |
// calculate delta transform point | |
var px = deltaTransformPoint(matrix, new Point(0, 1)); | |
var py = deltaTransformPoint(matrix, new Point(1, 0)); | |
// calculate skew | |
var skewX = ((180 / Math.PI) * Math.atan2(px.y, px.x) - 90); | |
var skewY = ((180 / Math.PI) * Math.atan2(py.y, py.x)); | |
return { | |
translateX:matrix.tx, | |
translateY:matrix.ty, | |
scaleX:Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b), | |
scaleY:Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d), | |
skewX:skewX, | |
skewY:skewY, | |
rotation:skewX // rotation is the same as skew x | |
} | |
} | |
function deltaTransformPoint(matrix, point) { | |
//return matrix.deltaTransformPoint(point); | |
var dx = point.x * matrix.a + point.y * matrix.c + 0; | |
var dy = point.x * matrix.b + point.y * matrix.d + 0; | |
return new Point(dx, dy); | |
} | |
function asDecompose( | |
inMatrix) | |
{ | |
var matrix = { | |
a: inMatrix[0], | |
c: inMatrix[1], | |
b: inMatrix[3], | |
d: inMatrix[4], | |
tx: inMatrix[6], | |
ty: inMatrix[7] | |
}; | |
return matrixTransforms(matrix); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Dear,
It don't seems to work, the skew and rotation values are probably wrong, how the SkewX can be always equal to the rotation ?
With this matrix example :
matrix(0.214, -0.303, 0.246, 0.242, 300, 300)
I get :
translate(300.0, 300.0),
scale(0.370951479307, 0.345079700939),
rotate(-45.4696271749),
skewX(-45.4696271749),
skewY(-54.7675619191)
Wich is not the same transform at all.