Аффинное преобразование - это специальная матрица 3x3, используемая для применения перемещения, поворота, сдвига или перекоса и масштабирования к системам координат в двухмерных графических контекстах.

Аффинное преобразование - это специальная матрица 3x3, используемая для применения перемещения, поворота, сдвига или перекоса и масштабирования к системам координат в двухмерных графических контекстах. Параллельные линии останутся параллельными, поэтому перспектива не может быть применена. Угол между линиями, которые не параллельны, может быть изменен с помощью операций перекоса.

a c x b d y 0 0 1 

Нижний ряд аффинного преобразования всегда равен 0 0 1, поэтому аффинное преобразование описывается только шестью значениями. Преобразование точки является основой всех операций с аффинными преобразованиями.

new.x = old.x * at.a + old.y * at.c + at.x new.y = old.x * at.b + old.y * at.d + at.y 

Идентификационное преобразование преобразует точку в себя.

1 0 0 0 1 0 0 0 1 

Значения x и y (часто называемые tx и ty) будут переводить точку. Значения a b c d применяют вращение, сдвиг и масштаб к точке. Следующее аффинное преобразование будет вращать точку на r радиан вокруг начала координатного пространства.

 cos(r) sin(r) 0 -sin(r) cos(r) 0 0 0 1 

Чтобы применить сдвиг или перекос по радианам rx и ry, используйте следующую матрицу. При положительном значении rx вертикальные линии будут казаться наклоненными влево, а при положительном значении ry горизонтальные линии будут скользить вниз вправо.

 1 tan(rx) 0 tan(ry) 1 0 0 0 1 

Масштабирование применяется более непосредственно. Для масштабирования по sx и sy используйте следующую матрицу. Использование отрицательного масштаба будет отражать или отражать систему координат вокруг оси. Например, использование -1 для sy в этой матрице перевернет систему координат вверх ногами.

sx 0 0 0 sy 0 0 0 1 

Чтобы применить несколько эффектов одновременно, можно объединить несколько матриц аффинного преобразования. Порядок объединения имеет значение. Порядок наименьшего удивления - перевести, повернуть, наклонить, затем масштабировать. Это также, как преобразование будет восприниматься, независимо от первоначального порядка операций.

Для поворота вокруг точки, отличной от начала координат, операция поворота заключена в скобки с помощью операций перевода. Второй перевод будет в направлении поворота, так как перевод будет объединен после поворота.

translate(-x,-y) rotate(r) translate(x,y) 

В тех случаях, когда преобразование связано с конкретным визуальным элементом, таким как css или CALayer, может существовать источник преобразования, который неявно транслирует аффинное преобразование. Помните об этом, если вам нужно переводить между координатными пространствами.

Чтобы объединить два аффинных преобразования u и v в преобразование new, сделайте следующее.

new.a = u.a * v.a + u.c * v.b new.b = u.b * v.a + u.d * v.b new.c = u.a * v.c + u.c * v.d new.d = u.b * v.c + u.d * v.d new.x = u.a * v.x + u.c * v.y + u.x new.y = u.b * v.x + u.d * v.y + u.y 

Обратную матрицу можно вычислить, если определитель не равен нулю. Преобразование точки аффинным преобразованием и обратным аффинным преобразованием восстановит исходную точку.

determinant = a*d - b*c inverse.a = d/determinant inverse.b = -b/determinant inverse.c = -c/determinant inverse.d = a/determinant inverse.x = (c*y - d*x)/determinant inverse.y = (b*x - a*y)/determinant 

Перевод аффинного преобразования всегда доступен в виде значений x и y. Другие входы также могут быть извлечены. Для аффинного преобразования, которое, как известно, не имеет перекоса, вращение и масштаб можно рассчитать следующим образом.

r = atan2( c , d ) sx = sqrt( a*a + b*b ) sy = sqrt( d*d + c*c ) 

Вращение, перекос и масштаб могут быть вычислены для произвольного аффинного преобразования. Это будут значения восприятия в порядке наименьшего удивления, а не входные значения. Когда аффинное преобразование поворачивается и наклоняется, или наклоняется вдоль обеих осей, будет два значения вращения. Наименьшее из них будет вращением восприятия, а разница - перекосом.

if ( a*d < 0 ) { if ( a < 0 ) { flip = 1; a = -a; b = -b; } else { flip = 2; d = -d; c = -c; } } else { flip = 0 } rx = atan2( -b , a ) ry = atan2( c , d ) if ( abs( rx ) < abs( ry ) ) { r = rx skew_rx = 0 skew_ry = ry - rx scale_x = sqrt( a*a + b*b ) scale_y = d / (cos(r) - sin(r)*tan(skew_ry)) } else { r = ry skew_ry = 0 skew_rx = ry - rx scale_y = sqrt( d*d + c*c ) scale_x = a / (cos(r) + sin(r)*tan(skew_rx)) } if ( 1 == flip ) scale_x = -scale_x; if ( 2 == flip ) scale_y = -scale_y; 

Исходная матрица будет равна объединению следующих эффектов.

translate(x,y) rotate(r) skew(skew_rx,skew_ry) scale(scale_x,scale_y) 

Это можно использовать для проверки того, что преобразование будет восприниматься как задуманное. Когда все операции поворота, перекоса и масштабирования объединены, масштабирование может быть искажено, если перекос и поворот не являются взаимодополняющими.

Документация по аффинным преобразованиям для некоторых популярных платформ: