Рассмотрим следующую матрицу
| x_sc y_sk 0 |
| x_sk y_sc 0 |
| x_tr y_tr 1 |
с sk
указывает на перекос, sc
указывает на масштаб и tr
указывает на перевод.
Это представляет чистое вращение, если все три истинны
y_sk == -x_sk
y_sc == x_sc
x_sc * y_sc - x_sk * y_sk == 1
В этом случае, если theta
- угол поворота, то
theta == arcos(x_sc)
Это даст вам ответ в радианах (скорее всего), поэтому вам нужно пересчитать в градусы.
Предполагая, что у вас есть объект с именем M, представляющий матрицу, свойства, которые соответствуют моим определениям выше, вы можете сделать:
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
Для чистого поворота, за которым следует (или предшествует) преобразование масштабирования, которое поддерживает соотношение сторон:
| sc 0 0 |
| 0 sc 0 |
| 0 0 1 |
Тогда вы можете нам следующую личность:
x_sc * y_sc - x_sk * y_sk == sc^2
Это дает нам
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
}
}
Если вы хотите учесть переводы, вы попадаете в мир боли.