Difference between revisions of "CS110:Lab09"

From IPRE Wiki
Jump to: navigation, search
('''Making Music''')
(Links)
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
='''Lab 09: Exploring Music''' =
+
='''Lab 09: Objects in Graphics''' =
 +
 
  
 
=='''Objective'''==
 
=='''Objective'''==
* Learn some fundamentals of sound and music
+
* Use various Myro commands to create and manipulate graphical objects
* Create musical compositions
+
  
=='''Useful Resources'''==
+
==To Do==
 +
* Execute and modify the pieces of code introduced in this session
 +
* Read Chapter 8 of your text
  
[[ChucK]]
+
== Useful Links ==
  
=='''Sound'''==
+
[[Myro_Reference_Manual#Graphics_Objects_Interface| Myro Graphics Objects Interface]] <br>
Having explored and used many of the robot commands by now, you have seen that your robot make beeps when you call the '''beep()''' function. You can also have Myro make a beep directly out of your computer, rather than the robot. For instance, if you execute the following command:
+
[http://cs.brynmawr.edu/~dkumar/Myro/Text/June09/PDF/Chapter8.pdf| Chapter 8 of your Text]
 +
 
 +
== Creating a Graphics Window ==
 +
 
 +
You have probably used different computer programs such as ''Paint'' or ''GIMP'' to draw different shapes and edit images.  
 +
In this lab session you will be creating and manipulating various drawings.
 +
The Myro module provides various commands you can use to draw objects, color them and
 +
manipulate them in other ways. In order to draw anything you first need to create a window or canvas
 +
to draw it on. You can create such a window using the following command:
  
 
<pre>
 
<pre>
computer.beep(3, 880)
+
myCanvas = GraphWin()
 
</pre>
 
</pre>
  
This command tells your computer to play a tone at 880 Hertz for 3 seconds. Hertz is
+
When you enter this command. A window similar to the one below should appear:
a unit that measures frequency. <br>
+
[[Image:Graphwin.GIF|center]]
  
<b>1Hertz = 1cycle / second </b>
+
To close the window, use the following command:
 +
<pre>
 +
myCanvas.close()
 +
</pre>
  
Therefore, a beep at 880 Hz represents 880 complete cycles per second.
+
By default, the size of the window is 200 pixels high and 200 pixels wide and its name is
Humans can hear frequencies in the 20 Hz to 20000 Hz (or 20 Kilo Hertz) range and
+
“Graphics Window”. To change the size of the window and to rename it, you can execute the command below:
are able to distinguish sounds that differ only by a few
+
<pre>
Hertz (as little as 1 Hz). This ability varies from person to person.
+
myCanvas = GraphWin(“My BigCanvas”, 300, 300)
 
+
</pre>
Try the following commands and see if you can distinguish between the two tones:
+
  
 +
The command above creates a window called “My BigCanvas” that is 300 pixels wide and 300 pixels tall.
 +
You can change the background color of your graphics window to yellow as shown below:
 
<pre>
 
<pre>
computer.beep(1, 440)
+
myCanvas.setBackground(“yellow”)
computer.beep(1, 450)
+
 
</pre>
 
</pre>
 +
[[Image:YellowWin.GIF|center]]
  
To make the tones more distinctive, place the commands above in a loop so
+
Examples of colors you can use are: “red”, “blue”, “gray”, “yellow”, “AntiqueWhite”, “LavenderBlush”, “WhiteSmoke”.
that you can repeatedly hear the alternating tones. <br>
+
There are several thousand color names to choose from. To see a list of these colors, Google: "color names list".  
  
 +
You can also create your own colors by specifying their red, green, and blue components.
 +
Recall from previous labs and lectures that each color is made up of three values: '''RGB''' or red, green and blue color
 +
values. Each of the these values can be in the range 0 to 255. For instance, the RGB values of pure red are: (255, 0, 0).
 +
White is defined as (255,255, 255), black as (0, 0, 0) and pink as (255, 175, 175). There are as many as 256x256x256 colors
 +
(i.e. over 16 million colors!). Given specific RGB values, you can create a new color by using the
 +
command, color_rgb:
 +
<pre>
 +
myColor = color_rgb(255, 175, 175)
 +
</pre>
  
'''Do This:''' Program your computer to create a siren by repeating two
+
== Drawing Objects on your Canvas ==
different tones. You will have to experiment
+
with different pairs of frequencies (they may be close together or far apart) to
+
produce a realistic sounding siren. Write your program to play the siren for 15
+
seconds. The louder the better!
+
  
=='''Musical Scales'''==
+
Once you've created a window, you can then draw a variety of geometrical objects (points, lines, circles, rectangle, and
 +
even text and images) on your canvas. Before you draw an object, however, you must first ''create'' it.
 +
Before you can do this, you should become familiar with the coordinate system of the graphics window.
  
In western music, a ''scale'' is divided into 12 notes (from 7 major notes:
+
In a graphics window with width, W=200 and height H=400 (i.e WxH pixels) the pixel
ABCDEFG). An ''octave'' in C comprises of the 12 notes shown below: <br>
+
(0, 0) is at the top left corner and the pixel (199, 399) will be at the bottom
 +
right corner. That is, x-coordinates increase as you go right and y-coordinates
 +
increase as you go down. <br>
  
<b> C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B </b> <br><br>
+
The simplest object that you can ''create'' is a point. This is done as follows:
 +
<pre>
 +
p = Point(100, 50)
 +
</pre>
  
C# (pronounced "C sharp") is the same tone as Db (pronounced "D flat").
+
In the above command, p is an object that is a Point whose x-coordinate is at 100 and y-coordinate
Frequencies corresponding to a specific note, for example C, are multiplied (or
+
is at 50. This command ''creates'' a Point object. In order to draw it on the canvas, you
divided) by 2 to generate the same note in a higher (or lower) octave. For instance
+
have to enter the command:
in the two tones shown below, the second tone is one octave higher than the first: <br><br>
+
<pre>
computer.beep(1, 440)<br>
+
p.draw(myCanvas)
computer.beep(1, 880) <br> <br>
+
</pre>
  
Therefore in order to raise a tone by 1 octave, you multiply the frequency by 2.
+
In python, objects such as points, strings, lists etc. have standard operations that can be
Likewise, to make a tone 1 octave lower, you divide by 2.  
+
performed on them. The general syntax for carrying out an operation on an object is: <br>
Notes indicating an octave can be denoted as follows: <br>
+
<b>C0 C1 C2 C3 C4 C5 C6 C7 C8 </b><br><br>
+
That is, C0 is the note for C in the lowest (or 0) octave. The fifth octave
+
(numbered 4) is commonly referred to as a middle octave. Thus C4 is the C
+
note in the middle octave. The frequency corresponding to C4 is 261.63 Hz. <br> <br>
+
  
'''Do This:'''
+
<object>.<function>(<parameters>)
Try playing '''C4''' on the computer. Also try C5 (523.25) which is twice the
+
frequency of C4 and C3 (130.815). <br>
+
  
=='''Computing the Computer's Range of Tones'''==
+
In the example above, <object> is the name p which was earlier
 +
defined to be a Point object, <function> is draw, and <parameters> is
 +
myCanvas. The draw function requires the graphics window as the parameter.
 +
That is, you are asking the point represented by p to be drawn in the window
 +
specified as its parameter. The Point objects have other useful functions.
 +
For instance, you can use the following commands to get the  x- and y-coordinates
 +
of the point:
 +
<pre>
 +
>>> p.getX()
 +
100
 +
>>> p.getY()
 +
50
 +
</pre>
  
In common tuning, the 12 notes are equidistant. Therfore, if the frequency doubles every octave, each successive note is 21 / 12 apart. That is, if C4 is 261.63 Hz, C# (or Db) will be:  
+
Objects are created using their ''constructors'' like the Point(x, y) constructor above. You
 +
will use lots of constructors in this section for creating other graphics objects. For instance,
 +
you can create a line object in a similar manner. To create a line, you must specify the location the two end
 +
points of the line. Therefore a line that starts from the point (0, 0) and ends at the point
 +
(100, 200) can be created and drawn as follows:
  
C#4/Db4 = 261.63 *2 ^(1/12) = 277.18
+
<pre>
 +
L = Line(Point(0,0), Point(100,200))
 +
L.draw(myCanvas)
 +
</pre>
  
We can then compute all successive note frequencies:
+
The image below shows the canvas with the objects drawn so far.
  
* D4 = 277.18 * 2 ^ (1/12) = 293.66
+
[[Image:WinLine.GIF|center]]
* D#4/Eb = 293.66 * 2 ^ (1/12) = 311.13 
+
You can then draw the line using the same draw command as above:
* etc. 
+
<pre>
 +
L.draw(myCanvas)
 +
</pre>
  
'''Note: ''' In python, the characters that denote the exponent are '''**'''. Therefore to raise 2 by the exponent 3, you would type:
+
To get the values of a line’s end points, use the following commands:
 +
<pre>
 +
>>> start = L.getP1()
 +
>>> start.getX
 +
0
 +
>>> end = L.getP2()
 +
>>> end.getY()
 +
200
 +
</pre>
  
 +
Here is a small Python loop that can be used to create and draw several lines:
 
<pre>
 
<pre>
2 ** 3
+
for n in range(0, 200, 5):
 +
  L=Line(Point(n,25),Point(100,100))
 +
  L.draw(myCanvas)
 
</pre>
 
</pre>
  
The lowest tone that the Computer can play is A0 and the highest tone is C8. A0 has a frequency of 27.5 Hz, and C8 has a frequency of 4186 Hz. That's quite a range! See if you can you hear the entire range. Try this:
+
[[Image:LinesWin.GIF|center]]
  
 +
In the loop above the value of n starts at 0 and increases by
 +
5 after each iteration all the way up to but not including 200 (i.e. 195). For each value of
 +
n a new Line object is created with starting co-ordinates (n,25) and end point at (100, 100).
 +
 +
'''Do This:''' Try out all the commands introduced in this lab. Then observe the
 +
effects produced by the loop above. Change the increment 5 in the loop above
 +
to different values (1, 3, etc.) and observe the effect. Next, try out the
 +
following loop:
 
<pre>
 
<pre>
computer.beep(1, 27.5)
+
for n in range(0, 200, 3):
computer.beep(1, 4186)
+
L = Line(Point(n, 100), Point(180, 180))
 +
L.draw(myCanvas)
 +
wait(0.3)
 +
L.undraw()
 
</pre>
 
</pre>
  
'''Do This:''' Write a program to play all the 12 notes in an octave
+
The ''undraw'' function, as the name implies, undraws a particular object. In the above for loop,
using the above computation. You may assume in your program that C0 is
+
a line is created for each value of n, drawn, an after 0.3 seconds, erased.  
16.35 and then use that to compute all frequencies in a given octave (C4 is
+
Once again, you should modify different values in this loop, such as the increment or the wait time
16.35 * 24). Your program should input an octave (a number from 0 through
+
to see the effect.
8), produce all the notes in that octave and also printout a frequency chart for
+
each note in that octave.
+
  
== '''Making Music''' ==
+
== Drawing Other Geometric Objects ==
  
Now we turn from beeps to music. First, let's make an easy method of playing notes by name, rather than by frequencies:
+
You can draw several other geometrical shapes such as: circles, rectangles, ovals, and
 +
polygons. Once again, in order to draw any of these shapes, you must first create it. For instance,
 +
to draw a circle, you can issue the commands:
  
 
<pre>
 
<pre>
from myro import *
+
centerPoint = Point(100, 150)
 
+
radius = 30
def getFrequency(noteName):
+
C = Circle(centerPoint, radius)
    return media._frequncy[noteName.lower()]
+
C.draw(myCanvas)
 
</pre>
 
</pre>
  
To use this, you can give it the name of a note as a string, and get back the frequency. For example:
+
centerPoint is a Point object and radius is specified in pixels. Thus, the circle C is
 +
centered at (100, 150) and has a radius of 30. For details on how other shapes are drawn,
 +
you can go to the link to ''Myro Graphics Objects Interface'' above. <br><br>
  
 +
All the geometrical objects have several functions in common. For instance,
 +
you can get the center point of a circle, (as well as a rectangle, or an oval) by
 +
using the command:
 
<pre>
 
<pre>
>>> getFrequency("C4")
+
centerPoint = C.getCenter()
261.60000000000002
+
 
+
>>> computer.beep(1, getFrequency("C4"))
+
[plays a lovely note at that frequency for 1 second]
+
 
</pre>
 
</pre>
  
You can also transcribe an entire song as a string using the makeSong() function in Myro. For example, to get the frequencies and timings for "A4 1/4; C5 1/8; C5 1/8; A4 1/4" you could:
+
By default, all objects are drawn in black (this may be white if you are using a Mac).
 
+
There are a number of ways to modify colors for objects. For each object you can specify a color for its
>>> makeSong("A4 1/4; C5 1/8; C5 1/8; A4 1/4")
+
outline as well as a color to fill it with. For example, to draw a circle centered
[(440.0, 0.25), (523.29999999999995, 0.125), (523.29999999999995, 0.125), (440.0, 0.25)]
+
at (100, 150), radius 30, and outline color red, and fill color yellow:
 
+
To use this, you could:
+
 
+
 
<pre>
 
<pre>
for freq, note in makeSong("A4 1/4; C5 1/8; C5 1/8; A4 1/4"):
+
C = Circle(Point(100, 150), 30)
    # convert notes (eq, 1/4) into seconds:
+
C.draw(myCanvas)
    beat = note * 4 * 0.4              # 1/4 = one beat, which lasts for 0.4 seconds
+
C.setOutline(“red”)
    computer.beep(beat, freq)
+
C.setFill(“yellow”)
 
</pre>
 
</pre>
  
You can also put the song in a separate file and use '''readSong(filename)'''. For more details on this function, see [[Song File Format]].
+
Note: setFill and setOutline have the same effect on Point and Line objects
 
+
(since there is no place to fill any color). Also, the line or the
Now, explore the functions of [[ChucK]] i.e. '''Run the example commands you see!!''' ChucK is already installed on the machines in the lab so you can skip the section that deals with installation if you are doing these exercises in the la. You will need to understand the basic operations to continue. <br>
+
outline drawn is always 1 pixel thick. You can change the thickness by using
 
+
the command setWidth(<pixels>). For example to change the width of the circle’s outline to 5 pixels:
After you have used the functions in ChucK, you will see that you can change the  
+
frequencies of different instruments pretty easily by using the '''setFrequency''' command.  
+
So instead of changing the frequency of the computer and making it beep, you could change the
+
frequency of a mandolin and pluck its strings using commands similar to the ones
+
you just executed:  
+
 
+
 
<pre>
 
<pre>
man = Mandolin() #create a mandolin instrument
+
C.setWidth(5)
man.connect()
+
for freq, note in makeSong("A4 1/4; C5 1/8; C5 1/8; A4 1/4"):
+
    man.setFrequency(freq)
+
    wait(0.3)
+
    m.pluck(note)
+
 
</pre>
 
</pre>
  
== Creating Instruments and Parts ==
+
== Drawing Random Circles ==
  
For this example, we will create a 7 measure song, each measure having three beats. Let's define a beat to be 0.4 seconds long.
+
'''Do This:''' The program below draws several circles of random sizes with
 +
random colors. Try it out! A sample output is shown below.
  
First, let's start with a percussion background. If we make a quarter note be one beat, then there are 3 quarter notes in a measure. This is known as 3 4 time.
 
  
Let's have our percussion play a quarter note, eighth note, eighth note, quarter.  
+
[[Image:RandomCircles.GIF|center]]
 +
<pre>
 +
# File: randomCirles.py
 +
# Description: Program to draw a bunch of random colored circles
  
To make this a little easier, let's create a generic function that will tell an instrument to play a note at a given strength, and wait a certain amount of time. This is very similar to how we move a robot:
+
from random import *
  
# helper function to play one sound / note
+
def makeCircle(x, y, r):
def playOnce(instrument, time, strength):
+
     # creates a Circle centered at point (x, y) of radius r
     instrument.noteOn(strength)
+
     return Circle(Point(x, y), r)
     wait(time)
+
  
Next, we define the percussion instrument (a Shaker) and its 7-measure part:
+
def makeColor():
 +
    # creates a new color using random RGB values
 +
    red = randrange(0, 256)
 +
    green = randrange(0, 256)
 +
    blue = randrange(0, 256)
 +
    return color_rgb(red, green,blue)
  
def playShakers():
+
def main():
     shakers = Shakers()
+
     # Create and display a graphics window
     shakers.connect()
+
    width = 300
     beat = 0.4
+
    height = 300
     for i in range(7):
+
    myCanvas = GraphWin(" Random Circles",width,height)
         playOnce(shakers, beat, 1)
+
     myCanvas.setBackground("white")
         playOnce(shakers, beat/2, .8)
+
     # draw a bunch of random circles with random colors
         playOnce(shakers, beat/2, .8)
+
    N = 200
         playOnce(shakers, beat, 1)      
+
     for i in range(N):
    shakers.noteOn(1)
+
         # pick random center point and radius in the window
 +
        x = randrange(0,width)
 +
         y = randrange(0,height)
 +
         r = randrange(5, 25)
 +
         c = makeCircle(x, y, r)
 +
        # select a random color
 +
        c.setFill(makeColor())
 +
        c.draw(myCanvas)
 +
main()
 +
</pre>
  
Notice that this repeats 7 measure of the 1/4 1/8 1/8 1/4 pattern. To leave the shakers in a normal state, we issue the command '''shakers.noteOn(1)'''. Also, we define the instrument as a function of no parameters. This is important for later.
+
'''Do This:''' Modify the program to input (specify) the number of circles
 +
to be drawn. Recall: randrange(m,n) returns a random number in range [m to n-1].
 +
Modify the program to create other geometric shapes and draw them randomly.
  
You can test it with:
+
== Animating Geometric Objects ==
 +
You can move any geometric object you draw in the graphics window by using the command
 +
'''move(dx, dy)'''. For example, to move the circle, C, 10 pixels to the right and 5
 +
pixels down you can use the command (Note: C must have already been predefined):
 +
<pre>
 +
C.move(10, 5)
 +
</pre>
 +
'''Do This:''' Write a program that moves a circle about (randomly) in the
 +
graphics window. First, enter this following program and try it out.
 +
<pre>
 +
# Moving a circle
  
>>> playShakers()
+
from random import *
 +
def main():
 +
    # create and draw the graphics window
 +
    w = GraphWin("Moving Circle", 500, 500)
 +
    w.setBackground("white")
 +
    # Create a red circle
 +
    c = Circle(Point(250, 250), 50)
 +
    c.setFill("purple")
 +
    c.draw(w)
 +
    # Do a simple animation for 200 steps
 +
    for i in range(200):
 +
        c.move(randrange(-4, 5), randrange(-4, 5))
 +
        wait(0.2)
 +
main()
 +
</pre>
 +
'''Do This:''' Write a program to move different geometric objects around in
 +
your graphics window.
 +
==Drawing Text and Images==
  
And let's define another instrument, and its part:
+
You can also insert '''text''' into your graphics window just like you did with geometric shapes.
 +
You will first have to create the text using the command:
 +
<pre>
 +
myText = Text(<anchor point>, <string>)
 +
</pre>
  
def playBar():
+
and then draw it. You can specify the type face, size, and style of the text. See the Myro graphics reference
    bar = StruckBar()
+
at the end of chapter 8 in your text or on the link provided above to get more details about the
    bar.connect()
+
different features of texts. <br>
    beat = 0.4
+
    wait(beat * 6) # wait for 2 measures / loop iterations
+
    for i in range(5):
+
        playOnce(bar, beat/2, .8)       
+
        playOnce(bar, beat/2, .8)
+
        playOnce(bar, beat, 1)
+
        playOnce(bar, beat, 1)
+
    bar.noteOn(1)
+
  
and test it:
+
'''Images''' can also be treated like the geometric objects you have been creating and drawing. You can create an
 +
image using the Image command:
 +
<pre>
 +
myPhoto = Image(<centerPoint>, <file name>)
 +
</pre>
  
>>> playBar()
+
You have to have an already prepared image in one of the common image
 +
formats (like JPEG, GIF, etc.) and stored in a file (<file name>). Once the
 +
image object is created, it can be drawn, undrawn, or moved just like other
 +
shapes. <br>
  
Notice how it waits for two measures (6 beats) and then plays 5 measures.
+
You can use a combination of texts, images, and geometric objects to create
 +
simple and more advanced graphical programs such as making plots, creating art,
 +
developing video games or graphical user interfaces, or even an
 +
animated story. What you do with this knowledge is only limited by your creativity.
  
And finally, a Mandolin part:
+
= Assignment 09 =
  
def playMandolin():
+
'''*** Exercise 4 will be graded as a BONUS''' worth 4 points. Exercises 1-3 will be graded out of 9. <br>
    m = Mandolin()
+
    m.connect()
+
    m.setGain(0.3)
+
    beat = 0.4
+
    wait(beat * 12) # wait for 4 measures / loop iterations
+
    for i in range(3):
+
        playOnce(m, beat, 1)
+
        playOnce(m, beat, 1)
+
        playOnce(m, beat/2, .8)
+
        playOnce(m, beat/2, .8)
+
    m.noteOn(1)
+
  
Notice that it waits 4 measures (12 beats) and then plays 3 measures.
+
---------------------------------------------------------------------------------------------------
 +
'''***Original Assignment below'''<br>
  
This Mandolin part plays all the same note. You can change the frequency of such instruments using the '''setFrequency()''' method. See [[ChucK]] for more details. Combined with the '''makeSong()''' function (above) you can create beautiful duets between say, a Violin and a Piano.
+
'''Chapter 8, Exercises 1 - 4. ''' '''Note: ''' Exercise Four is a BONUS Part. These exercises are detailed below: <br>
  
== '''Creating an Orchestra'''==
+
'''Exercise 1: ''' Using the graphics commands learned in this session (and detailed in your text), write a
 +
program to generate a seasonal drawing: winter, summer, beach, or a festival scene. <br>
  
To play multiple parts together, we'll use the '''doTogether''' function. It takes a series of function names, and plays them together.
+
'''Exercise 2: ''' Write a program that has a function drawRobot(x, y, w) such that it draws the
 +
figure of a robot shown on the right (see your text for this image, pg. 212). The robot is anchored at (x, y) and is drawn in the window, w. Also notice that the robot is entirely made up of rectangles (8 of them). <br>
  
>>> doTogether(playShakers, playBar, playMandolin)
+
'''Exercise 3: ''' Using the drawRobot function from the previous exercise, draw a pyramid of robot as shown on the right
 
+
(see your text for this image, pg. 212).
NOTE: don't put this line in your file. Instead, type it in the Python Shell.
+
 
+
= Assignment 09 =
+
  
'''Write a piece of music and perform it:''' The composition should be at least 1 minute 30 seconds in length. You should use at least three instruments, and one of those should use different frequencies. Your assignment will be graded on style of code, and style of music. Demos will be done the following week. HINT: you might want to find some musical compositions on the web to play some nice music. For example, a search for "notes to ode to joy" found this: [http://wiki.answers.com/Q/What_are_the_notes_ode_to_joy ode_to_joy].
+
'''Exercise 4: ''' Suppose that each robot from the previous exercise is colored using one of
 +
the colors: red, blue, green, and yellow. Each time a robot is drawn, it uses the
 +
next color in the sequence. Once the sequence is exhausted, it recycles. Write
 +
a program to draw the above pyramid so robots appear in these colors as they
 +
are drawn. You may decide to modify drawRobot to have an additional
 +
parameter: drawRobot(x, y, c, w) or you can write it so that drawRobot
 +
decides which color it chooses. Complete both versions and compare the
 +
resulting programs. Discuss the merits and/or pitfalls of these versions with
 +
friends. [Hint: Use a list of color names.] Note: You only need to ensure that each robot on the same level of the pyramid has the same color. <br>
  
'''Bonus points''' will be given for extra components: more than three parts, use of frequencies, harmony, variety of instruments, fast parts/slow parts, etc.
+
= Links =
  
= Links to Course-Related Pages =
 
 
* Back to [http://wiki.roboteducation.org/CS110_Lab Lab Home Page]  
 
* Back to [http://wiki.roboteducation.org/CS110_Lab Lab Home Page]  
* Back to [http://cs.brynmawr.edu/Courses/cs110/fall2009/ Course Home Page]
+
* Back to [http://cs.brynmawr.edu/Courses/cs110/spring2010/ Course Home Page]

Latest revision as of 18:09, 25 March 2010

Lab 09: Objects in Graphics

Objective

  • Use various Myro commands to create and manipulate graphical objects

To Do

  • Execute and modify the pieces of code introduced in this session
  • Read Chapter 8 of your text

Useful Links

Myro Graphics Objects Interface
Chapter 8 of your Text

Creating a Graphics Window

You have probably used different computer programs such as Paint or GIMP to draw different shapes and edit images. In this lab session you will be creating and manipulating various drawings. The Myro module provides various commands you can use to draw objects, color them and manipulate them in other ways. In order to draw anything you first need to create a window or canvas to draw it on. You can create such a window using the following command:

myCanvas = GraphWin()

When you enter this command. A window similar to the one below should appear:

Graphwin.GIF

To close the window, use the following command:

myCanvas.close()

By default, the size of the window is 200 pixels high and 200 pixels wide and its name is “Graphics Window”. To change the size of the window and to rename it, you can execute the command below:

myCanvas = GraphWin(“My BigCanvas”, 300, 300)

The command above creates a window called “My BigCanvas” that is 300 pixels wide and 300 pixels tall. You can change the background color of your graphics window to yellow as shown below:

myCanvas.setBackground(“yellow”)
YellowWin.GIF

Examples of colors you can use are: “red”, “blue”, “gray”, “yellow”, “AntiqueWhite”, “LavenderBlush”, “WhiteSmoke”. There are several thousand color names to choose from. To see a list of these colors, Google: "color names list".

You can also create your own colors by specifying their red, green, and blue components. Recall from previous labs and lectures that each color is made up of three values: RGB or red, green and blue color values. Each of the these values can be in the range 0 to 255. For instance, the RGB values of pure red are: (255, 0, 0). White is defined as (255,255, 255), black as (0, 0, 0) and pink as (255, 175, 175). There are as many as 256x256x256 colors (i.e. over 16 million colors!). Given specific RGB values, you can create a new color by using the command, color_rgb:

myColor = color_rgb(255, 175, 175)

Drawing Objects on your Canvas

Once you've created a window, you can then draw a variety of geometrical objects (points, lines, circles, rectangle, and even text and images) on your canvas. Before you draw an object, however, you must first create it. Before you can do this, you should become familiar with the coordinate system of the graphics window.

In a graphics window with width, W=200 and height H=400 (i.e WxH pixels) the pixel (0, 0) is at the top left corner and the pixel (199, 399) will be at the bottom right corner. That is, x-coordinates increase as you go right and y-coordinates increase as you go down.

The simplest object that you can create is a point. This is done as follows:

p = Point(100, 50)

In the above command, p is an object that is a Point whose x-coordinate is at 100 and y-coordinate is at 50. This command creates a Point object. In order to draw it on the canvas, you have to enter the command:

p.draw(myCanvas)

In python, objects such as points, strings, lists etc. have standard operations that can be performed on them. The general syntax for carrying out an operation on an object is:

<object>.<function>(<parameters>)

In the example above, <object> is the name p which was earlier defined to be a Point object, <function> is draw, and <parameters> is myCanvas. The draw function requires the graphics window as the parameter. That is, you are asking the point represented by p to be drawn in the window specified as its parameter. The Point objects have other useful functions. For instance, you can use the following commands to get the x- and y-coordinates of the point:

>>> p.getX()
100
>>> p.getY()
50

Objects are created using their constructors like the Point(x, y) constructor above. You will use lots of constructors in this section for creating other graphics objects. For instance, you can create a line object in a similar manner. To create a line, you must specify the location the two end points of the line. Therefore a line that starts from the point (0, 0) and ends at the point (100, 200) can be created and drawn as follows:

L = Line(Point(0,0), Point(100,200))
L.draw(myCanvas)

The image below shows the canvas with the objects drawn so far.

WinLine.GIF

You can then draw the line using the same draw command as above:

L.draw(myCanvas)

To get the values of a line’s end points, use the following commands:

>>> start = L.getP1()
>>> start.getX
0
>>> end = L.getP2()
>>> end.getY()
200

Here is a small Python loop that can be used to create and draw several lines:

for n in range(0, 200, 5):
   L=Line(Point(n,25),Point(100,100))
   L.draw(myCanvas)
LinesWin.GIF

In the loop above the value of n starts at 0 and increases by 5 after each iteration all the way up to but not including 200 (i.e. 195). For each value of n a new Line object is created with starting co-ordinates (n,25) and end point at (100, 100).

Do This: Try out all the commands introduced in this lab. Then observe the effects produced by the loop above. Change the increment 5 in the loop above to different values (1, 3, etc.) and observe the effect. Next, try out the following loop:

for n in range(0, 200, 3):
	L = Line(Point(n, 100), Point(180, 180))
	L.draw(myCanvas)
	wait(0.3)
	L.undraw()

The undraw function, as the name implies, undraws a particular object. In the above for loop, a line is created for each value of n, drawn, an after 0.3 seconds, erased. Once again, you should modify different values in this loop, such as the increment or the wait time to see the effect.

Drawing Other Geometric Objects

You can draw several other geometrical shapes such as: circles, rectangles, ovals, and polygons. Once again, in order to draw any of these shapes, you must first create it. For instance, to draw a circle, you can issue the commands:

centerPoint = Point(100, 150)
radius = 30
C = Circle(centerPoint, radius)
C.draw(myCanvas)

centerPoint is a Point object and radius is specified in pixels. Thus, the circle C is centered at (100, 150) and has a radius of 30. For details on how other shapes are drawn, you can go to the link to Myro Graphics Objects Interface above.

All the geometrical objects have several functions in common. For instance, you can get the center point of a circle, (as well as a rectangle, or an oval) by using the command:

centerPoint = C.getCenter()

By default, all objects are drawn in black (this may be white if you are using a Mac). There are a number of ways to modify colors for objects. For each object you can specify a color for its outline as well as a color to fill it with. For example, to draw a circle centered at (100, 150), radius 30, and outline color red, and fill color yellow:

C = Circle(Point(100, 150), 30)
C.draw(myCanvas)
C.setOutline(“red”)
C.setFill(“yellow”)

Note: setFill and setOutline have the same effect on Point and Line objects (since there is no place to fill any color). Also, the line or the outline drawn is always 1 pixel thick. You can change the thickness by using the command setWidth(<pixels>). For example to change the width of the circle’s outline to 5 pixels:

C.setWidth(5)

Drawing Random Circles

Do This: The program below draws several circles of random sizes with random colors. Try it out! A sample output is shown below.


RandomCircles.GIF
# File: randomCirles.py
# Description: Program to draw a bunch of random colored circles

from random import *

def makeCircle(x, y, r):
    # creates a Circle centered at point (x, y) of radius r
    return Circle(Point(x, y), r)

def makeColor():
    # creates a new color using random RGB values
    red = randrange(0, 256)
    green = randrange(0, 256)
    blue = randrange(0, 256)
    return color_rgb(red, green,blue)

def main():
    # Create and display a graphics window
    width = 300
    height = 300
    myCanvas = GraphWin(" Random Circles",width,height)
    myCanvas.setBackground("white")
    # draw a bunch of random circles with random colors
    N = 200
    for i in range(N):
        # pick random center point and radius in the window
        x = randrange(0,width)
        y = randrange(0,height)
        r = randrange(5, 25)
        c = makeCircle(x, y, r)
        # select a random color
        c.setFill(makeColor())
        c.draw(myCanvas)
main()

Do This: Modify the program to input (specify) the number of circles to be drawn. Recall: randrange(m,n) returns a random number in range [m to n-1]. Modify the program to create other geometric shapes and draw them randomly.

Animating Geometric Objects

You can move any geometric object you draw in the graphics window by using the command move(dx, dy). For example, to move the circle, C, 10 pixels to the right and 5 pixels down you can use the command (Note: C must have already been predefined):

C.move(10, 5)

Do This: Write a program that moves a circle about (randomly) in the graphics window. First, enter this following program and try it out.

# Moving a circle

from random import *
def main():
    # create and draw the graphics window
    w = GraphWin("Moving Circle", 500, 500)
    w.setBackground("white")
    # Create a red circle
    c = Circle(Point(250, 250), 50)
    c.setFill("purple")
    c.draw(w)
    # Do a simple animation for 200 steps
    for i in range(200):
        c.move(randrange(-4, 5), randrange(-4, 5))
        wait(0.2)
main()

Do This: Write a program to move different geometric objects around in your graphics window.

Drawing Text and Images

You can also insert text into your graphics window just like you did with geometric shapes. You will first have to create the text using the command:

myText = Text(<anchor point>, <string>)

and then draw it. You can specify the type face, size, and style of the text. See the Myro graphics reference at the end of chapter 8 in your text or on the link provided above to get more details about the different features of texts.

Images can also be treated like the geometric objects you have been creating and drawing. You can create an image using the Image command:

myPhoto = Image(<centerPoint>, <file name>)

You have to have an already prepared image in one of the common image formats (like JPEG, GIF, etc.) and stored in a file (<file name>). Once the image object is created, it can be drawn, undrawn, or moved just like other shapes.

You can use a combination of texts, images, and geometric objects to create simple and more advanced graphical programs such as making plots, creating art, developing video games or graphical user interfaces, or even an animated story. What you do with this knowledge is only limited by your creativity.

Assignment 09

*** Exercise 4 will be graded as a BONUS worth 4 points. Exercises 1-3 will be graded out of 9.


***Original Assignment below

Chapter 8, Exercises 1 - 4. Note: Exercise Four is a BONUS Part. These exercises are detailed below:

Exercise 1: Using the graphics commands learned in this session (and detailed in your text), write a program to generate a seasonal drawing: winter, summer, beach, or a festival scene.

Exercise 2: Write a program that has a function drawRobot(x, y, w) such that it draws the figure of a robot shown on the right (see your text for this image, pg. 212). The robot is anchored at (x, y) and is drawn in the window, w. Also notice that the robot is entirely made up of rectangles (8 of them).

Exercise 3: Using the drawRobot function from the previous exercise, draw a pyramid of robot as shown on the right (see your text for this image, pg. 212).

Exercise 4: Suppose that each robot from the previous exercise is colored using one of the colors: red, blue, green, and yellow. Each time a robot is drawn, it uses the next color in the sequence. Once the sequence is exhausted, it recycles. Write a program to draw the above pyramid so robots appear in these colors as they are drawn. You may decide to modify drawRobot to have an additional parameter: drawRobot(x, y, c, w) or you can write it so that drawRobot decides which color it chooses. Complete both versions and compare the resulting programs. Discuss the merits and/or pitfalls of these versions with friends. [Hint: Use a list of color names.] Note: You only need to ensure that each robot on the same level of the pyramid has the same color.

Links