Tuesday 15 July 2014

Maths with Python

Last week I was reviewing analytic geometry and while looking at graphs, equations, theorems and points I was a little bored and decided to try and implement some part of that in Python.

Even though I am still not that practical with Python classes, I am beginning to experiment classes for different purposes. As you know a class is a sort of template, a collection of code and methods (functions inside a class are called methods) which can be called on the instances of the class.

In this example, I created two classes: a class for points and a class for circumferences.
The modules I used are matplotlib and numpy. You can check on my Python page for the link to download these modules or simply google them.

The Point class is really basic, well, not the most basic class you could create but pretty basic.

class Point(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return "(%s,%s)" %(round(self.x ,2), round(self.y, 2))

The __init__ methods initializes the class. After you have defined an instance of the point Class, as below

p = Point(0,0)

every time you need to know the x coordinate, you can simply type in

p.x

and Python will print to you the value of x for the instance (the point) p.

The __repr__ methods gives you the freedom to decide how to (represent) display your instance when called. For example, in this case, when I type in the command line

p

The interpreter will show (0,0) because that is the representation of a point p I told him to display through __repr__
The screenshots below show the results


Now that we have our Point class, let's skip to fancier stuff :)
for the circumference class pyplot and numpy are needed so we need to import them. Note that usually import statements are above, in the first lines of the script, however, in order not to confuse anyone I put them here.
This is the Circle class:

#New class for circumferences
import matplotlib.pyplot as plt
import numpy as np

class Circle(object):

    def __init__(self, point, r):
        self.point = point
        self.xc = point.x
        self.yc = point.y
        self.r = r
        self.a = -2*self.xc
        self.b = -2*self.yc
        self.c = (self.xc)**2 + (self.yc)**2 - (self.r)**2

    def check_if_circle(self, x, y):
        if (round(x**2 + y**2 + self.a*x + self.b*y + self.c, 1) == 0):
            #print("The point is on the circumference")
            return True
        else:
            #print("The point is NOT on the circumference")
            return False


    def __repr__(self):
        parameters = {"a":self.a, "b":self.b, "c":self.c, "r":self.r}
        #print(parameters)
        if self.a != 0 and self.b != 0:
            return ("The circle has the centre in (%s, %s) and
 has a radius of %d.\nThe equation is:\nx^2 + y^2 " + str(self.a)
 + "x " + str(self.b) + "y " + str(self.c) + " = 0") 
 %(round(self.xc, 2), round(self.yc, 2), self.r)
        elif self.a == 0 and self.b != 0:
            return ("The circle has the centre in (%s, %s) and
 has a radius of %d.\nThe equation is:\nx^2 + y^2 " + str(self.b)
 + "y " + str(self.c) + " = 0")  %(round(self.xc, 2), 
 round(self.yc, 2), self.r)
        elif self.b == 0 and self.a != 0:
            return ("The circle has the centre in (%s, %s) and
 has a radius of %d.\nThe equation is:\nx^2 + y^2 " + str(self.a)
 + "x " + str(self.c) + " = 0")  %(round(self.xc, 2), 
 round(self.yc, 2), self.r)
        else:
            return ("The circle has the centre in (%s, %s) and
 has a radius of %d.\nThe equation is:\nx^2 + y^2 " + str(self.c)
 + " = 0") %(round(self.xc, 2), round(self.yc, 2), self.r)

    def area(self):
        return (np.pi * (self.r)**2)

    def area_sphere(self):
        return (4*(np.pi)*(self.r)**2)

    def volume_sphere(self):
        return(4/3*(np.pi)*(self.r)**3)

    def plot_crf(self):

        def semi_sphere_positive(x):
            y = self.yc + np.sqrt((self.r)**2 - (x - self.xc)**2)
            return y

        def semi_sphere_negative(x):
            y = self.yc - np.sqrt(self.r**2 - (x - self.xc)**2)
            return y

        z = np.linspace(self.xc - self.r,self.xc + self.r,1000)
        graphone = semi_sphere_positive(z)
        graphtwo = semi_sphere_negative(z)
        plt.plot(z,graphone)
        plt.plot(z,graphtwo)
        plt.show()


#define an instance, a circumference of centre p and radius 2
C = Circle(p, 2)

The __repr__ method is slightly fancier in order to display the equation of the circumference in its canonical form according to the values of a,b and c. Remember that:


After this class has been defined, you can call all its methods on C and take a look at the results.
This is particularly interesting if you are actually doing your homework on analytic geometry and you want to develop your programming skills at the same time. Every geometrical figure has its own characteristics and properties. Classes are the perfect tool to collect data which is characterized by a common denominator.

Here you can find a screenshots of the methods in the Circle class

and finally the most interesting method: the graphical representation of the circumference:

C.plot_crf()

and the result:


Note that, since the equation of the circumference is not a function, I had to plot the two semi-circumference. The graphical result looks still good though.
Alternatively, you could have used polar coordinates and the code would have shrunk down by a great amount.


1 comment: