| 1 | = Calculating coefficients for Affine Transformation = |
| 2 | |
| 3 | == Introduction == |
| 4 | |
| 5 | Geospatial rasters inherently have two coordinate systems associated with them: pixel indices and real world coordinates. Although some rasters have a very complex relationship between these two coordinate systems, many have a set of simple linear relationships between the two coordinate systems. These simple linear relationships are ''modular'' and may be combined in many ways. Regardless of the order in which they are combined, an affine transform results. The transform is then used to convert coordinates between the two coordinate systems of the raster. This page describes a set of ubiquitous individual transformations and demonstrates how they may be combined to produce an affine transformation. |
| 6 | |
| 7 | == Individual operations == |
| 8 | |
| 9 | This page discusses operations in two dimensions only. Each operation is presented as a 2x2 matrix, and each operation performs only one function. These operations were taken from [http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics wikipedia]. While the matrices presented here contain the bulk of the functionality of a finished affine transform, they are not ''complete'' affine transforms themselves. |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | Starting from the beginning: We want to be able to calculate the |
| 15 | parameters for an affine transform which includes the operations: |
| 16 | scaling, translation, rotation, and skew (shearing). Matrices for |
| 17 | these individual operations are found on |
| 18 | http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics |
| 19 | . What ho! We can combine these individual operations willy nilly by |
| 20 | matrix multiplication. But note that these individual matrices are the |
| 21 | only places where individual coefficients represent meaningful |
| 22 | parameters. Once you start the multiplication, the coefficients become |
| 23 | all jumbled up with terms combined in various ways. |
| 24 | |
| 25 | So, using wikipedia plus a little customization, I've labeled the PURE |
| 26 | coefficients (as opposed to our jumbled coefficients) as follows: |
| 27 | |
| 28 | Sx : scale in the x direction |
| 29 | Sy : scale in the y direction |
| 30 | Tx : translation in the x direction |
| 31 | Ty : translation in the y direction |
| 32 | Kx : shearing parallel to x axis |
| 33 | Ky : shearing parallel to y axis |
| 34 | theta : angle of rotation CLOCKWISE around the origin (not around the |
| 35 | x axis, not around the y axis: around the origin; or if you like, |
| 36 | around the invisible Z axis coming out of the screen and poking you in |
| 37 | the eye.) |
| 38 | |
| 39 | The next step is to define an order. I chose: "Scale followed by |
| 40 | rotation followed by shearing (skew)". |
| 41 | |
| 42 | Multiplying these matrices together, as described here |
| 43 | (http://en.wikipedia.org/wiki/Transformation_matrix#Composing_and_inverting_transformations) |
| 44 | gives a 2x2 matrix, which is not an affine transform yet. Let's label |
| 45 | the coefficients of this matrix as follows |
| 46 | |
| 47 | | O11 O12 | |
| 48 | | O21 O22 | |
| 49 | |
| 50 | (I apologize for the ascii graphics throughout. Gmail is not using a |
| 51 | monospaced font even in "plain text" mode.) |
| 52 | |
| 53 | So what I get for these coefficients (after multiplying in the order |
| 54 | specified) is: |
| 55 | |
| 56 | O11 = Sx * (cos(theta) + Ky sin(theta)) |
| 57 | O12 = Sx * (Kx cos(theta) + sin(theta)) |
| 58 | O21 = Sy * (-sin(theta) + Ky cos(theta)) |
| 59 | O22 = Sy * (-Kx * sin(theta) + cos(theta)) |
| 60 | |
| 61 | And the final bit is to add translation by making this into an affine transform: |
| 62 | |
| 63 | | O11 O12 O13 | |
| 64 | | O21 O22 O23 | |
| 65 | | 0 0 1 | |
| 66 | |
| 67 | where: |
| 68 | |
| 69 | O13 = Tx |
| 70 | O23 = Ty |
| 71 | |
| 72 | To be pedantic, this is used as follows: |
| 73 | |
| 74 | | E | | O11 O12 O13 | | i | |
| 75 | | N | = | O21 O22 O23 | | j | |
| 76 | | 1 | | 0 0 1 | | 1 | |
| 77 | |
| 78 | where: |
| 79 | E = easting |
| 80 | N = northing |
| 81 | i = pixel column |
| 82 | j = pixel row |
| 83 | |
| 84 | |
| 85 | The coefficients map onto our jumbled named coefficients as follows : |
| 86 | |
| 87 | ScaleX = O11 |
| 88 | SkewX = O12 |
| 89 | OffsetX = O13 |
| 90 | SkewY = O21 |
| 91 | ScaleY = O22 |
| 92 | OffsetY = O23 |
| 93 | |
| 94 | The important thing to note is that the things we're rather loosely |
| 95 | calling Scale[XY] and Skew[XY] represent all of Scale, Rotation and |
| 96 | Shearing. This dictates that you cannot set these coefficients without |
| 97 | knowing all three. |