-
-
Save thierryc/5dc31333e2224729f94200e2b33199e0 to your computer and use it in GitHub Desktop.
Decomposing a 2D transformation matrix to find the skew
This file contains hidden or 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