CS 151: Lab #8

Lab Exercise 8: Aggregate Objects

This lab exercise is intended to give you practice in creating a class. We will go over the details of creating a class, and then build a class that holds a graphics object consisting of several basic graphics types.


Tasks

  1. You will need the graphics.py file for this exercise.
  2. Create a new file called username_graphics.py, where username is your Colby id.
  3. We'll start by creating a simple class called Peace. The Peace class should act just like any other Zelle graphics object, but it will consist of a circle and three lines.

    A class consists of a class name, a constructor, internal data fields, and a set of methods. In order to simulate the behavior of a Zelle graphics object, our class needs to have the following methods.

    • Peace( center, radius ) - constructor that returns a reference to a Peace object
    • draw(win) - takes a window and draws the object
    • undraw() - undraws the object
    • move(tx, ty) - moves the object by tx and ty
    • clone() - returns a clone of the object (same location, but not drawn)
    • setFill(color) - sets the fill color of the object
    • setWidth(width) - sets the width of the lines of the object

    The skeleton of your Peace class should look like the following. Note the quotes at the beginning of each function. These descriptions will be displayed if you type help(Peace) in python.

    class Peace:
    """Creates a Peace symbol object that behaves like a Zelle graphics object"""
        
        def __init__( self, center, radius ):
            """Constructs the Peace object given center point c and a radius r"""
    
        def construct(self, ctr, rad):
            """Constructs the Peace object given center point ctr and a radius rad"""
    
        def draw(self, win):
            """Draws the Peace object in the specified window"""
    
        def undraw(self, win):
            """Undraws the Peace object, fails quietly if not drawn"""
    
        def move(self, tx, ty):
            """Moves the Peace object"""
    
        def clone(self):
            """Creates a copy of the Peace object and returns it"""
    
        def setFill(self, color):
            """Sets the background color of the Peace circle"""
    
        def setWidth(self, width):
            """Sets the width of the lines in the object"""
    
        def getCenter(self):
            """returns a clone of the center point of the object"""
    

    You can download the skeleton file.

  4. Once you've got the skeleton above in your file, you need to write the methods. The first method to write is the construct method. The Peace symbol needs to keep track of where it is located (its center), how big it is (the radius), and all of the objects from which it is constructed (a circle and three lines).

    Creating fields in an object (variables in which to store data), is similar to creating regular variables and assigning values to them. The difference when working with an object is that we use the self variable to indicate that the new variable should be a field for the object. The following three lines create three fields and assign values to them.

            self.center = ctr.clone()
            self.radius = rad
            self.shapes = []
    
    Note that we want to clone the center point so that the object contains its own version of the point and not just a reference.

    The rest of the method just needs to 1) create a circle, 2) create a line from the top of the circle to the bottom, and 3) create two lines from the center of the circle to points that are angled out at 45 degrees from the bottom. Collect each of the four graphics objects in the self.shapes list created above. (Hint: If you add (0.7071 * radius) to the Y-coordinate of the center point and add (+/- 0.7071 * radius) to the X-coordinate of the center point, that will give you the appropriate points on the circle.)

  5. Given the construct method, the actual constructor __init__ should be trivial to write, as it is simply a call to the construct function.
  6. The draw, undraw, and setWidth methods should simply apply the appropriate method to each of the objects in the self.shapes list.
  7. The move method needs to move both the center point and all of the objects in the shapes list.
  8. The setFill method should set only the fill color of the circle object. Note that once you have finished the functions to here, you should be able to run the program so that the PeaceTest() function is called.
  9. The getCenter method should return a clone of the center point.
  10. The clone method needs to create a new Peace object with the same center and radius values. Then, to make it a real clone, you need to clear the shapes list of the new object and replace it with clones of the objects from self.shapes.
  11. Once you have all of the methods implemented, add the following code to your PeaceTest function and see what happens. You can also get it from here.
        plist = []
        for i in range(20):
            pt = p.clone()
            pt.move( random.gauss(0, 80), random.gauss(0, 80) )
            pt.setFill( color_rgb( random.random() * 255, 255, random.random() * 255 ) )
            pt.draw(win)
            plist.append(pt)
    
        print 'plist length', len(plist)
    
        win.getMouse()
    
        while win.checkMouse() == None:
            
            for q in plist:
                dx = (200 - q.getCenter().getX())
                dy = (200 - q.getCenter().getY())
                if math.fabs(dx) > 0.5 or math.fabs(dy) > 0.5:
                    q.move( dx*0.03, dy*0.03 )
    
        win.close()
    
  12. If you have time, try creating another simple object that consists of a collection of objects.

Once you've finished the above exercise, get started on the next project.