306 lines
8.5 KiB
Plaintext
306 lines
8.5 KiB
Plaintext
{
|
||
"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 = 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
|
||
}
|