ACM SIGCSE 2003: Multimedia Construction Projects
Download
Report
Transcript ACM SIGCSE 2003: Multimedia Construction Projects
Project “Georgia Computes!”
First Courses Workshop
Day 2
Mark Guzdial
College of Computing
Georgia Institute of Technology
[email protected]
http://www.cc.gatech.edu/~mark.guzdial
http://www.georgiacomputes.org
Workshop Plan-Day 2
9-10:30: Introduction to Computing using Robotics in
Python
10:30-11:30: Tackling a homework assignment in
Robotics
11:30-12:30: Lunch
12:30-2:30: Introduction to Computing for Engienering
using MATLAB
Follow the light
2:30-2:45: Break
2:45-4:30: Data Structures in Media Computation using
Java
4:30-5: Wrap-up discussion and evaluation of workshop
CS1 Robotics with Python
Microsoft Research has funded the
Institute for Personal Robotics in
Education
Tucker Balch, Directing
Monica Sweat, Developing GT’s CS1
Joint between Bryn Mawr and
Georgia Tech
Doug Blank (Developing Myro)
Deepak Kumar (Teaching their first
CS1 with robots)
http://www.roboteducation.org
Curriculum Goals
Make entry into computer science more
accessible
Revamp
CS1 & CS2 curricula
Use personal robots as a “vehicle”
Fresh approach to introducing computing
Influence robot design based on past experience
Influence software development
Pilot CS1 in Spring 2007
Offered at Bryn Mawr (Deepak Kumar) and
GaTech (Monica Sweat)
Use the Parallax Scribbler robot
Wireless bluetooth interface designed by
GaTech enables Scribbler interface
Myro software running under Dr. Python (IDE) to
control Scribbler
Course will provide additional data on curriculum
design
Curriculum Development Strategy
Step One: Figure out something that students
will want to do.
Step Two: Teach the CS and Robotics to make
that happen.
Goals:
Relevance
Motivation
Context
for Transferrable Learning
Example CS1 Exercises: Early
Focus on variables, arguments, functions, giving
commands to a computer, sequencing commands
Personalize your robot (use colors, pens, stickers, etc.).
Give it a personality, and a specific “move”
Then experiment with difference basic robot movement
behaviors (go forward, backward, spin, turn, etc.) and learn how
to upload and play a tune. Design a series of steps for your robot
to perform a dance while playing a tune.
Test the sensitivity and range of IR sensors for light
detection, obstacle detection. The latter will vary
depending on the reflectance of the object being
sensed...
Put these results in Excel to introduce ideas of computational
science: Gathering data from sensors and analyzing it.
Example CS1 Exercises: Later
Iteration
Focus on iterating, sequencing within an iteration, limiting iteration
Experiment with simple behaviors like going forward for a while and
then backward. Repeat these behaviors several times. Does the
robot track the same space or are the movements shifting its space?
A good way to test these would be to insert a pen and let the robot
draw its path each time. This will help observe and get used to
variations in your robots motor behaviors.
Write a loop to input a sound (could be on laptop instead of robot)
then play it back. Do this in a group of robots. Make a sound,
allowing the group behavior and dynamics to create a cacophony.
Write programs for the robot to draw a square, a circle, a figure-8, a
5 point star...and other shapes...a spiral?
Example CS1 Exercises: Powerful
Representation and Interpretation
Using some other data structure or sensed data as a command to drive
other behavior
Create a file with commands like "left on 30 \n right on 30 \n beep" Write a
program to read these commands and execute them – in other words,
define a mini robot language and write an interpreter for it. Gives us the
opportunity to address string processing, a typical CS1 topic.
Have one robot "call out" audio commands (perhaps specific tones, via the
speaker), and have other robots "hear" the commands (via microphones)
and execute the commands.
Follow a line of symbols/fiducials, where the symbols (colors or scan codes)
can be interpreted as music. Start the robot on the line, and as it encounters
the markings, it plays a note. The spacing is the timing of the songs. Put
one after another, and they play in a round. Have two go together (on two
lines) and they play a harmony. The robot could also write the music with a
pen. First robot writes the song, second robot plays it.
Parallax Scribbler Robot
Low cost ($80) and features
3 photosensors
IR sensors in front
IR on chasis
Servo controlled motors
3 Programmable LEDs
Speaker
Battery operated (6 AAs)
Serial interface
Assessment Methods
Within term:
Initial,
midterm, final surveys.
Focus group or individual student interviews.
Across term:
– do they stay in CS?
How well do they do?
Tracking
Installing Myro on Windows
1.
2.
3.
Download the latest Myro from
http://wiki.roboteducation.org/Windows_Setup
Save it, open it, and expand it.
Double-click on install.bat
Setting up Bluetooth
Testing Myro
Testing the Robot
In other words:
initialize(“com5”)
Controlling the robot’s motors
Most Myro robot movement functions control the
speed (specifically, amount of power) of the
motor.
motors(1.0,0.5)
# Gives full power to motor Left,
# half power to motor Right
forward(1.0) #Both motors, full speed ahead
backward(0.5) #Backwards, half speed
turnLeft (0.1) #Turn left, slowly
turnRight(0.25) # Turn right, slightly more quickly
stop() #STOP EVERYTHING
same as motors(0,0)
Defining a robot function: Yoyo
def yoyo():
forward(1)
wait(1) # Wait one second
backward(1)
wait(1)
stop()
Can just type
this in, and then
execute it as:
yoyo()
Or can enter it
into a module
(filename)
Parameterizing our YoYo
def yoyo1(speed):
forward(speed)
wait(1) # Wait one second
backward(speed)
wait(1)
stop()
Further parameterizing
def yoyo2(speed, wait):
forward(speed)
wait(wait)
backward(speed)
wait(wait)
stop()
# Wait a bit
Can do something forever
from myro import *
initialize(“com5”)
def yoyo2(speed, wait):
forward(speed)
wait(wait) # Wait one
second
backward(speed)
wait(wait)
stop()
def wiggle(speed,waitTime):
rotate(speed)
wait(waitTime)
rotate(-speed)
wait(waitTime)
stop()
def dance():
while True:
yoyo2(1.0,1)
wiggle(1.0,0.2)
yoyo2(0.5,0.5)
wiggle(0.5,0.5)
Use Control-C to
stop this.
Using the robot as an object
Robot can be controlled using global functions,
or as methods to robot objects.
Review
from myro import *
robot = Scribbler(“com4”)
robot.turnRight(0.25); wait(0.25); robot.stop()
robot.forward(0.25); wait(0.25); robot.stop()
def function():
while True:
Reading the Light Sensors
robot.getLight(0)
robot.getLight(1)
robot.getLight(2)
>>> robot.getLight()
[657, 1453, 1025]
Light
sensors
Which one is which?
Exercise: Playing blind man’s bluff
0,1,2:
left, right, center?
Do the values go up with darkness or with light?
Modeling Animals
How do animals sense light?
Why do moths move to the light?
How do they know which way to turn to
get there?
Does it matter if you see vs. smell?
Let’s model light-seeking behavior
Choosing action depending on senses
New statement: if
Allows us to test conditions (logical expressions)
and choose actions based on those conditions.
if
(some logical test goes here) :
The actions go on the line below, indented.
if robot.getLight(0) > 800:
robot.turnLeft(0.25)
Blocks
Just like the lines after def and while, all the lines
indented the same after if are part of the same block
A block is defined in Python by indentation.
Lines at the same level of indentation are in the same block.
A block is used to define the body of a function and the
loop.
A block is used to define the actions of a successful if
test.
Where’s the light?
We can compare against a value, but what we
really care about is the relative light values.
if robot.getLight(0) > robot.getLight(2):
print "LEFT!"
Signaling a Turn
def signalingTurn():
left = 0
right = 2
while True:
if robot.getLight(left) < robot.getLight(right):
print “Left!"
if robot.getLight(right) < robot.getLight(left):
print "Right!"
signalingTurn()
Audibly signaling a turn
def signalingTurn():
left = 0
right = 2
while True:
if robot.getLight(left) < robot.getLight(right):
robot.beep(0.25,400)
if robot.getLight(right) < robot.getLight(left):
robot.beep(0.25,800)
signalingTurn()
Making Music
beep(1,400) #Plays at frequency 400 Hz
# for 1 second
computer.beep(0.5,440)
# Has the computer beep at A-above-middle C
# (440 Hz) for ½ second
Can they play a duet?
Try it!
Myro Song Format
Myro has a more music-like format that it
supports:
s = makeSong(“c 1; d .5; d#4 1/2”)
# C in the fifth octave for a whole note
# D in the fifth octave for a 1/2 note
# D-sharp in fourth octave for a 1/2 note
robot.playSong(s,0.75) # Play this for ¾ second
Exercises
Option #1: Follow the Light
Write a function that will turn the robot toward
the light, much as an insect might follow the
light.
Can
you turn based on the amount of light?
Option #2: Make the Robot Dance
Write a program to play music and “dance” your
Scribbler
Use
beep() and playSong to make music
Use movements like yoyo and wiggle
CS1 for Engineering in MATLAB
Syllabus
Sample lessons on getting started
Syllabus
Getting started with MATLAB
Introduction to Vectors, the main MATLAB data type
Conditionals, iteration, and functions
Cell arrays (mini-databases)
Structures
Problem solving
General arrays
Graphing (MATLAB does professional quality graphics)
Bodies of Rotation and Matrices
File I/O
Multimedia: Image and sound manipulation
Serious CS: Numerical methods, Big O, Sorting,
Queues, and Graphs
Objectives – the MATLAB User
Interface
■ How to use the Command window to explore single
commands interactively and how to recall earlier
commands to be repeated or changed
■ Where to examine the variables and files created in
MATLAB
■ How to view and edit data tables created in MATLAB
■ How MATLAB presents graphical data in separate
windows
■ How to create scripts to solve simple arithmetic problems
File menu
Close icon
The Default Window
Current
directory
Command window
Workspace window
Command history
Array Editor
New variable icon
If you don’t have MATLAB, Octave!
2.4 Scripts
Create a script derived from the Pythagorean theorem to compute
the hypotenuse of a right triangle:
H2 = A2 + B2
where A and B are the sides adjacent to the right angle, and H is
the hypotenuse opposite.
clear
clc
A = 3; % the first side of a triangle
B = 4; % the second side of a triangle
hypSq = A^2 + B^2; % the square of the
% hypotenuse
H = sqrt(hypSq) % the answer
2.5 Engineering Example—Spacecraft
Launch
clear
clc
cmPerInch = 2.54; % general knowledge
inchesPerFt = 12; % general knowledge
metersPerCm = 1/100; % general knowledge
MetersPerFt = metersPerCm * cmPerInch * inchesPerFt;
startFt = 25000; % ft - given
startM = startFt * MetersPerFt;
g = 9.81; % m/sec^2
top = 100; % km - given
s = (top*1000) - startM; % m
initial_v = (2*g*s)^0.5 % the final answer
3.1 Concept: Using Built-in
Functions
In this chapter we will see the use of some of the functions built into
MATLAB.
At the end of each chapter that uses built-in functions, you will find a
summary table listing the function specifications.
For help on a specific function, you can type the following:
>> help <function name>
For example:
>> help sqrt
SQRT
Square root.
SQRT(X) is the square root of the elements of X.
Complex results are produced if X is not positive.
3.2 Concept: Data Collections
This section considers two very common ways to group data: in arrays
and in vectors.
Data Abstraction allows us to refer to groups of data collectively:
“all the temperature readings for May” or
“all the purchases from Wal-Mart.”
We can not only move these items around as a group, but also perform
mathematical or logical operations on these groups, e.g.:
compute the average, maximum, or minimum temperatures for a month
A Homogeneous Collection is constrained to accept only items of the
same data type – in this case, they will all be numbers
3.3 MATLAB Vectors
Individual items in a vector are usually referred to as its elements.
Vector elements have two separate and distinct attributes that make
them unique in a specific vector:
their numerical value and
their position in that vector.
For example, the individual number 66 is the third element in this
vector. Its value is 66 and its index is 3. There may be other items in the
vector with the value of 66, but no other item will be located in this
vector at position 3.
Vector Manipulation
We consider the following basic operations on
vectors:
Creating
a Vector
Determining the size of a Vector
Extracting data from a vector by indexing
Shortening a Vector
Mathematical and logical operations on Vectors
Creating a Vector – Constant
Values
Entering the values directly, e.g.
A = [2, 5, 7, 1, 3]
Entering the values as a range of numbers e.g.,
B = 1:3:20
Using the linspace(...) function e.g.
C = linspace (0, 20, 11)
Using the functions zeros(1,n), ones(1,n), rand(1,n) and
randn(1,n) to create vectors filled with 0, 1, or random
values between 0 and 1
Size of Vectors and Arrays
MATLAB provides two functions to determine the
size of arrays in general (a vector is an array with
one row):
the
function size(A) when applied to the array A
returns vector containing two quantities: the number
of rows and the number of columns
The function length(A) returns the maximum value in
the size of an array; for a vector, this is its length.
Indexing a Vector
The process of extracting values from a vector,
or inserting values into a vector
Syntax:
v(index)
returns the element(s) at the location(s)
specified by the vector index.
v(index) = value replaces the elements at the
location(s) specified by the vector index.
The indexing vector may contain either
numerical or logical values
Numerical Indexing
The indexing vector may be of any length
It should contain integer (non-fractional)
numbers
The values in the indexing vector are
constrained by the following rules:
For
reading elements, all index values must be
1 <= element <= length(vector)
For
replacing elements, all index values must be
1 <= element
Replacement Rules
Either:
1.
•
•
All dimensions of the blocks on either side of the replacement
instruction must be equal, or
There must be a single element on the RHS of the
replacement
If you replace beyond the end of the existing vector,
the vector length is automatically increased.
2.
•
•
Any element not specifically replaced remains unchanged.
Elements beyond the existing length not replaced are set to 0.
Logical Indexing
The indexing vector length must be less than or equal to
the original vector length
It must contain logical values (true or false)
Access to the vector elements is by their relative position
in the logical vector
When reading elements, only the elements corresponding to
true index values are returned
When replacing elements, the elements corresponding to true
index values are replaced
Beware – logical vectors in Matlab echo in the Command
window as 1 or 0, but they are not the same thing.
Shortening an Array
Never actually necessary. It is advisable to
extract what you want by indexing rather than
removing what you don’t want.
Can lead to logic problems when changing the
length of a vector
Accomplished by assigning the empty vector ([])
to elements of a vector, or to complete rows or
columns of an array.
Operating on Vectors
Three techniques extend directly from operations
on scalar values:
■ Arithmetic operations
■ Logical operations
■ Applying library functions
Two techniques are unique to arrays in general,
and to vectors in particular:
■ Concatenation
■ Slicing (generalized indexing)
Arithmetic operations
In the Command window, enter the following:
>> A = [2 5 7 1 3];
>> A + 5
ans =
7 10 12 6 8
>> A .* 2
ans =
4 10 14 2 6
>> B = -1:1:3
B =
-1 0 1 2 3
Arithmetic operations (continued)
>> A .* B % element-by-element multiplication
ans =
-2 0 7 2 9
>> A * B % matrix multiplication!!
??? Error using ==> mtimes
Inner matrix dimensions must agree.
>> C = [1 2 3]
C =
1 2 3
>> A .* C % A and C must have the same length
??? Error using ==> times
Matrix dimensions must agree.
Logical operations
>> A = [2
>> B = [0
>> A >= 5
ans =
0 1 1 0 0
>> A >= B
ans =
1 0 1 0 1
>> C = [1
>> A > C
??? Error
5 7 1 3];
6 5 3 2];
2 3]
using ==> gt
Matrix dimensions must agree.
Logical operations (continued)
>> A = [true true false false];
>> B = [true false true false];
>> A & B
ans =
1 0 0 0
>> A | B
ans =
1 1 1 0
>> C = [1 0 0]; % NOT a logical vector
>> A(C) % yes, you can index logical vectors, but ...
??? Subscript indices must either be real positive
integers or logicals.
A Footnote: the find function
Continuing the code above:
>> C = find(B)
ans =
[1 3]
The find(...) function consumes a logical vector
and returns the numerical indices of the
elements of that vector that are true.
Applying library functions
All MATLAB functions accept vectors of numbers rather than single
values and return a vector of the same length.
Special Functions:
■ sum(v) and mean(v) consume a vector and return a number
■ min(v) and max(v) return two quantities: the minimum or
maximum value in a vector, plus the position in that vector
where that value occurred.
■ round(v), ceil(v), floor(v), and fix(v) remove the fractional
part of the numbers in a vector by conventional rounding, rounding up,
rounding down, and rounding toward zero, respectively.
Concatenation
MATLAB lets you construct a new vector by
concatenating other vectors:
A = [B C D ... X Y Z]
where the individual items in the brackets may be any
vector defined as a constant or variable, and the length
of A will be the sum of the lengths of the individual
vectors.
A = [1 2 3 42]
is a special case where all the component elements are
scalar quantities.
Slicing (generalized indexing)
A(4) actually creates an anonymous 1 × 1 index vector,
4, and then using it to extract the specified element from
the array A.
In general,
B(<rangeB>) = A(<rangeA>)
where <rangeA> and <rangeB> are both index vectors, A is an
existing array, and B can be an existing array, a new array, or
absent altogether (giving B the name ans). The values in B at the
indices in <rangeB> are assigned the values of A from <rangeA> .
Rules for Slicing
■ Either the dimensions of <rangeB> must be equal
to the dimensions of <rangeA> or <rangeA> must be
of size 1
■ If B did not exist before this statement was
implemented, it is zero filled where assignments
were not explicitly made
■ If B did exist before this statement, the values
not directly assigned in <rangeB> remain
unchanged
Representing Mathematical Vectors
An unfortunate clash of names
Vectors in mathematics can be represented by Matlab
vectors
The first, second and third values being the x, y and z
components
Matlab vector addition and subtraction work as expected.
Matlab magnitude and scaling works as expected.
Dot product is just the sum of A .* B
Cross product has a Matlab function
Engineering Example—Forces and
Moments
So given a pair of forces A
and B acting at a point P,
find:
The
resultant force, and
The moment of that resultant
about the origin
Vector Solution
clear
clc
PA = [0 1 1]
PB = [1 1 0]
P = [2 1 1]
M = [4 0 1]
% find the resultant of PA and PB
PC = PA + PB
% find the unit vector in the direction of PC
mag = sqrt(sum(PC.^2))
unit_vector = PC/mag
% find the moment of the force PC about M
% this is the cross product of MP and PC
MP = P - M
moment = cross( MP, PC )
MATLAB Arrays
A Transposed Array
Array Manipulation
We consider the following basic operations on
vectors:
Creating
an array
Extracting data from an array by indexing
Shortening an array
Mathematical and logical operations on arrays
Creating an Array – Constant
Values
Entering the values directly, e.g.
A = [2, 5, 7; 1, 3, 42] the semicolon identifies
the next row, as would a new line in the
command
Using the functions zeros( rows, cols), ones(rows,
cols), rand(rows, cols) and randn(rows, cols) to
create vectors filled with 0, 1, or random values
between 0 and 1
Indexing an Array
The process of extracting values from an array,
or inserting values into an array
Syntax:
A(row,
col) returns the element(s) at the location(s)
specified by the array row and column indices.
A(row, col) = value replaces the elements at the
location(s) specified by the array row and column
indices.
The indexing row and column vectors may
contain either numerical or logical values
Numerical Indexing
The indexing vectors may be of any length
It should contain integer (non-fractional)
numbers
The values in the indexing vectors are
constrained by the following rules:
For
reading elements, all index values must be
1 <= element <= length(array dimension)
For
replacing elements, all index values must be
1 <= element
Replacement Rules
Either:
1.
•
•
All dimensions of the blocks on either side of the replacement
instruction must be equal, or
There must be a single element on the RHS of the
replacement
If you replace beyond the end of any dimension of the
existing array, the size in that dimension is
automatically increased.
2.
•
•
Any element not specifically replaced remains unchanged.
Elements beyond the existing dimension length not replaced
are set to 0.
Logical Indexing
The indexing vector length must be less than or
equal to the original array dimension
It must contain logical values (true or false)
Access to the array elements is by their relative
position in the logical vectors
When reading elements, only the elements
corresponding to true index values are returned
When replacing elements, the elements
corresponding to true index values are replaced
Operating on Arrays
Four techniques extend directly from operations on
vectors:
■ Arithmetic operations
■ Logical operations
■ Applying library functions
■ Slicing (generalized indexing)
The following deserves an additional word
because of the nature of arrays:
■ Concatenation
Array Concatenation
Array concatenation can be accomplished
horizontally or vertically:
R
= [A B C] succeeds as long as A, B and C have the
same number of rows; the columns in R will be the
sum of the columns in A, B and C.
R = [A; B; C] succeeds as long as A, B and C have
the same number of columns; the rows in R will be
the sum of the rows in A, B and C.
Reshaping Arrays
Arrays are actually stored in column order in
Matlab. So internally, a 2 × 3 array is stored as
a column vector: A(1,1)
A(2,1)
A(1,2)
A(2,2)
A(1,3)
A(2,3)
Any n × m array can be reshaped into any p × q
array as long as n*m = p*q using the reshape
function.
3.6 Engineering Example—Computing
Soil Volume
Consider the example where you are given the
depth of soil from a survey in the form of a
rectangular array of soil depth.
You are also given the footprint of the
foundations of a building to be built on that site
and the depth of the foundation.
Compute the volume of soil to be removed.
Survey Data
Building Footprint
Solution
clear
clc
% soil depth data for each square produced
% by the survey
dpth = [8 8 9 8 8 8 8 8 7 8 7 7 7 7 8 8 8 7
8 8 8 8 8 8 8 7 7 7 7 7 8 7 8 8 8 7
. . .
9 8 8 7 7 8 7 7 7 7 8 8 9 9 9 8 7 8];
% estimated proportion of each square that should
% be excavated
area = [1 1 1 1 1 1 1 1 1 1 .3 0 0 0 0 0 0 0
. . .
0 0 0 0 0 0 .4 .8 .9 1 1 1 1 1 1 1 1 .6];
square_volume = dpth .* area;
total_soil = sum(sum(square_volume))
4.1 Concept: Code Blocks
A code block is a collection of zero or more MATLAB instructions
identified for one of two reasons:
you wish to execute them only under certain circumstances, or
2. You wish to repeat them a certain number of times
1.
Some languages identify code blocks by enclosing them in braces ({.
. .}); others identify them by the level of indentation of the text.
MATLAB uses the occurrence of key command words in the text to
define the extent of code blocks:
if, switch, while, for, case, otherwise, else,
elseif, end
Code blocks are identified with blue coloring by the MATLAB text
editor. They are not part of the code block, but they serve both
as instructions on what to do with the code block, and
as delimiters that define the extent of the code block.
4.2 Conditional Execution in
General
Basic conditional execution
requires two things:
A logical
expression, and
A code block
If the expression is true, the code
block is executed.
Otherwise, execution is resumed
at the instruction following the
code block
Compound conditionals
By introducing elseif and else, we allow for the possibility
of either conditional or unconditional execution when a
test returns false as illustrated.
4.3 if Statements
The general template for if statements is:
if <logical expression 1>
<code block 1>
elseif <logical expression 2>
<code block 2>
.
.
.
elseif <logical expression n>
<code block n>
else
<default code block>
end
General Observations
A logical expression is any statement that
returns a logical result.
If that result is a logical vector, v, the if statement
behaves as:
if all(v)
While indentation has no effect on the logical
flow, it helps to clarify the logical flow. The
MATLAB editor automatically creates suitable
indentation as you type.
4.4 switch Statements
The template for a switch statement is:
switch <parameter>
case <case specification 1>
<code block 1>
case <case specification 2>
<code block 2>
.
.
case <case specification n>
<code block n>
otherwise
<default code block>
end
General Observations
The switch statement is looking for the
parameter to have an exact match to one of the
cases.
One case specification may have multiple
values enclosed in braces( {…}).
The default case catches any values of the
parameter other than the specified cases.
The default case should trap bad parameter
values.
4.5 Iteration in General
Iteration allows controlled repetition of a code block.
Control statements at the beginning of the code block
specify the manner and extent of the repetition:
The for loop is designed to repeat its code block a fixed number
of times and largely automates the process of managing the
iteration.
The while loop is more flexible in character. Its code block can
be repeated a variable number of times. It is much more of a
“do-it-yourself” iteration kit.
4.6 for Loops
The template for a for loop is:
for <variable> = <vector>
<code block>
end
The for loop automatically sets
the value of the variable to each
element of the vector in turn and
executes the code block with that
value.
4.7 while Loops
The code block will be repeated
as long as the logical expression
returns true.
The while loop template is:
<initialization>
while <logical expression>
<code block>
% must make some changes
% to enable the loop to terminate
end
4.8 Engineering Example—
Computing Liquid Levels
Give a tank as shown, how do
you calculate the volume of
liquid? The answer of course is “it
depends on h.”
If h <= r, do one calculation;
otherwise if h < (H-r) do a second;
Otherwise if h <= H, do a third;
Otherwise there is an error!
The Solution
if h < r
v = (1/3)*pi*h.^2.*(3*r-h);
elseif h < H-r
v = (2/3)*pi*r^3 + pi*r^2*(h-r);
elseif h <= H
v = (4/3)*pi*r^3 + pi*r^2*(H-2*r) ...
- (1/3)*pi*(H-h)^2*(3*r-H+h);
else
disp(‘liquid level too high’)
continue
end
fprintf( ...
'rad %0.2f ht %0.2f level %0.2f vol %0.2f\n', ...
r, H, h, v);
5.1 Concept: Abstraction
Procedural abstraction permits a code block that solves a
particular sub-problem to be packaged and applied to
different data inputs.
analogous to the concept of data abstraction where individual
data items are gathered to form a collection.
We have already used a number of built-in procedural
abstractions in the form of functions.
They allow us to apply a code block about which we know
nothing to data that we provide.
5.1 Concept: Encapsulation
Encapsulation is the concept of putting a wrapper
around a collection that you wish to protect from
outside influence.
Functions encapsulate the code they contain in
two ways:
the
variables declared within the function are not
visible from elsewhere, and
the function’s ability to change the values of variables
(otherwise known as causing side effects) is restricted
to its own code body.
5.2 Black Box View of a Function
are the formal parameters – the names given to the
incoming data inside the function.
<item 1...n> are the actual parameters provided to the function by
its caller.
<param 1...n>
They may have names different from the formal parameter names
They are correlated to the formal parameter names by their position
5.3 MATLAB Implementation
The template for defining a function is:
function <return info> <function name> (<parameters>)
<documentation>
<code body> % must return the results
The function code must be stored in a file whose
name is the name of the function.
Functions return data to the caller by assigning
values to the return variable(s)
MATLAB throws an error if a function does not
make assignments to all the return variables.
5.4 Engineering Example—Measuring a
Solid Object
We need to compute the volume and wetted area of this
object.
This requires one function that computes the volume and
wetted area of a cylinder
We have a range of disk heights for which we require
this information.
Solution
The function stored in cylinder.m
function [area, volume] =
% function to compute the
% usage: [area, volume] =
base = pi .* radius.^2;
volume = base .* height;
area = 2 * pi * radius .*
cylinder(height, radius)
area and volume of a cylinder
cylinder(height, radius)
height + 2 * base;
The test script
clear
clc
h = 1:5; % set a range of disk thicknesses
R = 25;
r = 3;
[Area Vol] = cylinder(h, R) % dimensions of large disk
[area vol] = cylinder(h, r) % dimensions of the hole
% compute remaining volume
Vol = Vol - 8*vol
Area = Area + 8*(area - 2*2*pi*r.^2)
Background
Two relationships between characters and numbers
1. Individual characters have an internal numerical
representation: The shapes we see in windows are created
by a character generator.
2. Strings of characters represent numerical values:
Numerical values are stored in MATLAB in a special, internal
representation for efficient numerical computation.
Whenever we need to see the value of a number, the internal
representation is converted into a character string representing its
value in a form we can read.
Similarly, to enter numerical values, we create a character string and
have it converted to the internal representation
Concept: Mapping
Mapping defines a relationship between two entities. e.g.
the idea that the function f(x) = x2 defines the mapping
between the value of x and the value
of f(x).
We will apply that concept to the process of translating a
character (like ‘A’) from its graphical form to a numerical
internal code. Character mapping allows each individual
graphic character to be uniquely represented by a
numerical value.
Concept: Casting
Casting is the process of changing the way a language views a piece
of data without actually changing the data value.
Under normal circumstances, a language like MATLAB automatically
presents a set of data in the “right” form.
However, there are times when we wish to force the language to treat a
data item in a specific way; we might want to view the underlying
numerical representation as a number rather that as a character, in
which case we have to cast the variable containing the character to a
numerical data type.
MATLAB implements casting as a function with the name of the data
type expected. In essence, these functions implement the mapping
from one character representation to another.
MATLAB Implementation of Casting
>> uint8('A') % uint8 is an integer data type
% with values 0 - 255
ans = 65
>> char(100) % char is the character class
ans = d
>> char([97 98 99 100 101])
ans = abcde
>> double('fred')
ans = 102 114 101 100
>> fred = 'Fred'
fred = Fred
>> next = fred + 1
next = 71 115 102 101
>> a = uint8(fred)
a = 70 114 101 100
>> name = char(a + 1)
name = Gsfe
String Operations
Since strings are internally represented as
vectors of numbers, all the normal vector
operations apply:
Arithmetic
and logical operations
Concatenation
Shortening
Indexing
Slicing
Conversion from Numbers to Strings
Use the following built-in MATLAB functions for a simple
conversion of a single number, x, to its string
representation:
int2str(x) if you want it displayed as an integer value
num2str(x, n) to see the decimal parts; the parameter n
represents the number of decimal places required—if not
specified, its default value is 3
sprintf(…) provides finer-grained format control
Its first parameter is a format control string that defines how
the resulting string should be formatted.
A variable number of value parameters follow the format string,
providing data items as necessary to satisfy the formatting.
Format Control in sprintf(…)
Characters in the format string are copied to the result string.
Special behavior is introduced by two special characters:
'%' introduces a conversion specification:
%d (integer),
%f (real),
%g (general),
%c (character) and
%s(string).
Each conversion requires a value parameter in the sprintf(…) call.
A number may be placed immediately after the % character to specify the
minimum number of characters in the conversion. The %f and %g
conversions can include '.n' to indicate the number of decimal places
required.
'\' introduces escape characters for format control. The most common:
\n (new line) and
\t (tab).
Conversion from Strings to
Numbers:input(…)
When possible, allow input(...) to do the conversion.
The function input(str) presents the string parameter to the user in the
Command window and waits for the user to type some characters and
the Enter key, all of which are echoed in the Command window. Then
it converts the input string according to the following rules. If the string
begins with:
a numerical character, MATLAB converts the string to a number
An alpabetic character, MATLAB constructs a variable name and looks
for its definition
an open bracket, '[', an array is constructed
the single quote character, MATLAB creates a string
If a format error occurs, MATLAB repeats the prompt.
This behavior can be modified if 's' is provided as the second
parameter to input(…), in which case the complete input character
sequence is saved as a string regardless of content.
Conversion from Strings to Numbers:
sscanf
In its simplest form, CV = sscanf(str, fmt) scans the string str and converts
each data item according to the conversion specifications in the format string
fmt.
Each item discovered in str produces a new row on the result array, CV, a
column vector.
If you convert strings this way, each character in the string becomes a
separate numerical result in the output vector.
MATLAB allows you to substitute thecharacter '*' for the conversion size
parameter to suppress any strings in the input string. For example:
str = 'are 4.700 1.321 4.800000'
B = sscanf( str, '%*s %f %f %f')
B =
4.7000
1.3210
4.8000
Miscellaneous Character String
Operations
disp(…) shows the contents of a variable in the
Command Window
fprintf(…) formats data for the Command Window exactly
as sprintf does to produce a string.
String Comparison
Strings may be compared as vectors; however, they must then obey vector
comparison rules
strcmp(…) and strcmpi(…) compare strings of any length.
>> 'abcd' == 'abcd'
ans = 1 1 1 1
>> 'abcd' == 'abcde'
??? Error using ==> eq
Array dimensions must match for binary array op.
>> strcmp('abcd', 'abcde')
ans = 0
>> strcmp('abcd', 'abcd')
ans = 1
>> 'abc' == 'a'
ans = 1 0 0
>> strcmpi('ABcd', 'abcd')
ans = 1
6.5 Arrays of Strings
Character string arrays can be constructed by
either of the following:
As
a vertical vector of strings, all of which must be the
same length
By using a special version of the char(…) cast
function that accepts a variable number of strings with
different lengths, pads them with blanks to make all
rows the same length, and stores them in an array of
characters
Engineering Example—Encryption
Encryption is the process of somehow changing a
message in the form of a string of characters so that it
can be understood at its destination, but
is unintelligible to a third party who does not have access to the
original encryption scheme.
Early encryption schemes involved shifting characters in
the alphabet either by a constant amount or according to
a one-time message pad.
However, these schemes are relatively easily cracked by
examining letter frequencies.
Our Approach
We will use a scheme that makes use of the MATLAB
random number generator to create a random character
shift unique to each occurrence of characters in a
message, so that letter frequency cannot be used to
determine the encryption technique.
At the destination, as long as the random number
generator is seeded with an agreed value, the message
can be reconstructed by shifting back the message
characters.
A few minor modifications wrap the characters on the
alphabet to remain within the set of printable letters.
The Solution - encryption
%%% encryption section
% seed the random generator to a known state
rand('state', 123456)
loch = 33;
hich = 126;
range = hich+1-loch;
rn = floor( range * rand(1, length(txt) ) );
change = (txt>=loch) & (txt<=hich);
enc = txt;
enc(change) = enc(change) + rn(change);
enc(enc > hich) = enc(enc > hich) - range;
disp('encrypted text')
encrypt = char(enc);
The Solution - decryption
%% good decryption
% seed the random generator to the same state
rand('state', 123456);
rn = floor( range * rand(1, length(txt) ) );
change = (encrypt>=loch) & (encrypt <= hich)
dec = encrypt;
dec(change) = dec(change) - rn(change) + range;
dec(dec > hich) = dec(dec > hich) - range;
disp('good decrypt');
decrypt = char(dec)
String Functions
num2str(a,n) Converts a number to its numerical
representation with n decimal places
disp(...) Displays matrix or text
fprintf(...) Prints formatted information
input(...) Prompts the user to enter a value
sscanf(...) Formats input conversion
sprintf(...) Formats a string result
strcmp(s1, s2) Compares two strings; returns true if equal
strcmpi(s1, s2) Compares two strings without regard to
case; returns true if equal
11.1 Plotting in General
The fundamental container for plotting is a
MATLAB figure
Simple plot of x versus y: plot(x, y)
Plot enhancements
axis,
colormap, grid on, hold on, legend, shading, text,
title, view, xlabel, ylabel, zlabel
Use subplot(r, c, n) for multiple plots on one
figure
1-116
Plot Enhancements
1.
2.
3.
4.
5.
clf
x = -2*pi:.05:2*pi;
subplot(2,3,1)
plot(x, sin(x))
title('1 - sin(x)');
6. subplot(2,3,2)
7. plot(x, cos(x))
8. title('2 - cos(x)');
9. subplot(2,3,3)
10. plot(x, tan(x))
11. title('3 - tan(x)');
12. subplot(2,3,4)
13. plot(x, x.^2)
14. title('4 - x^2');
15. subplot(2,3,5)
16. plot(x, sqrt(x))
17. title('5 - sqrt(x)');
18. subplot(2,3,6)
19. plot(x, exp(x))
20. title('4 - e^x');
1-117
11.2 2-D Plotting
Basic function for 2-D plots: plot(x, y, str)
x
and y are vectors of the same length
str specifies optional line color & style control
Plot options
subplot,
axis, hold on, title
Parametric plotting
Allows
the variables on each axis to be dependent on
a separate, independent variable
1-118
Multiple 2-D Plots
1-119
Special 2-D Effects
% Code for the first three plots
1. clear
2. clc
3. close all
4. x = linspace(0, 2*pi);
5. subplot(2, 3, 1)
6. plot(x, sin(x))
7. axis([0 2*pi -0.5 0.5])
8. title('Changing Data Range on an
Axis')
9. subplot(2, 3, 2)
10. plot(x, sin(x))
11. hold on
12. plot(x, cos(x))
13. axis tight
14. title('Multiple Plots with hold on')
15.
16.
17.
18.
19.
20.
subplot(2, 3, 3)
plot(x, sin(x), 'ó')
hold on
plot(x, cos(x), 'r:')
axis tight
title('Multiple Plots with hold on')
1-120
Transforming a Circle to an Airfoil
1-121
11.3 3-D Plotting
2-D plots in MATLAB are actually 3-D plots (select
the Rotate 3D icon on the tool bar)
Linear 3-D Plots
Extend
2-D plots by adding a set of z values
Use plot3(x, y, z, str)
Linear Parametric 3-D Plots
Allow
variables on each axis to be dependent on a
separate, independent variable
Other plot capabilities
bar3(x, y), barh3(x, y), pie3(y)
1-122
3-D View of a 2-D Plot
1-123
3-D Line plots
1-124
Parametric Line Plots
1-125
11.4 Surface Plots
Production of images based on mapping a 2-D
surface create a plaid
Basic capabilities
meshgrid(x,
y): compute mappings for the 3-D
coordinates
mesh(xx, yy, zz): plots the surface as white facets
outlined by colored lines
surf(xx, yy, zz): plots the surface as colored facets
outlined by black lines
1-126
Designing a Cube Surface plot
1-127
Cube Surfaces
1-128
Simple Surface Plot
1-129
Compound Surface Plot
1-130
Using External Illumination
1-131
Designing a Cylinder Plot
1-132
Cylinder Plot
1-133
Sphere Plot
1-134
Bodies of Rotation
Created by rotating a linear curve about a
specified axis
i.e.
Rotate z = f(x) about the x-axis
y
rotate z = f(x) about the x or z axes (not y)
= r cos(θ), z = r sin(θ)
Rotate z = f(x) about the z-axis
x
= r cos(θ), y = r sin(θ)
1-135
Rotating About the X Axis
1-136
Rotating About the Z Axis
1-137
Bodies of Rotation
1-138
Rotating Arbitrary Shapes
1-139
General Rotation Techniques
Rotating about an Arbitrary Axis
• Calculate the matrix that will place your
axis of rotation along the x-axis
• Transform x and z with that rotation
• Rotate the results about the x-axis
• Invert the transformation on the resulting
surface
1-140
A Solid Disk
1-141
A Klein Bottle
1-142
11.5 Engineering Example—Visualizing
Geographic Data
Two files of data
atlanta.txt:
presents streets of Atlanta
ttimes.txt: travel times between suburbs and city
Analyzing the Data
Determine
the file format
Discern the street map file content
Discern the travel time file content
1-143
Map of Atlanta
1-144
Multimedia CS2 in Java
Driving question:
“How did the
wildebeests
stampede in The
Lion King?”
Spring 2005: 31
students, 75%
female, 91%
success rate.
Connecting to the Wildebeests
It’s all about data structures
Syllabus
Introduction to Java and Media Computation
Manipulating
turtles, images, MIDI, sampled sounds.
Insertion and deletion (with shifting) of sampled
sounds (arrays).
Structuring Music
Goal: A structure
for flexible music composition
Put MIDI phrases into linked list nodes.
Use Weave and Repeat to create repeating motifs as found
in Western Music
At very end, create a two-branched list to start on trees.
Swan
Bells
Canon
Fur Elise
HW2: Create a collage, but must
use turtles
Syllabus (Continued)
Structuring Images
Using linearity in linked list to
represent ordering (e.g., left to right)
Using linearity in linked list to
represent layering (as in PowerPoint)
Mixing positioned and layered in one
structure, using abstract super
classes.
Structuring a scene in terms of
branches—introducing a scene graph
(first tree)
(We’ll see these slides as an
example later.)
Syllabus (Cont’d)
Structuring Sound
Collecting
sampled
sounds into linked
lists and trees, as
with images.
But all traversals are
recursive.
Use
different
traversals of same
tree to generate
different sounds.
Replace a sound inplace
Original
Scale the children
Scale the next
Syllabus (cont’d)
Generalizing lists and
trees
Create
an abstract class
“Linked List Node”
(LLNode) on top of the
sound and image class
hierarchies
Make all image and
sound examples work
the same
abstract LLNode
Knows next
Knows how to do
all basic list
operations
Syllabus (Cont’d)
JFrame
GUIs as trees
We
introduce construction
of a Swing frame as
construction of a tree.
Different layout managers
are then different
renderers of the same
tree.
JPanel
JPanel
JLabel “This is panel1!”
JButton
“Make a
picture”
JButton “Make
a sound”
Syllabus (cont’d)
Lists that Loop
Introduce
circular linked lists as a way of create
Mario-Brothers’ style cel animations.
Introduce trees that loop as a way of introducing
graphs.
gal1rightface.jpg
gal1right2.jpg
gal1rightface.jpg
gal1right1.jpg
Syllabus (cont’d)
Introducing Simulations
Introduce continuous and discrete event simulations, and Normal
and uniform probability distributions
We do wolves and deer,
disease propagation,
political influence.
Create a set of classes for simulation, then re-write our
simulations for those classes.
Writing results to a file for later analysis
Finally, Making the Wildebeests and Villagers
Mapping from positions of our turtles to an animation frame.
Creating an animation from a simulation.
HW7: Simulate European emigration to
America
Students are
required to try
several different
scenarios, aiming for
historical accuracy.
Counts of
Europeans,
Americans, and intransit per year are
written to a file for
graphing in Excel
Syllabus (cont’d)
Introduction to Discrete Event Simulations
Create
a discrete event simulation of trucks, factories,
salespeople, and markets.
Use turtles to create an animated display.
Now, the real focus is the simulation, and the
animation is just a mapping from the simulation.
Animation becomes yet another medium in which we can
review results, like data in an Excel spreadsheet, music, or
sound.
Example Slides
These come from the section on Structuring
Music then Structuring Images
Version 3:
SongNode and SongPhrase
SongNode instances will hold pieces (phrases)
from SongPhrase.
SongNode instances will be the nodes in the
linked list
Each
one will know its next.
Ordering will encode the order in the Part.
Each
one will get appended after the last.
Using SongNode and SongPhrase
Welcome to DrJava.
> import jm.JMC;
> SongNode node1 = new SongNode();
> node1.setPhrase(SongPhrase.riff1());
> SongNode node2 = new SongNode();
> node2.setPhrase(SongPhrase.riff2());
> SongNode node3 = new SongNode();
> node3.setPhrase(SongPhrase.riff1());
> node1.setNext(node2);
> node2.setNext(node3);
> node1.showFromMeOn(JMC.SAX);
All three SongNodes in one Part
How to think about it
node1
node2
myPhrase: riff1
myPhrase: riff2
next: node2
next: node3
node3
myPhrase: riff1
next: null
Declarations for SongNode
import jm.music.data.*;
import jm.JMC;
import jm.util.*;
import jm.music.tools.*;
public class SongNode {
/**
* the next SongNode in the list
SongNode’s know their
*/
Phrase and the next
private SongNode next;
node in the list
/**
* the Phrase containing the notes and durations associated with this node
*/
private Phrase myPhrase;
Constructor for SongNode
/**
* When we make a new element, the next part is empty,
and ours is a blank new part
*/
public SongNode(){
this.next = null;
this.myPhrase = new Phrase();
}
Setting the phrase
/**
* setPhrase takes a Phrase and makes it the one for this
node
* @param thisPhrase the phrase for this node
*/
public void setPhrase(Phrase thisPhrase){
this.myPhrase = thisPhrase;
}
Linked list methods
/**
* Creates a link between the current node and the input node
* @param nextOne the node to link to
*/
public void setNext(SongNode nextOne){
this.next = nextOne;
}
/**
* Provides public access to the next node.
* @return a SongNode instance (or null)
*/
public SongNode next(){
return this.next;
}
insertAfter
/**
* Insert the input SongNode AFTER this node,
* and make whatever node comes NEXT become the next of the input node.
* @param nextOne SongNode to insert after this one
*/
public void insertAfter(SongNode nextOne)
{
SongNode oldNext = this.next(); // Save its next
this.setNext(nextOne); // Insert the copy
nextOne.setNext(oldNext); // Make the copy point on to the rest
}
Using and tracing insertAfter()
> SongNode nodeA = new SongNode();
> SongNode nodeB = new SongNode();
> nodeA.setNext(nodeB);
> SongNode nodeC = new SongNode()
> nodeA.insertAfter(nodeC);
public void insertAfter(SongNode nextOne)
{
SongNode oldNext = this.next(); // Save
its next
this.setNext(nextOne); // Insert the copy
nextOne.setNext(oldNext); // Make the
copy point on to the rest
}
Traversing
the list
/**
* Collect all the notes from this node on
* in an part (then a score) and open it up for viewing.
* @param instrument MIDI instrument (program) to be used in playing this list
*/
public void showFromMeOn(int instrument){
// Make the Score that we'll assemble the elements into
// We'll set it up with a default time signature and tempo we like
// (Should probably make it possible to change these -- maybe with inputs?)
Score myScore = new Score("My Song");
myScore.setTimeSignature(3,4);
myScore.setTempo(120.0);
// Make the Part that we'll assemble things into
Part myPart = new Part(instrument);
// Make a new Phrase that will contain the notes from all the phrases
Phrase collector = new Phrase();
// Start from this element (this)
SongNode current = this;
// While we're not through...
while (current != null)
{
collector.addNoteList(current.getNotes());
// Now, move on to the next element
current = current.next();
};
// Now, construct the part and the score.
myPart.addPhrase(collector);
myScore.addPart(myPart);
// At the end, let's see it!
View.notate(myScore);
}
The Core of the Traversal
// Make a new Phrase that will contain the notes from all the phrases
Phrase collector = new Phrase();
// Start from this element (this)
SongNode current = this;
// While we're not through...
while (current != null)
{
collector.addNoteList(current.getNotes());
// Now, move on to the next element
current = current.next();
};
Then return what you collected
// Now, construct the part and the score.
myPart.addPhrase(collector);
myScore.addPart(myPart);
// At the end, let's see it!
View.notate(myScore);
}
getNotes() just pulls the notes back out
/**
* Accessor for the notes inside the node's phrase
* @return array of notes and durations inside the phrase
*/
private Note [] getNotes(){
return this.myPhrase.getNoteArray();
}
SongPhrase
SongPhrase is a collection of static methods.
We don’t ever need an instance of SongPhrase.
Instead, we use it to store methods that return
phrases.
It’s
not very object-oriented, but it’s useful here.
SongPhrase.riff1()
import jm.music.data.*;
import jm.JMC;
import jm.util.*;
import jm.music.tools.*;
public class SongPhrase {
//Little Riff1
static public Phrase riff1() {
double[] phrasedata =
{JMC.G3,JMC.EN,JMC.B3,JMC.EN,JMC.C4,JMC.EN,JMC.D4,JMC.EN};
Phrase myPhrase = new Phrase();
myPhrase.addNoteList(phrasedata);
return myPhrase;
SongPhrase.riff2()
//Little Riff2
static public Phrase riff2() {
double[] phrasedata =
{JMC.D4,JMC.EN,JMC.C4,JMC.EN,JMC.E4,JMC.EN,JMC.G4,JMC.
EN};
Phrase myPhrase = new Phrase();
myPhrase.addNoteList(phrasedata);
return myPhrase;
}
Computing a phrase
//Larger Riff1
static public Phrase pattern1() {
double[] riff1data =
{JMC.G3,JMC.EN,JMC.B3,JMC.EN,JMC.C4,JMC.EN,JMC.D4,JMC.EN};
double[] riff2data =
{JMC.D4,JMC.EN,JMC.C4,JMC.EN,JMC.E4,JMC.EN,JMC.G4,JMC.EN};
Phrase myPhrase = new Phrase();
// 3 of riff1, 1 of riff2, and repeat all of it 3 times
for (int counter1 = 1; counter1 <= 3; counter1++)
{for (int counter2 = 1; counter2 <= 3; counter2++)
myPhrase.addNoteList(riff1data);
myPhrase.addNoteList(riff2data);
};
return myPhrase;
}
As long as it’s a phrase…
The way that we use SongNote and
SongPhrase, any method that returns a phrase
is perfectly valid SongPhrase method.
10 Random Notes
(Could be less random…)
/*
* 10 random notes
**/
static public Phrase random() {
Phrase ranPhrase = new Phrase();
Note n = null;
for (int i=0; i < 10; i++) {
n = new Note((int) (128*Math.random()),0.1);
ranPhrase.addNote(n);
}
return ranPhrase;
}
10 Slightly Less Random Notes
/*
* 10 random notes above middle C
**/
static public Phrase randomAboveC() {
Phrase ranPhrase = new Phrase();
Note n = null;
for (int i=0; i < 10; i++) {
n = new Note((int) (60+(5*Math.random())),0.25);
ranPhrase.addNote(n);
}
return ranPhrase;
}
Going beyond connecting nodes
So far, we’ve just created nodes and connected
them up.
What else can we do?
Well, music is about repetition and interleaving
of themes.
Let’s
create those abilities for SongNodes.
Repeating a Phrase
Welcome to DrJava.
> SongNode node = new SongNode();
> node.setPhrase(SongPhrase.randomAboveC());
> SongNode node1 = new SongNode();
> node1.setPhrase(SongPhrase.riff1());
> node.repeatNext(node1,10);
> import jm.JMC;
> node.showFromMeOn(JMC.PIANO);
What it looks like
node
node1
node1
node1
…
Repeating
Note! What
happens to this’s
next? How
would you create
a looong repeat
chain of several
types of phrases
with this?
/**
* Repeat the input phrase for the number of times
specified.
* It always appends to the current node, NOT insert.
* @param nextOne node to be copied in to list
* @param count number of times to copy it in.
*/
public void repeatNext(SongNode nextOne,int count) {
SongNode current = this; // Start from here
SongNode copy; // Where we keep the current copy
for (int i=1; i <= count; i++)
{
copy = nextOne.copyNode(); // Make a copy
current.setNext(copy); // Set as next
current = copy; // Now append to copy
}
}
Here’s making a copy
/**
* copyNode returns a copy of this node
* @return another song node with the same notes
*/
public SongNode copyNode(){
SongNode returnMe = new SongNode();
returnMe.setPhrase(this.getPhrase());
return returnMe;
}
Step 1:
public void repeatNext(SongNode nextOne,int count) {
SongNode current = this; // Start from here
SongNode copy; // Where we keep the current copy
node
node1
phrase:
10
random
notes
phrase:
riff1()
next: null
next: null
current
nextOne
Step 2:
copy = nextOne.copyNode(); // Make a copy
node
node1
phrase:
10
random
notes
phrase:
riff1()
phrase:
riff1()
next: null
next: null
next: null
current
copy
nextOne
Step 3:
current.setNext(copy); // Set as next
node
node1
phrase:
10
random
notes
phrase:
riff1()
phrase:
riff1()
next: null
next: null
next:
current
copy
nextOne
Step 4:
current = copy; // Now append to copy
node
node1
phrase:
10
random
notes
phrase:
riff1()
phrase:
riff1()
next: null
next: null
next:
current
copy
nextOne
Step 5 & 6:
copy = nextOne.copyNode(); // Make a copy
current.setNext(copy); // Set as next
node
node1
phrase:
10
random
notes
phrase:
riff1()
phrase:
riff1()
phrase:
riff1()
next:
next: null
next: null
next:
current
copy
nextOne
Step 7 (and so on):
current = copy; // Now append to copy
node
node1
phrase:
10
random
notes
phrase:
riff1()
phrase:
riff1()
phrase:
riff1()
next:
next: null
next: null
next:
current
copy
nextOne
What happens if the node already
points to something?
Consider repeatNext and how it inserts:
It simply sets the next value.
What if the node already had a next?
repeatNext will erase whatever used to come
next.
How can we fix it?
repeatNextInserting
/**
* Repeat the input phrase for the number of times specified.
* But do an insertion, to save the rest of the list.
* @param nextOne node to be copied into the list
* @param count number of times to copy it in.
**/
public void repeatNextInserting(SongNode nextOne, int count){
SongNode current = this; // Start from here
SongNode copy; // Where we keep the current copy
for (int i=1; i <= count; i++)
{
copy = nextOne.copyNode(); // Make a copy
current.insertAfter(copy); // INSERT after current
current = copy; // Now append to copy
}
}
Weaving
/**
* Weave the input phrase count times every skipAmount nodes
* @param nextOne node to be copied into the list
* @param count how many times to copy
* @param skipAmount how many nodes to skip per weave
*/
public void weave(SongNode nextOne, int count, int skipAmount)
{
SongNode current = this; // Start from here
SongNode copy; // Where we keep the one to be weaved in
SongNode oldNext; // Need this to insert properly
int skipped; // Number skipped currently
for (int i=1; i <= count; i++)
{
copy = nextOne.copyNode(); // Make a copy
Should we
break before
the last
insert (when
we get to the
end) or
after?
//Skip skipAmount nodes
skipped = 1;
while ((current.next() != null) && (skipped < skipAmount))
{
current = current.next();
skipped++;
};
oldNext = current.next(); // Save its next
current.insertAfter(copy); // Insert the copy after this one
current = oldNext; // Continue on with the rest
if (current.next() == null) // Did we actually get to the end early?
break; // Leave the loop
}
}
Creating a node to weave
> SongNode node2 = new SongNode();
> node2.setPhrase(SongPhrase.riff2());
> node2.showFromMeOn(JMC.PIANO);
Doing a weave
> node.weave(node2,4,2);
> node.showFromMeOn(JMC.PIANO);
Weave Results
Before:
After
Walking the Weave
public void weave(SongNode nextOne, int count, int
skipAmount)
{
SongNode current = this; // Start from here
SongNode copy; // Where we keep the one to be weaved in
SongNode oldNext; // Need this to insert properly
int skipped; // Number skipped currently
Skip forward
for (int i=1; i <= count; i++)
{
copy = nextOne.copyNode(); // Make a copy
//Skip skipAmount nodes
skipped = 1;
while ((current.next() != null) && (skipped < skipAmount))
{
current = current.next();
skipped++;
};
Then do an insert
if (current.next() == null) // Did we actually get to the end early?
break; // Leave the loop
oldNext = current.next(); // Save its next
current.insertAfter(copy); // Insert the copy after this one
current = oldNext; // Continue on with the rest
}
Building a Scene
Computer graphics professionals work at two
levels:
They
define individual characters and effects on
characters in terms of pixels.
But then most of their work is in terms of the scene:
Combinations of images (characters, effects on
characters).
To describe scenes, they often use linked lists
and trees in order to assemble the pieces.
Use an array?
> Picture [] myarray = new Picture[5];
> myarray[0]=new Picture(FileChooser.getMediaPath("katie.jpg"));
> myarray[1]=new Picture(FileChooser.getMediaPath("barbara.jpg"));
> myarray[2]=new Picture(FileChooser.getMediaPath("flower1.jpg"));
> myarray[3]=new Picture(FileChooser.getMediaPath("flower2.jpg"));
> myarray[4]=new Picture(FileChooser.getMediaPath("butterfly.jpg"));
> Picture background = new Picture(400,400)
> for (int i = 0; i < 5; i++)
{myarray[i].scale(0.5).compose(background,i*10,i*10);}
> background.show();
Yeah, we could. But:
• Inflexible
• Hard to insert, delete.
Using a linked list
Okay, so we’ll use a linked list.
But what should the ordering represent?
Version
The order that things get drawn left-to-right.
Version
1: Linearity
2: Layering
The order that things get drawn bottom-to-top
Version 1:
PositionedSceneElement
> FileChooser.setMediaPath("D:/cs1316/MediaSources/");
> PositionedSceneElement tree1 = new PositionedSceneElement(new
Picture(FileChooser.getMediaPath("tree-blue.jpg")));
> PositionedSceneElement tree2 = new PositionedSceneElement(new
Picture(FileChooser.getMediaPath("tree-blue.jpg")));
> PositionedSceneElement tree3 = new PositionedSceneElement(new
Picture(FileChooser.getMediaPath("tree-blue.jpg")));
> PositionedSceneElement doggy = new PositionedSceneElement(new
Picture(FileChooser.getMediaPath("dog-blue.jpg")));
> PositionedSceneElement house = new PositionedSceneElement(new
Picture(FileChooser.getMediaPath("house-blue.jpg")));
> Picture bg = new Picture(FileChooser.getMediaPath("jungle.jpg"));
> tree1.setNext(tree2); tree2.setNext(tree3); tree3.setNext(doggy);
doggy.setNext(house);
> tree1.drawFromMeOn(bg);
> bg.show();
In this example, using
chromakey to compose..just
for the fun of it.
What this looks like:
Slightly different ordering:
Put the doggy between tree2 and tree3
> tree3.setNext(house); tree2.setNext(doggy);
doggy.setNext(tree3);
> bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
> tree1.drawFromMeOn(bg);
> bg.show();
Yes, we can put
multiple
statements in
one line.
Slightly different picture
PositionedSceneElement
public class PositionedSceneElement {
/**
* the picture that this element holds
**/
private Picture myPic;
/**
* the next element in the list
**/
private PositionedSceneElement next;
Pretty darn
similar to our
music linked lists!
Constructor
/**
* Make a new element with a picture as input,
and
* next as null.
* @param heldPic Picture for element to hold
**/
public PositionedSceneElement(Picture heldPic){
myPic = heldPic;
next = null;
}
Linked list methods
/**
* Methods to set and get next elements
* @param nextOne next element in list
**/
public void setNext(PositionedSceneElement nextOne){
this.next = nextOne;
}
public PositionedSceneElement getNext(){
return this.next;
}
Again, darn
similar!
Traverse
the list
Traversing the
list in order to
draw the scene
is called
rendering the
scene: Realizing
the picture
described by the
data structure.
/**
* Method to draw from this node on in the list, using
bluescreen.
* Each new element has it's lower-left corner at the lowerright
* of the previous node. Starts drawing from left-bottom
* @param bg Picture to draw drawing on
**/
public void drawFromMeOn(Picture bg) {
PositionedSceneElement current;
int currentX=0, currentY = bg.getHeight()-1;
current = this;
while (current != null)
{
current.drawMeOn(bg,currentX, currentY);
currentX = currentX + current.getPicture().getWidth();
current = current.getNext();
}
}
Core of the Traversal
current = this;
while (current != null)
{
//Treat the next two lines as “blah blah blah”
current.drawMeOn(bg,currentX, currentY);
currentX = currentX +
current.getPicture().getWidth();
current = current.getNext();
}
Generalizing
Reconsider these lines:
> tree3.setNext(house);
tree2.setNext(doggy);
doggy.setNext(tree3);
This is actually a general case of:
Removing
the doggy from the list
Inserting it after tree2
Removing the doggy
> tree1.setNext(tree2);
tree2.setNext(tree3);
tree3.setNext(doggy);
doggy.setNext(house);
> tree1.remove(doggy);
> tree1.drawFromMeOn(bg);
Putting the mutt back
> bg = new
Picture(FileChooser.getMe
diaPath("jungle.jpg"));
> tree1.insertAfter(doggy);
> tree1.drawFromMeOn(bg);
Removing an
element
from the list
/** Method to remove node from list, fixing links
appropriately.
* @param node element to remove from list.
**/
public void remove(PositionedSceneElement node){
if (node==this)
{
System.out.println("I can't remove the first node
from the list.");
return;
};
PositionedSceneElement current = this;
// While there are more nodes to consider
while (current.getNext() != null)
{
if (current.getNext() == node){
// Simply make node's next be this next
current.setNext(node.getNext());
// Make this node point to nothing
node.setNext(null);
return;
}
current = current.getNext();
}
}
insertAfter
Think about what’s
involved in creating
insertBefore()…
/**
* Insert the input node after this
node.
* @param node element to insert
after this.
**/
public void
insertAfter(PositionedSceneElem
ent node){
// Save what "this" currently
points at
PositionedSceneElement oldNext
= this.getNext();
this.setNext(node);
node.setNext(oldNext);
}
Animation = (Changing a structure
+ rendering) * n
We can use what we just did to create
animation.
Rather than think about animation as “a
series of frames,”
Think about it as:
Repeatedly:
Change a data structure
Render (draw while traversing) the data structure
to create a frame
AnimatedPositionedScene
public class AnimatedPositionedScene {
/**
* A FrameSequence for storing the frames
**/
FrameSequence frames;
/**
* We'll need to keep track
* of the elements of the scene
**/
PositionedSceneElement tree1, tree2, tree3, house, doggy, doggyflip;
public void setUp(){
frames = new FrameSequence("D:/Temp/");
Setting up
the animation
FileChooser.setMediaPath("D:/cs1316/mediasources
/");
Picture p = null; // Use this to fill elements
p = new Picture(FileChooser.getMediaPath("treeblue.jpg"));
tree1 = new PositionedSceneElement(p);
p = new Picture(FileChooser.getMediaPath("treeblue.jpg"));
tree2 = new PositionedSceneElement(p);
p = new Picture(FileChooser.getMediaPath("treeblue.jpg"));
tree3 = new PositionedSceneElement(p);
p = new Picture(FileChooser.getMediaPath("houseblue.jpg"));
house = new PositionedSceneElement(p);
p = new Picture(FileChooser.getMediaPath("dogblue.jpg"));
doggy = new PositionedSceneElement(p);
doggyflip = new PositionedSceneElement(p.flip());
}
Render the first frame
public void make(){
frames.show();
// First frame
Picture bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.setNext(doggy); doggy.setNext(tree2);
tree2.setNext(tree3);
tree3.setNext(house);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
Render the doggy moving right
// Dog moving right
bg = new Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggy);
tree2.insertAfter(doggy);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
bg = new Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggy);
tree3.insertAfter(doggy);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
bg = new Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggy);
house.insertAfter(doggy);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
Moving left
//Dog moving left
bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggy);
house.insertAfter(doggyflip);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggyflip);
tree3.insertAfter(doggyflip);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggyflip);
tree2.insertAfter(doggyflip);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
bg = new
Picture(FileChooser.getMediaPath("jungle.jpg"));
tree1.remove(doggyflip);
tree1.insertAfter(doggyflip);
tree1.drawFromMeOn(bg);
frames.addFrame(bg);
}
Results
Version 2: Layering
> Picture bg = new Picture(400,400);
> LayeredSceneElement tree1 = new LayeredSceneElement(
new Picture(FileChooser.getMediaPath("tree-blue.jpg")),10,10);
> LayeredSceneElement tree2 = new LayeredSceneElement(
new Picture(FileChooser.getMediaPath("tree-blue.jpg")),100,10);
> LayeredSceneElement tree3 = new LayeredSceneElement(
new Picture(FileChooser.getMediaPath("tree-blue.jpg")),200,100);
> LayeredSceneElement house = new LayeredSceneElement(
new Picture(FileChooser.getMediaPath("house-blue.jpg")),175,175);
> LayeredSceneElement doggy = new LayeredSceneElement(
new Picture(FileChooser.getMediaPath("dog-blue.jpg")),150,325);
> tree1.setNext(tree2); tree2.setNext(tree3); tree3.setNext(doggy);
doggy.setNext(house);
> tree1.drawFromMeOn(bg);
> bg.show();
First version of Layered Scene
Reordering the layering
> house.setNext(doggy); doggy.setNext(tree3);
tree3.setNext(tree2); tree2.setNext(tree1);
> tree1.setNext(null);
> bg = new Picture(400,400);
Basically, we’re
> house.drawFromMeOn(bg); reversing the list
> bg.show();
Reordered (relayered) scene
Think about
what’s
involved in
creating a
method to
reverse() a
list…
What’s the difference?
If we were in PowerPoint or Visio, you’d say that
we changed the layering.
“Bring
to front”
“Send to back”
“Bring forward”
“Send backward”
These commands are
actually changing the
ordering of the layers in the
list of things to be redrawn.
• Change the ordering in the
list.
• Render the scene
• Now it’s a different layering!
Traversing
/**
* Method to draw from this node on in the list, using
bluescreen.
* Each new element has it's lower-left corner at the
lower-right
* of the previous node. Starts drawing from leftbottom
* @param bg Picture to draw drawing on
**/
public void drawFromMeOn(Picture bg) {
LayeredSceneElement current;
current = this;
while (current != null)
{
current.drawMeOn(bg);
current = current.getNext();
}
}
/**
* Method to draw from this picture, using bluescreen.
* @param bg Picture to draw drawing on
**/
private void drawMeOn(Picture bg) {
this.getPicture().bluescreen(bg,x,y);
}
Linked list traversals are all the same
current = this;
while (current != null)
{
current.drawMeOn(bg);
current = current.getNext();
}
New Version: Trees for defining
scenes
Not everything in a scene is a single list.
Is it the responsibility of the elements to know about
layering and position?
Think about a pack of fierce doggies, er, wolves attacking the
quiet village in the forest.
Real scenes cluster.
Is that the right place to put that know how?
How do we structure operations to perform to sets of
nodes?
For example, moving a set of them at once?
The Attack of the Nasty Wolvies
Closer…
Then the Hero Appears!
And the Wolvies retreat
What’s underlying this
This scene is described by a tree
Each
picture is a BlueScreenNode in this tree.
Groups of pictures are organized in HBranch or
VBranch (Horizontal or Vertical branches)
The root of the tree is just a Branch.
The branches are positioned using a MoveBranch.
Labeling the Pieces
Branch (root)
MoveBranch to
(10,50)
VBranch with
BlueScreenNode
wolves
MoveBranch to
(10,400)
MoveBranch to
(300,450)
HBranch with 3
BSN houses and a
HBranch with BSN
trees
VBranch with 3
BSN houses
It’s a Tree
Branch (root)
MoveBranch to
(10,50)
MoveBranch to
(10,400)
MoveBranch to
(300,450)
HBranch with 3
BSN houses and a
VBranch with
BlueScreenNode
wolves
HBranch with BSN
trees
VBranch with 3
BSN houses
The Class Structure
DrawableNode knows only next, but knows
how to do everything that our picture linked lists
do (insertAfter, remove, last, drawOn(picture)).
Everything
else is a subclass of that.
PictNode knows it’s Picture myPict and knows
how to drawWith(turtle) (by dropping a picture)
BlueScreenNode doesn’t know new from
PictNode but knows how to drawWith(turtle) by
using bluescreen.
Branch Class Structure
Branch knows its children—a linked list of other
nodes to draw. It knows how to drawWith by:
(1)
telling all its children to draw.
(2) then telling all its children to draw.
A HBranch draws its children by spacing them
out horizontally.
A VBranch draws its children by spacing them
out vertically.
The Class Structure Diagram
Note: This is not
the same as the
scene (object)
structure!
DrawableNode
Knows: next
PictNode
Branch
Knows: myPict
Knows: children
Knows how to
drawWith
HBranch
VBranch
Knows how
to drawWith
horizontally
Knows how to
drawWith
vertically
BlueScreenNode
Knows how to
drawWith as
bluescreen
Funding Sources
• National Science Foundation
• Georgia Tech's College of Computing
• Georgia’s Department of Education
• GVU Center,
• Al West Fund
• President's Undergraduate Research Award
• Toyota Foundation