15-110 Summer Session Two - 2014

Lab 10 - Monday, July 28


Goals

This lab is intended to develop your understanding of doing simple graphics with Python. We will be using the module Canvas from PythonLabs. We will also be using the module random to generate random colors for the shapes we draw. After we learn how to draw rectangles, we introduce the concept of a fractal in the last question and make you observe the recursive nature of fractals. That part is mainly intended to make you think recursively and enjoy a beautiful application of recursion.

When you are done with this lab, you should be able to do the following:

  1. Initialize a canvas of a certain size
  2. Explain how the coordinate system works in the module Canvas
  3. Draw rectangles on the canvas, possibly with borders, and possibly filled with color
  4. Use the module random to generate random integers
  5. Use the module random to choose random elements from a given list
  6. Explain the effect of using a seed for a pseudorandom number generator

TA Demonstration (as needed)

Deliverables

  1. random_boxes.py
  2. data_display.py
  3. triangle.py

Activities

  1. Write a Python function random_boxes() that creates a window of size 350 by 350 and draws a 40 by 40 grid of 8 by 8 squares, each colored a random color from black, white, yellow, cyan, and magenta.

    Note: Your results may vary since we are using a random number generator and we do not expect you to seed the random number generator to fix the sequence of numbers that it will generate.

  2. Write a function data_display(matrix) that takes a 4 by 4 matrix as its parameter and displays a 4 by 4 grid of 80 by 60 rectangles in a window of size 350 (width) by 270 (height) based on the data in the input matrix . If the value in a matrix cell is odd, draw a yellow rectangle in its grid location in the window and if the value in a matrix cell is even, draw a blue rectangle in its grid location in the window.

    Image for matrix = [[0,2,1,4], [4,5,3,8], [9,4,7,1], [5,1,7,0]]


  3. The image to the right is a Sierpinski's Triangle (albeit, rotated and with a different angle than the canonical form). It is a fractal; that is, it is "a rough or fragmented geometric shape that can be split into parts, each of which is (at least approximately) a reduced-size copy of the whole." In this case, you will notice that, if you look at the lower-right corner, it looks the same (down to the level of one pixel) at different levels of magnification.

    Starting with a completely filled-in square, this Sierpinski's Triangle can be produced with the following procedure:

    1. Return None if the image is too small to be visibly subdivided.
    2. Otherwise, consider the square being divided up into four quadrants (squares).
    3. Draw a square (rectangle with equal sides) in the upper-left quadrant.
    4. Recursively draw a Sierpinski triangle in each of the other three quadrants.

    Finish the following incomplete Python implementation of this algorithm and save it as triangle.py. You only need to supply the parameters to the recursive procedure calls. You should not add any other additional code. If you do this correctly, you will be able to reproduce the image shown above, by calling start_triangle(256, "blue") after loading your source file. You should note that when you specify drawing coordinates for the canvas, the top left corner is the origin (0,0), x increases as you go from left to right, but y increases as you go from top to bottom.

    HINT: You need to figure out the top-left corner and size for each of the other three quadrants and fill them in for the parameters for the three recursive calls.

    # This function initializes a PythonLabs Canvas, 
    # then calls the recursive function triangle to do all the work
    
    def start_triangle(size, color):
        Canvas.init(size + 35, size + 35, "SierpinskisTriangle")
        Canvas.Rectangle(1, 1, size + 1, size + 1, fill=color)
        triangle(0, 0, size)
    
    
    # draw a Sierpinski triangle with top left at (x,y) and 
    # with height and width of size
    def triangle(x, y, size):
        # stop when the size gets smaller than 2
        # (since we can't subdivide a pixel)
        if size < 2:
            return None
        half = size // 2
        draw_square(x, y, half)
    
        # recursively repeat the triangle
        # for each of the other three quadrants
        triangle(         ,          ,          ) # Fill in the missing parameters of this call
        triangle(         ,          ,          ) # Fill in the missing parameters of this call
        triangle(         ,          ,          ) # Fill in the missing parameters of this call
    
    
    def draw_square(x, y, half):
        # draw a square in the upper left quadrant
        Canvas.Rectangle(1 + x,
                         1 + y,
                         1 + x + half,
                         1 + y + half, width=0, fill="white")