Я бы сказал, что ООП со статической и динамической типизацией - это две отдельные дисциплины в одной и той же школе ООП.
Предполагая, что преобразование ТОЛЬКО содержит вращение, это просто: просто возьмите acos элемента m11.
Он все еще работает, если преобразование содержит перевод, но если он содержит срезание или масштабирование, вам не повезло. Их можно восстановить, разложив матрицу на матрицу сдвига, масштабирования и поворота, но получаемые вами результаты, скорее всего, не такие, какие вы ищете.
Самый простой общий способ - преобразовать (0,0) и (1,0), а затем использовать тригонометрические функции (arctan), чтобы получить угол
Матрица преобразования - это реализация, используемая для трехмерной графики. Это упрощает математику, чтобы ускорить трехмерную позиционную / поворотную ориентацию точек / объектов. Действительно, очень трудно вырвать ориентацию из Преобразования из-за того, как оно накапливает последовательные перемещения / вращения / масштабы.
Вот предложение. Возьмите вектор, который указывает в простом направлении, например (1,0,0), а затем примените к нему преобразование. Полученный вектор будет преобразован и повернут, чтобы получить что-то вроде этого: (27,8, 19,2, 77,4). Примените преобразование к (0,0,0), чтобы получить что-то вроде (26.1, 19.4, 50.8). Вы можете использовать эти две точки для расчета примененных вращений, зная их начальные точки (1,0,0).
Помогает ли это?
Обычно вам нужна обратная триггерная функция, но вам нужно остерегаться двусмысленности квадрантов, и это то, что вы должны использовать atan2 (иногда пишется как arctan2). Итак, либо поверните единичный вектор [0, 1] в [x, y], а затем используйте atan2 (y, x), либо, если матрица реализует только поворот, вы можете использовать atan2 (m12, m11). (Они похожи на ответы Хавьера и Нильса, за исключением того, что в них не используется atan2.)