{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Class Hierarchies" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Imports\n", "import math" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this lecture we shall try to understand how to use functions defined in one class easily in other classes. For that, we shall define a class called Polygon which will define a polygon on the plane. It will have methods to find the area and circumference. Then we shall use this to have special subclasses : Rectangle, Triangle. We shall then have another subclass : RegularPolygon. Square, EquilateralTriangle will be subclasses of this class, as well as Rectangle and Triangle respectively." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "The Class Polygon" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The shoelace method says that if a polygon has vertices $(x_1, y_1), (x_2, y_2), \\dotsc, (x_n, y_n)$ in *counter clockwise* direction, then the area of the polygon is given by the formula\n", "\\begin{equation}\n", "\\frac{1}{2} \\left(\n", "\\det\\begin{pmatrix}x_1 & x_2 \\\\ y_1 & y_2\\end{pmatrix} +\n", "\\det\\begin{pmatrix}x_2 & x_3 \\\\ y_2 & y_3\\end{pmatrix} +\n", "\\dotsb +\n", "\\det\\begin{pmatrix}x_{n - 1} & x_{n} \\\\ y_{n - 1} & y_{n} \\end{pmatrix} +\n", "\\det\\begin{pmatrix}x_n & x_1 \\\\ y_n & y_1\\end{pmatrix}\n", "\\right).\n", "\\end{equation}" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Polygon :\n", " \"\"\"Computer representation of a polygon.\n", " \n", " Attributes :\n", " lop : A list of coordinate pairs which list the vertices of \n", " the polygon in the counter clockwise order.\n", " \n", " Method :\n", " __init__ : Initializes the polygon\n", " area() : returns the area of the polygon\n", " __str__ : Returns the string \"n-gon with area A\"\n", " __repr__ : returns lop in string format\n", " \"\"\"\n", " \n", " def __init__(self, lop) :\n", " self.lop = lop\n", " \n", " def area(self) :\n", " l = self.lop # list of vertices\n", " n = len(l) # number of vertices\n", " \n", " # Find area using the shoelace method\n", " s = 0 # To store the value of the sum in shoelace\n", " for i in range(n) :\n", " ip1mn = (i + 1) % n\n", " s += l[i][0] * l[ip1mn][1] - l[ip1mn][0]*l[i][1]\n", " return float(s)/2.0\n", " \n", " def __str__(self) :\n", " return \"%d-gon with area %g\" % (len(self.lop), self.area())\n", " \n", " def __repr__(self) :\n", " return \"Polygon(\" + str(self.lop) + \")\"" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " print \"Testing class Polygon\"\n", " poly = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])\n", " print \"Our polygon is a\", poly, \".\"\n", " print \"It was defined by\", poly.__repr__(), \".\"" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Testing class Polygon\n", "Our polygon is a 4-gon with area 1 .\n", "It was defined by Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) .\n" ] } ], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "class Rectangle(Polygon) :\n", " \"\"\"A subclass of Polygon which defines rectangle by the two ends of the base and height.\n", " Positive height is in the direction 90 deg counter clockwise from v1 -> v2. \n", " \"\"\"\n", " def __init__(self, v1, v2, height) :\n", " \"\"\"v1 : first vertex of the base\n", " v2 : second vertex\n", " height : height\n", " \"\"\"\n", " \n", " (x1, y1) = v1\n", " (x2, y2) = v2\n", " perpdir = (y1 - y2, x2 - x1)\n", " lenperp = math.sqrt((y1 - y2)**2 + (x2 - x1)**2)\n", "\n", " x3 = float(height) * (y1 - y2) / lenperp + x1 # Why?\n", " y3 = float(height) * (x2 - x1) / lenperp + y1 # Why?\n", " v3 = (x3, y3)\n", "\n", " x4 = float(height) * (y1 - y2) / lenperp + x2 # Why?\n", " y4 = float(height) * (x2 - x1) / lenperp + y2 # Why?\n", " v4 = (x4, y4)\n", "\n", " Polygon.__init__(self, [v1, v2, v4, v3])\n", " \n", " def __str__(self) :\n", " return \"A rectangle of area %g\" % self.area()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " rect = Rectangle((0,0), (1, 1), math.sqrt(1.0/2))\n", " print rect\n", " print rect.__repr__()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "A rectangle of area 1\n", "Polygon([(0, 0), (1, 1), (0.5, 1.5), (-0.5, 0.5)])\n" ] } ], "prompt_number": 5 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Class Triangle" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Triangle(Polygon) :\n", " \"\"\"Create a triangle given 3 vertices.\"\"\"\n", " \n", " def __init__(self, v1, v2, v3) :\n", " Polygon.__init__(self, [v1, v2, v3])\n", " \n", " def __str__(self) :\n", " return \"A triangle with area %g\" % self.area()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " tr = Triangle((0,0), (1,0), (0, 2))\n", " print tr\n", " print tr.__repr__()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "A triangle with area 1\n", "Polygon([(0, 0), (1, 0), (0, 2)])\n" ] } ], "prompt_number": 7 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Class RegularPolygon" ] }, { "cell_type": "code", "collapsed": false, "input": [ "class RegularPolygon(Polygon) :\n", " \"\"\"Given the end points of a side an number of sides,\n", " this creates an internal representation of a regular\n", " polygon.\"\"\"\n", " \n", " def __init__(self, v1, v2, n) :\n", " internalangle = float(n-2) * math.pi / float(n)\n", " # print internalangle * 180/ math.pi\n", " (x1, y1) = v1\n", " (x2, y2) = v2\n", " lenside = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)\n", " \n", " lop = [v1, v2]\n", " for i in range(3, n+1) :\n", " vm2 = lop[-2]\n", " vm1 = lop[-1]\n", " (x, y) = vm2\n", " (z, w) = vm1\n", " \n", " # Why does the following work?\n", " p = z + (x - z) * math.cos(internalangle) \\\n", " + (y - w) * math.sin(internalangle)\n", " q = w + (y - w) * math.cos(internalangle) \\\n", " + (z - x) * math.sin(internalangle)\n", " lop.append((p, q))\n", " # print x, y, z, w, p,q \n", " \n", " Polygon.__init__(self, lop)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " pt = RegularPolygon((4, 3), (4 + 1.0/math.sqrt(2), 3 + 1.0/math.sqrt(2)), 5)\n", " print pt\n", " print pt.__repr__()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "5-gon with area 1.72048\n", "Polygon([(4, 3), (4.707106781186548, 3.7071067811865475), (4.253116281447001, 4.598113305374915), (3.2654279408518634, 4.441678840334684), (3.108993475811633, 3.4539904997395463)])\n" ] } ], "prompt_number": 9 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Class EquilateralTriangle and Square." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I use multiple inheritence just to show how it works. However it is better not to use multiple inheritence and some languages do not even support it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "class EquilateralTriangle(Triangle, RegularPolygon) :\n", " def __init__(self, v1, v2) :\n", " RegularPolygon.__init__(self, v1, v2, 3)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " eqt = EquilateralTriangle((0, 0), (1, 0))\n", " print eqt\n", " print eqt.__repr__()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "A triangle with area 0.433013\n", "Polygon([(0, 0), (1, 0), (0.4999999999999999, 0.8660254037844386)])\n" ] } ], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "class Square(Rectangle, RegularPolygon) :\n", " def __init__(self, v1, v2) :\n", " RegularPolygon.__init__(self, v1, v2, 4)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "if __name__ == '__main__' :\n", " sq = Square((0, 0), (1, 0))\n", " print sq\n", " print sq.__repr__()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "A rectangle of area 1\n", "Polygon([(0, 0), (1, 0), (0.9999999999999999, 1.0), (-1.1102230246251565e-16, 0.9999999999999998)])\n" ] } ], "prompt_number": 13 } ], "metadata": {} } ] }