#!/usr/bin/env python3

import math
import numpy as np

# I derived the following by plotting the unit vectors on graph paper.
unit   = np.matrix([[1, 0], [0, 1]])
rot90  = np.matrix([[0, 1], [-1, 0]])
rot180 = np.matrix([[-1, 0], [0, -1]])
rot270 = np.matrix([[0, -1], [1, 0]])

def assert_matrices_are_equal(a, b):
    assert((a == b).all())

# Insight 1: you can multiple matrix transformations together to comopse
# transformations.
def verify_rotations():
    _rot180 = rot90 * rot90
    assert_matrices_are_equal(rot180, _rot180)

    _rot270 = _rot180 * rot90
    assert_matrices_are_equal(rot270, _rot270)
    assert_matrices_are_equal(rot270, rot90 * rot90 * rot90)

    _unit = _rot270 * rot90
    assert_matrices_are_equal(unit, _unit)
    assert_matrices_are_equal(unit, rot90 * rot90 * rot90 * rot90)

# Insight 2: a generalised 2D rotation transformation assuming clockwise rotations.
def rotate(degrees):
    degrees = math.radians(degrees)
    return np.matrix([
        [math.cos(degrees), math.sin(degrees)],
        [-1 * math.sin(degrees), -1 * math.cos(degrees)],
    ])

def rotate_a_line():
    # rotate a vertical line clockwise, with the expected line after each rotation.
    line = np.matrix([[0], [4]])

    line_90  = np.matrix([[4], [0]])
    line_180 = np.matrix([[0], [-4]])
    line_270 = np.matrix([[-4], [0]])

    # Vectors are a special case of matrices...
    assert_matrices_are_equal(line_90, rot90 * line)
    assert_matrices_are_equal(line_180, rot180 * line)
    assert_matrices_are_equal(line_270, rot270 * line)

def rotate_a_diagonal():
    # rotate a diagonal line clockwise, with the expected line after each rotation.
    line = np.matrix([[4], [4]])

    line_90  = np.matrix([[4], [-4]])
    line_180 = np.matrix([[-4], [-4]])
    line_270 = np.matrix([[-4], [4]])

    assert_matrices_are_equal(line_90, rot90 * line)
    assert_matrices_are_equal(line_180, rot180 * line)    
    assert_matrices_are_equal(line_270, rot270 * line)    


if __name__ == '__main__':
    verify_rotations()
    assert(np.isclose(rot90, rotate(90)).all())
    rotate_a_line()
    rotate_a_diagonal()

    print('OK')

Generated by Kyle Isom using scpaste at Tue Nov 13 14:46:24 2018. PST. (original)