Affine transformations in the plane

Geometry
Growth and form
Mappings

An affine transformation is a geometric transformation that preserves lines and parallelism, but not necessarily Euclidean distances and angles. Examples of affine transformations include:

In the app in Figure 1 you can explore transformation of a set of points.

#| standalone: true
#| components: [viewer]
#| viewerHeight: 600

from shiny import App, Inputs, Outputs, Session, render, ui
from shiny import reactive


import numpy as np
import matplotlib.pyplot as plt
import skimage as ski
import pyodide
from skimage.transform import SimilarityTransform
from skimage.transform import warp
from skimage.transform import PiecewiseAffineTransform
from skimage.transform import AffineTransform
from skimage.io import imread
import io
from pathlib import Path
from skimage.transform import resize, rescale



app_ui = ui.page_fluid(
    ui.layout_sidebar(
        ui.panel_sidebar(
    ui.input_slider(id="Rotation",label="Rotation",min=-2.0*np.pi,max=2.0*np.pi,value=0.0,step=np.pi/20.0),
    ui.input_slider(id="Scale",label="Scale",min=0.1,max=3.0,value=1.0,step=0.1),
    ui.input_slider(id="Shear",label="Shear",min=-3.0,max=3.0,value=0.0,step=0.1),
    ui.input_slider(id="translate_x",label="translate_x",min=-3.0,max=3.0,value=1.0,step=0.1),
    ui.input_slider(id="translate_y",label="translate_y",min=-3.0,max=3.0,value=1.0,step=0.1)),
    ui.panel_main(ui.output_plot("plot")),
    ),
)

def server(input: Inputs, output: Outputs, session: Session):
    
    @render.plot
    def plot():
        # Calculate the translation required to move all points into positive coordinates

        translation_vec=[input.translate_x(),input.translate_y()]
        scale_param=input.Scale()
        shear_param=input.Shear()
        rotation_param=input.Rotation()
        tform_shift = AffineTransform(translation=translation_vec,scale=scale_param,shear=shear_param,rotation=rotation_param)
        homog_trans_matrix=tform_shift.params


        old_coordinates=[[0,0,1.0],[0,1,1.0],[0,2,1.0],[0,3,1.0],[0,4,1.0],
        [4.0,0,1.0],[4.0,1,1.0],[4.0,2,1.0],[4.0,3,1.0],[4.0,4,1.0],
        [1.0,0.0,1.0],[2.0,0.0,1.0],[3.0,0.0,1.0],
        [1.0,4.0,1.0],[2.0,4.0,1.0],[3.0,4.0,1.0]]
        old_coordinates=np.array(old_coordinates)

        new_coordinates=old_coordinates.copy()

        for i in range(old_coordinates.shape[0]):

            homog_vec=np.array(old_coordinates[i,:]).copy()
            new_coordinates[i,:]=homog_trans_matrix@homog_vec



        fig,ax=plt.subplots()
        ax.plot()
        ax.set_xticks(np.arange(-10,10))
        ax.set_yticks(np.arange(-10,10))
        ax.plot(old_coordinates[:,0],old_coordinates[:,1],'r*')
        ax.plot(new_coordinates[:,0],new_coordinates[:,1],'k*')

        ax.grid(True)
        plt.axis('equal')
        ax.set_xlim([-10,10])
        ax.set_ylim([-10,10])
        ax.legend(['Original','Transformed'])
        plt.show()

app = App(app_ui, server)

Figure 1

At Dundee, concepts from geometry are studied in core modules Maths 1A and Maths 1B.

At Level 3 in the module Differential Geometry students study generalisations of 2D mappings to arbitrarily curved spaces.

You can find out more about these modules here. :::