Skip to content

Instantly share code, notes, and snippets.

@fwextensions
Created March 16, 2012 19:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save fwextensions/2052247 to your computer and use it in GitHub Desktop.
Save fwextensions/2052247 to your computer and use it in GitHub Desktop.
Decomposing a 2D transformation matrix to find the skew
/*
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);
}
@Gust5
Copy link

Gust5 commented Oct 19, 2013

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment