kreek - 1 year ago 124

ActionScript Question

I know a matrix [x scale, y skew, x skew, y scale, trans x, trans y], and would like to get the angle in degrees.

thanks!

Answer Source

Consider the following matrix

```
| x_sc y_sk 0 |
| x_sk y_sc 0 |
| x_tr y_tr 1 |
```

with `sk`

indicating skew, `sc`

indicating scale and `tr`

indicating translation.

This only represents a **pure** rotation if all three are true

```
y_sk == -x_sk
y_sc == x_sc
x_sc * y_sc - x_sk * y_sk == 1
```

In this case, if `theta`

is the angle of rotation, then

```
theta == arcos(x_sc)
```

This will give you the answer in radians (most likely), so you'll need to convert to degrees.

Assuming you have an object called M, representing the matrix, the properties that match my definitions above, you could do:

```
function toPureRotation(var M) {
if( (M.y_sk != (-1 * M.x_sk)) ||
(M.y_sc != M.x_sc) ||
((M.x_sc * M.y_sc - M.x_sk * M.y_sk) != 1)
) {
return Number.NaN;
}
else {
return Math.acos(M.x_sc); // For radians
return Math.acos(M.x_sc) * 180 / Math.PI; // For degrees
}
}
```

**EDIT**

For a pure rotation followed by (or preceded by) a scaling transform that maintains aspect ratio:

```
| sc 0 0 |
| 0 sc 0 |
| 0 0 1 |
```

Then you can us the following identity:

```
x_sc * y_sc - x_sk * y_sk == sc^2
```

This gives us

```
function toRotation(var M) {
if( (M.y_sk != (-1 * M.x_sk)) ||
(M.y_sc != M.x_sc)
)
) {
return Number.NaN;
}
else {
var scale_factor = Math.sqrt((M.x_sc * M.y_sc - M.x_sk * M.y_sk));
return Math.acos(M.x_sc/scale_factor); // For radians
return Math.acos(M.x_sc/scale_factor) * 180 / Math.PI; // For degrees
}
}
```

If you want to factor in translations, you're entering a world of hurt.