# Using matplotlib for Matrix Transformation Demo

In this post, I will introduce my demonstration about matrix transformation using matplotlib. The purpose of this demo is give us a useful tool to explore how a matrix can transform a shape. The final result is given by below image:

### What is transformation matrix?

In linear algreba 1, linear transformations can be represented by matrices. If $T$ is a linear transformation mapping $R^n$ to $R^m$ and $\vec x$ is a column vector with $n$ entries, then

$T( \vec x ) = \mathbf{A} \vec x$

For some $m \times n$ matrix $A$, called the transformation matrix of $T$.

### Setup

In this part, I will discuss about important parts in my code.

We will transform a square represented by 4 points

origin_matrix = np.matrix([
[ui_ox.val, ui_oy.val],
[ui_ox.val + 1, ui_oy.val],
[ui_ox.val + 1, ui_oy.val+1],
[ui_ox.val, ui_oy.val + 1]])


User can change values of ui_ox.val and ui_oy.val (which represent original position of shape) through two sliders

# original controller
Button(plt.axes([0.1, 0.2, 0.8, 0.04]), "Original Position")
ax_ox = plt.axes([0.1, 0.16, 0.35, 0.02])
ui_ox = Slider(ax_ox, '', -2, 2, valinit=0)
ax_oy = plt.axes([0.55, 0.16, 0.35, 0.02])
ui_oy = Slider(ax_oy, '', -2, 2, valinit=0)


The transform matrix can be controlled through 4 sliders

# transformation controller
Button(plt.axes([0.1, 0.1, 0.8, 0.04]), "Transformation Matrix")
ax_t00 = plt.axes([0.1, 0.05, 0.35, 0.02])
ui_t00 = Slider(ax_t00, '', -5, 5, valinit=0)
ax_t01 = plt.axes([0.55, 0.05, 0.35, 0.02])
ui_t01 = Slider(ax_t01, '', -5, 5, valinit=-0)
ax_t10 = plt.axes([0.1, 0.01, 0.35, 0.02])
ui_t10 = Slider(ax_t10, '', -5, 5, valinit=0)
ax_t11 = plt.axes([0.55, 0.01, 0.35, 0.02])
ui_t11 = Slider(ax_t11, '', -5, 5, valinit=0)


The transformed shape represented by result matrix

result_matrix = (transform_matrix * origin_matrix.transpose()).transpose()


Finally, We draw shapes by Polygon function

ax.add_patch(Polygon(origin_matrix, color='black'))


### Experiment

The second part, we will use this tool to examize some basic transformations by a matrix.

#### Rotation

For rotation by an angle $\theta$ clockwise about the origin 1 the functional form is $x' = x \cos \theta + y \sin \theta$ and $y' = -x \sin \theta + y \cos \theta$. Written in matrix form, this becomes:

$\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} cos \theta & sin \theta \\ - sin \theta & cos \theta \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}$

Let $\theta = \pi / 4$ (45 degrees), we have a transformation matrix:

$\begin{bmatrix} \frac{\sqrt{2}}{2} & \frac{\sqrt{2}}{2} \\ - \frac{\sqrt{2}}{2} & \frac{\sqrt{2}}{2} \end{bmatrix} \sim \begin{bmatrix} 0.707 & 0.707 \\ - 0.707 & 0.707 \end{bmatrix}$

#### Shearing

For shear mapping (visually similar to slanting), there are two possibilities.

A shear parallel to the x axis has x’ = x + ky and y’ = y. Written in matrix form, this becomes:

$\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} 1 & k \\ 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}$

A shear parallel to the y axis has x’ = x and y’ = y + kx, which has matrix form:

$\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} 1 & 0 \\ k & 1 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}$

Let $k = 3$, we have two transformation matrices:

$\begin{bmatrix} 1 & 3 \\ 0 & 1 \end{bmatrix}, \begin{bmatrix} 1 & 0 \\ 3 & 1 \end{bmatrix}$

### Reflection

To reflect a vector about a line that goes through the origin 1, let $\scriptstyle \vec{l} = (l_x, l_y)$ be a vector in the direction of the line:

$\mathbf{A} = \frac{1}{\lVert\vec{l}\rVert^2} \begin{bmatrix} l_x^2 - l_y^2 & 2 l_x l_y \\ 2 l_x l_y & l_y^2 - l_x^2 \end{bmatrix}$

Let $l_1 = (1, 0)$ (reflect through $Ox$) and $l_2 = (1, -1)$ (reflect through $y=-x$), we have two transformation matrices:

$\begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}, \begin{bmatrix} 0 & -1 \\ -1 & 0 \end{bmatrix}$

### Complete Code

# __author__ = 'rain'

from pylab import *
import matplotlib.pyplot as plt
from matplotlib.widgets import Button, Slider

fig = plt.figure()
ax = fig.add_subplot(111, xlim=(-6, 6), ylim=(-6, 6))
plt.grid()
ax.set_aspect('equal')

def draw(val):
origin_matrix = np.matrix([[ui_ox.val, ui_oy.val],
[ui_ox.val + 1, ui_oy.val],
[ui_ox.val + 1, ui_oy.val+1],
[ui_ox.val, ui_oy.val + 1]])
transform_matrix = np.matrix([[ui_t00.val, ui_t01.val], [ui_t10.val, ui_t11.val]])
result_matrix = (transform_matrix * origin_matrix.transpose()).transpose()
ax.clear()
ax.grid()

# original controller
Button(plt.axes([0.1, 0.2, 0.8, 0.04]), "Original Position")
ax_ox = plt.axes([0.1, 0.16, 0.35, 0.02])
ui_ox = Slider(ax_ox, '', -2, 2, valinit=0)
ax_oy = plt.axes([0.55, 0.16, 0.35, 0.02])
ui_oy = Slider(ax_oy, '', -2, 2, valinit=0)

# transformation controller
Button(plt.axes([0.1, 0.1, 0.8, 0.04]), "Transformation Matrix")
ax_t00 = plt.axes([0.1, 0.05, 0.35, 0.02])
ui_t00 = Slider(ax_t00, '', -5, 5, valinit=0)
ax_t01 = plt.axes([0.55, 0.05, 0.35, 0.02])
ui_t01 = Slider(ax_t01, '', -5, 5, valinit=-2)
ax_t10 = plt.axes([0.1, 0.01, 0.35, 0.02])
ui_t10 = Slider(ax_t10, '', -5, 5, valinit=-2)
ax_t11 = plt.axes([0.55, 0.01, 0.35, 0.02])
ui_t11 = Slider(ax_t11, '', -5, 5, valinit=0)

ui_ox.on_changed(draw)
ui_oy.on_changed(draw)
ui_t00.on_changed(draw)
ui_t01.on_changed(draw)
ui_t10.on_changed(draw)
ui_t11.on_changed(draw)

draw(0)
plt.show()


1.  http://en.wikipedia.org/wiki/Transformation_matrix