1/27/2017 planets (1)

CIS 211 Project 3: OOP Due 11:00 P.M. January 27, 2017

Reading: M&R 10.1 10.4

Our goal this week is to gain some experience writing class definitions for some simple objects. The classes are part of a solar system simulation. This week we’ll define the objects used in the simulation. Next week we’ll implement the simulation itself, and later in the term we’ll add visualization.

Part 1: Vectors (50 points)

Define a class named Vector. Instances of this class will be Euclidan vectors (https://en.wikipedia.org/wiki/Euclidean_vector (https://en.wikipedia.org/wiki/Euclidean_vector)).

An instance of this class will have three attributes, representing , , and coordinates in space. When a Vector object is created the constructor should be passed three numbers to use as the initial values of the coordinates.

Your class should also have:

accessor functions named x, y, and z, which return the current value of the specified coordinate

a __repr__ function that displays a Vector as a tuple of 3 numbers; use “%.3g” in the format statement so coordinates are shown with 3

significant digits

methods that implement ==, +, ‐, and * operations (see below)

a method named norm that computes the length, or magnitude, of the vector, defined by the equation

a method named clear that sets all coordinates to 0

To see if two vectors are equal, simply see if their , , and components are the same. This will almost certainly fail (due to roundoff errors) when the coordinates are of the size used in the solar system simulation, but it will help test the other operations, and we’ll use small numbers in these tests.

To add or subtract two vectors, make a new vector that has the sum or difference of the components of two existing vectors.

The method that implemements multiplication should implement scalar multiplication: the second operand should be an integer or a float, and the result is a new vector where all components are multiplied by the scalar.

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

1/7

zyx

zyx

2z+ 2y+ 2x√=∥v∥ ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

1/27/2017 planets (1)

Example:

>>> v1 = Vector(3, 5, 0)

>>> v2 = Vector(1, 1, 4)

>>> v1.x() 3

>>> v1.y() 5

>>> v1.norm()

5.830951894845301

>>> v1 + v2

(4,6,4)

>>> v1 ‐ v2

(2,4,‐4)

>>> v2 * 3

(3,3,12)

>>> v1 + v2 == Vector(4,6,4)

True

>>> v1.clear()

>>> v1

(0,0,0)

Code:

In [ ]: from math import sqrt

class Vector:

“””

A Vector is a 3‐tuple of (x,y,z) coordinates.

“””

# YOUR CODE HERE

pass

Tests:

Optional If you want to do your own tests use the code cell below to create and test objects. You can add additional cells here if you want.

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

2/7

1/27/2017 planets (1)

In [ ]:

In [ ]:

In [ ]:

In [ ]:

In[]: In[]: In[]: In [ ]: In [ ]:

Autograder Tests:

v1 = Vector(1, 1, 1)

v2 = Vector(2, 2, 2)

v3 = Vector(3, 3, 3)

assert str(v1) == ‘(1,1,1)’

assert str(v2) == ‘(2,2,2)’

assert Vector(1, 2, 3) == Vector(1, 2, 3)

assert Vector(1, 2, 3) != Vector(1.001, 2.001, 3.001)

assertv1+v2==v3

assertv3‐v2==v1

assertv3==v1*3

assert round(v2.norm(), 10) == round(sqrt(12), 10) v1.clear()

assert v1 == Vector(0,0,0)

Documentation:

YOUR DOCUMENTATION HERE

Part 2: Celestial Bodies (50 points)

Define a class named Body that will be used to represent the Sun and planets in the solar system simulation.

Each instance of this class should have the following attributes:

mass, represented by a single floating point number position, velocity, and force, each of which is a 3D vector a name

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

3/7

1/27/2017 planets (1)

Define the constructor so that all attributes are optional. The default name is None, mass is 0, and position and velocity are (0,0,0). The force vector should always be initialized to (0,0,0).

The representation string for a Body should include the name, if it’s not None, and then the mass, position, and velocity:

>>> Body()

0kg (0,0,0) (0,0,0)

>>> ep = Vector(‐2.700743E+10, 1.446007E+11, 9686451)

>>> Body(name = ‘earth’, mass = 5.9736E+24, position = ep)

earth: 5.97e+24kg (‐2.7e+10,1.45e+11,9.69e+06) (0,0,0)

Your class should also include the following:

accessor functions called name, mass, position, velocity, and force that return the corresponding attribute

a method called direction which takes another Body object as a parameter and returns a vector that “points at” the other Body (see example below)

a method named clear_force that sets the force vector to (0,0,0) by calling that vector’s clear method

an add_force method that takes another Body as a parameter and updates the force vector using the equation shown below

a method called move that will use the current value of the force vector to update the object’s position using the algorithm outlined below.

This example illustrates the direction method. Notice how the direction from b1 to b2 is the same size but points the other way from the direction from b2 to b1.

>>> b1 = Body(position = Vector(0,1,0))

>>> b2 = Body(position = Vector(1,0,0))

>>> b1.direction(b2)

(1,‐1,0)

>>> b2.direction(b1)

(‐1,1,0)

To implement add_force, first compute the force pulling a body A toward another body B. Let be the direction from A to B. Then a vector that defines the force is

where is the mass of body B. Add to the force vector in the object that represents A.

The move method will take a parameter named dt which is a time step size. To move a body A use the accumulated forces created by previous calls to add_force. First compute a vector that represents the acceleration of A:

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

4/7

⃗d

3∥⃗d∥

Bm × ⃗d = ⃗ f

⃗f

⃗f Bm

1/27/2017 planets (1)

where is the universal gravitational constant and is A’s force vector. Then update A’s velocity vector:

Finally, update A’s position vector:

Code:

Put your class definition in the following code cell. Note the gravitational constant defined for you.

has been

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

5/7

G

× ⃗A v + ⃗A p = ⃗A p ×⃗a+ ⃗Av= ⃗Av

⃗A f G ⃗A f × G = ⃗ a

1/27/2017 planets (1)

In [ ]: G = 6.67E‐11

class Body:

“””

A Body object represents the state of a celestial body. A body has mass

(a scalar), position (a vector), and velocity (a vector). A third vector,

named force, is used when calculating forces acting on a body. An

optional name can be attached to use in debugging.

“””

def __init__(self, mass = 0, position = Vector(0,0,0), velocity = Vector(0,0,0

“””

Create a new Body object with the specified mass (a scalar), position (a v

and velocity (another vector). A fourth argument is an optional name for

“””

# YOUR CODE HERE

pass

def __repr__(self):

# YOUR CODE HERE

pass

def name(self):

# YOUR CODE HERE

pass

def mass(self):

# YOUR CODE HERE

pass

def position(self):

# YOUR CODE HERE

pass

def velocity(self):

# YOUR CODE HERE

pass

def force(self):

# YOUR CODE HERE

pass

def direction(self, other):

# YOUR CODE HERE

pass

def add_force(self, other):

# YOUR CODE HERE

pass

def clear_force(self):

# YOUR CODE HERE

pass

def move(self, dt):

# YOUR CODE HERE

http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb

6/7

ector the b

1/27/2017 planets (1)

pass

Tests:

Optional If you want to do your own tests use the code cell below to create and test objects. You can add additional cells here if you want.

In [ ]:

In [ ]:

In [ ]:

In [ ]:

In [ ]:

In [ ]:

In [ ]:

Autograder Tests:

melon = Body(name=’melon’, mass=3.0, position=Vector(0,6371000,0))

earth = Body(name=’earth’, mass=5.9736E+24)

assert str(melon) == “melon: 3kg (0,6.37e+06,0) (0,0,0)”

assert str(earth) == “earth: 5.97e+24kg (0,0,0) (0,0,0)”

assert earth.direction(melon) == Vector(0,6371000,0)

assert melon.direction(earth) == Vector(0,‐6371000,0)

melon.add_force(earth)

assert ‐1.48e+11 < melon.force().y() < ‐1.47e+11
melon.move(1)
assert 6370990 < melon.position().y() < 6371000
melon.clear_force()
assert melon.force() == Vector(0,0,0)
Documentation:
YOUR DOCUMENTATION HERE
http://localhost:8888/notebooks/Desktop/planets%20(1).ipynb
7/7