{ "cells": [ { "cell_type": "markdown", "id": "924a2a50", "metadata": {}, "source": [ "## Question 3 (10 marks)" ] }, { "cell_type": "code", "execution_count": 1, "id": "2b3d1ba2", "metadata": {}, "outputs": [], "source": [ "import math\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "id": "478bad7a", "metadata": {}, "outputs": [], "source": [ "points = np.load('data/points.npy').astype(np.uint8)" ] }, { "cell_type": "markdown", "id": "c1e442a7", "metadata": {}, "source": [ "## Method 1" ] }, { "cell_type": "code", "execution_count": 3, "id": "e07b0285", "metadata": {}, "outputs": [], "source": [ "def m1_compute_rotation_matrix(points, theta):\n", " \"\"\"\n", " Write a function compute_rotation_matrix(points, theta) to compute the rotation matrix in\n", " homogeneous coordinate system to rotate a shape depicted with 2-dimensional (x,y) coordinates\n", " points with an angle 𝜃 (theta in the definition) in the anticlockwise direction about the centre of the shape.\n", "\n", " Parameters:\n", " points: a 2-dimensional numpy array of data type uint8 with shape 𝑘 × 2. Each row\n", " of points is a Cartesian coordinate (x, y).\n", " \n", " theta: a floating-point number denoting the angle of rotation in degree.\n", " \n", " Returns:\n", " The expected output is a 2-dimensional numpy array of data type float64 with shape 3 × 3.\n", " \"\"\"\n", "\n", " # Convert theta from degrees to radians\n", " theta_rad = np.radians(theta)\n", "\n", " # Calculate the centre of the shape\n", " centre = np.mean(points, axis=0)\n", "\n", " # Define the translation matrices to move the centre of the shape to the origin and back\n", " translation_to_origin = np.array([[1, 0, -centre[0]],\n", " [0, 1, -centre[1]],\n", " [0, 0, 1]], dtype=np.float64)\n", "\n", " translation_back = np.array([[1, 0, centre[0]],\n", " [0, 1, centre[1]],\n", " [0, 0, 1]], dtype=np.float64)\n", "\n", " # Define the rotation matrix about the origin\n", " rotation = np.array([[np.cos(theta_rad), -np.sin(theta_rad), 0],\n", " [np.sin(theta_rad), np.cos(theta_rad), 0],\n", " [0, 0, 1]], dtype=np.float64)\n", "\n", " # Combine the translation and rotation into a single transformation matrix\n", " rotation_matrix = np.dot(np.dot(translation_back, rotation), translation_to_origin)\n", " \n", " return rotation_matrix" ] }, { "cell_type": "code", "execution_count": 4, "id": "16ef4247", "metadata": {}, "outputs": [], "source": [ "m1_rotation_matrices = []\n", "\n", "for t in range(0, 365, 5):\n", " m1_rotation_matrices.append( m1_compute_rotation_matrix(points, t) )" ] }, { "cell_type": "markdown", "id": "5554bde0", "metadata": {}, "source": [ "## Method 2" ] }, { "cell_type": "code", "execution_count": 5, "id": "087b6ac9", "metadata": {}, "outputs": [], "source": [ "def m2_compute_rotation_matrix(points, theta):\n", "\n", " # Convert angle to radians\n", " theta_rad = np.deg2rad(theta)\n", " \n", " cos_theta = np.cos(theta_rad)\n", " sin_theta = np.sin(theta_rad)\n", "\n", " # Compute center of the shape\n", " center = np.mean(points, axis=0)\n", " \n", " # Construct rotation matrix\n", " rotation_matrix = np.array([\n", " [ cos_theta, -sin_theta, -center[0] * cos_theta + center[1] * sin_theta + center[0] ],\n", " [ sin_theta, cos_theta, -center[0] * sin_theta - center[1] * cos_theta + center[1] ],\n", " [0, 0, 1]\n", " ])\n", " \n", " return rotation_matrix" ] }, { "cell_type": "code", "execution_count": 6, "id": "02ec3b60", "metadata": {}, "outputs": [], "source": [ "m2_rotation_matrices = []\n", "\n", "for t in range(0, 365, 5):\n", " m2_rotation_matrices.append( m2_compute_rotation_matrix(points, t) )" ] }, { "cell_type": "markdown", "id": "a130c201", "metadata": {}, "source": [ "## Save Output" ] }, { "cell_type": "code", "execution_count": 7, "id": "23967b5d", "metadata": {}, "outputs": [], "source": [ "np.save('data/question_3_rotation_matrices.npy', m1_rotation_matrices)" ] }, { "cell_type": "markdown", "id": "a808d8a4", "metadata": {}, "source": [ "## Put students' implementations here" ] }, { "cell_type": "markdown", "id": "06417b95", "metadata": {}, "source": [ "This is one common mistake." ] }, { "cell_type": "code", "execution_count": 8, "id": "b0836f8d", "metadata": {}, "outputs": [], "source": [ "def compute_rotation_matrix(points, theta):\n", "\n", " # Convert angle to radians\n", " theta_rad = np.deg2rad(theta)\n", " \n", " # Calculate sine and cosine of the angle\n", " cos_theta = np.cos(theta_rad)\n", " sin_theta = np.sin(theta_rad)\n", " \n", " # Compute center of the shape\n", " center = np.mean(points, axis=0)\n", " \n", " # Translate points to origin\n", " translated_points = points - center\n", " \n", " # Wrong: Construct rotation matrix\n", " rotation_matrix = np.array([[cos_theta, -sin_theta, center[0]],\n", " [sin_theta, cos_theta, center[1]],\n", " [0, 0, 1]])\n", " \n", " return rotation_matrix" ] }, { "cell_type": "markdown", "id": "73b68192", "metadata": {}, "source": [ "## Test (Should output ALL PASS)" ] }, { "cell_type": "markdown", "id": "1c0a88a6", "metadata": {}, "source": [ "Restart and Run ALL for each submission" ] }, { "cell_type": "code", "execution_count": 9, "id": "132d734b", "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 PASS\n", "Failed\n" ] }, { "ename": "AssertionError", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[9], line 9\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(n_pass, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPASS\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 8\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m----> 9\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m n_pass \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mlen\u001b[39m(m1_rotation_matrices)\n\u001b[0;32m 10\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mALL PASS\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 11\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAssertionError\u001b[39;00m:\n", "\u001b[1;31mAssertionError\u001b[0m: " ] } ], "source": [ "n_pass = 0\n", "for t in range(0, 365, 5):\n", " if np.allclose(compute_rotation_matrix(points, t), m1_rotation_matrices[int(t / 5)]):\n", " n_pass = n_pass + 1\n", "\n", "print(n_pass, \"PASS\")\n", "\n", "try:\n", " assert n_pass == len(m1_rotation_matrices)\n", " print(\"ALL PASS\")\n", "except AssertionError:\n", " print(\"Failed\")\n", " raise" ] }, { "cell_type": "code", "execution_count": null, "id": "03e9c423", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "what", "language": "python", "name": "what" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.16" } }, "nbformat": 4, "nbformat_minor": 5 }