Transformation Matrices – 2D Demo

The theory of matrices was first developed (or so I read) in relation to geometric transformations.

The best single reference that explained Transformation Matrices to me esp with regards to graphics programming was Rod Stephens book Visual Basic Graphics Programming, which is 20+ years old. It’s a comprehensive but clear introduction. There are also many linear algebra math videos on Khan, Youtube etc that i am just starting to explore. Stephens multiplies his vector from the left of the matrix. Everyone else does it from the right, so i cannot use his examples as-is, but looking at his methods has been very helpful.

A vector is also a matrix, and its a point. Multiplying a square matrix by a column vector yields another column vector. Thats how the point gets transformed. The transformation matrix can contain numbers for scaling, translating (moving) and rotation.

The basic idea can be shown with a 2D autocad implementation and then extend to full 3D. Matrix math, and multiplication of matrices is somewhat hard to grasp, but programming it from scratch is good reinforcement. The basic 3D matrix is a 4×4 grid of doubles. The 2D matrix is 3×3.

The first sub initializes an identity matrix, which is the base. The subs that create Translation, Scaling and Rotation numbers will modify the identity matrix. To combine these operations into one, multiplication of two 3×3 matrices is done. Finally to apply the matrix to a point, the matrix is multiplied by the 1×3 point vector.

In reality, we are going to use arrays as matrices, and the array of a 1×3 is actually just a 3, but we are going to treat it as a column. arrays start with index zero. Most matrix references or maybe all use 1 as the base number.

Here is the 3×3 initial matrix with value 1 on the main diagonal and zero elsewhere. Its a function that returns the result and does not take any arguments.

show_mat(M) is a sub to show the matrix in the immediate window screen for checking.

    Public Function m3x3_ID() As Double(,)
        Dim M(0 To 2, 0 To 2) As Double
        Dim i, j As Integer

        For i = 0 To 2
            For j = 0 To 2
                If i = j Then
                    M(i, j) = 1
                    M(i, j) = 0
                End If

        Return M
    End Function

    Public Sub show_mat(M(,) As Double)
        Dim i, j As Integer
        Dim str As String = ""
        For i = 0 To UBound(M, 1)
            For j = 0 To UBound(M, 2)
                If j = 0 Then
                    str = str & vbCrLf
                End If
                str = str & M(i, j) & vbTab

    End Sub

We need a sub to multiply a 3×3 matrix by a 1×3 vector. MxV. This is a simple program that takes the Matrix and Vector as arguments and returns a Vector.
For 2D the Z value is not required but is required by autocad, leading to a bit of complication we wont have with 3D.

    Function MxV(M(,) As Double, V() As Double) As Double()
        Dim V2(2) As Double

        V2(0) = M(0, 0) * V(0) + M(0, 1) * V(1) + M(0, 2) * 1
        V2(1) = M(1, 0) * V(0) + M(1, 1) * V(1) + M(1, 2) * 1
        V2(2) = M(2, 0) * V(0) + M(2, 1) * V(1) + M(2, 2) * 1

        'need to zero this out for 2D demo purpose
        V2(2) = 0

        Return V2

    End Function

Matrices are combined by multiplication. I still have to show myself why that works, when rotation and scaling use the same cells. The multiplication of two 3×3 matrices is row by column. You could do it with brute force, but studying the concise math definition –

c(ij) = a(i1)b(1j) + a(i2)b(2j) + a(i3)b(3j)

– shows the basic i and j loop variables and the third variable just goes from 1 to 3. Modifying slightly for our 0 to 2 array gives a 3 variable loop. Matrices A and B are 3×3. The order matters. Multiplication is not commutative. A movement then a rotation is different than a rotation then a movement. The function returns the new matrix.

    Function MxM(A(,) As Double, B(,) As Double) As Double(,)
        Dim C(2, 2) As Double
        Dim i, j, n As Integer
        Dim value As Double

        For i = 0 To 2
            For j = 0 To 2
                value = 0
                For n = 0 To 2
                    value = value + A(i, n) * B(n, j)
                C(i, j) = value

        Return C
    End Function