| Overview | Schedule | Resources | Assignments | Home |
By working through the steps in this handout, you will develop a HasCl program to draw a picture made up of many overlapping squares of different sizes and colors.
Shape type has several other constructors):
data Shape = Poly([(Num, Num)], Color, Color) | Over(Shape, Shape) | Blank;This says that a
Shape value is either a
polygon, or the combination of one
Shape over another, or nothing at all. A
polygon needs three parameters--the value Poly(ps, c1, c2)
describes a polygon whose vertices are given by the list ps,
with border color c1 and interior color c2.
Each point in the list of vertices is a pair (x, y) :: (Num, Num).
The coordinate system of the graphics window (which pops up when you
evaluate an expression of type Shape) initially has the point
(0, 0) at the upper-left corner and (200, 200) at
the lower-right, although this will change as you resize the window,
pan around (click and drag the mouse), or zoom in and out (if you have
a mouse with a scroll wheel). A color is specified as a value of
the following data type, which is also defined in the
graphics module:
data Color = RGBA(Num, Num, Num, Num);The value
RGBA(r, g, b, a) specifies a color with
red, green, blue, and "alpha" components given by the numbers r, g, b, and a respectively, where each
component ranges from 0 (completely absent) to 255 (full
strength). The alpha level determines the transparency of the color, from
0 for completely transparent to 255 for completely opaque. The graphics module also defines some useful
constants of type Color; for example,
red is the value RGBA(255, 0, 0, 255)
(look in the graphics module function browser in Funnie to see what other
colors are defined). There is also a function
RGB :: (Num, Num, Num) -> Color which makes it easier
to create an opaque color given just the red, green, and blue components.
import std.graphics;
square(x, y, r, c) = Poly([(x-r, y-r), (x+r, y-r), (x+r, y+r), (x-r, y+r)], c, c);
The import declaration is similar to the one in Java--it tells
the compiler that we want to use the definitions from another module (by default,
only definitions in the current module and std.base are available).
This function will create a polygon with four vertices, giving us a square with
center (x, y) and half-width r (like the radius of a
circle--for our purposes, this will be a convenient way to specify a square).
Both the border and the interior will be of color c.
square(50, 40, 15, RGB(0, 255, 0)). If you
type this in, the system should pop-up a graphics window
containing the square.
For testing, it will be convenient to define some sample squares. Add each of the following to the source in your module window and compile:
redGiant = square(70, 80, 50, RGB(255, 0, 0)); whiteDwarf = square(20, 50, 10, RGB(255, 255, 255)); purpleMedium = square(60, 40, 30, RGB(128, 0, 128));Now you can easily draw a square by entering its name, e.g.,
redGiant, in
the module's expression window. However, this only lets you
draw one square at a time. To combine several squares in
one picture, we need the Over constructor of
the Shape data type, as follows:
Over(redGiant, purpleMedium). Notice how the
squares are combined, and see what happens if you reverse
the order of the squares. For convenience, you may also use
the +++ operator to put one Shape over
another: try whiteDwarf +++ purpleMedium +++ redGiant.
Shape. As usual when
working with a list of things, we will define the function
by recursion. Here is the base case, which uses the special
value Blank to produce a blank picture:
showShapeList([ ]) = Blank;The recursive case will have the following form:
showShapeList([s : ss]) = ;When this pattern matches,
s will be the first
shape on the list, and ss will be a list of
the remaining shapes. Write an appropriate right-hand side
for this case of the function. The shape s is
already a Shape; you will need to use
showShapeList to produce another
Shape from ss. These two
Shapes will then need to be combined into
one with Over. When you have defined the
function, try it out with showShapeList([redGiant,
whiteDwarf]).
diagonalSquares(x, y, r, c, 0) = [ ];
diagonalSquares(x, y, r, c, n) = [square(x, y, r, c) :
diagonalSquares(x+r, y+r, r, c, n-1)];
After entering this function, evaluate
showShapeList(diagonalSquares(30, 30, 10, blue,
9)). The cases for this function mean that
diagonalSquares(x, y, r, c, n) will produce
a list of n squares (because the list is empty
when n is 0, and it gets one
extra element for each recursive call as n
counts down to 0). The first one will have its
center at (x,y), with half-width r and
color c. Succeeding squares will be offset
by adding r to the x and
y coordinates of the corner; the effect will
be that each square will be centered on the lower-right
corner of the previous one. You should get a picture that
looks like a blue staircase.
vanishingSquares which is similar to
diagonalSquares, except replace the size argument
r in the recursive call (to
vanishingSquares, of course) with the expression
r*3/4. To try this out, you will probably want
to start with a larger initial square; something like this
should work: showSquareList(vanishingSquares(30, 30,
20, blue, 7))
++. Here is a skeleton of the code for you to
fill in:
squareDesign(x, y, r, c, 0) = ;
squareDesign(x, y, r, c, n) = [square(x, y, r, c) :
squareDesign(x-r, y-r, r/2, c, n-1) ++
squareDesign(x+r, y-r, r/2, c, n-1) ++
squareDesign( ) ++
squareDesign( )];
When you have successfully compiled the finished function,
try evaluating the following expression:
showShapeList(squareDesign(100, 100, 40, blue, 4)).
You can change the 4 to
5 to draw one more level, but it will take too
long if you try to do 6 or more levels (each level has four
times as many squares, so there are 1024 squares at level
6).
lessRed and
lessGreen, each of type (Color) ->
Color. Here is one:
lessRed(RGBA(r, g, b, a)) = RGBA(r/2, g, b, a);You will need to enter this and a similar definition for
lessGreen, then write a new function similar
to squareDesign that calls these functions in
the appropriate places. Call this new function
colorDesign, and test it (make sure the initial square
has some red and green in it--for example,
showShapeList(colorDesign(100, 100, 40, white, 5))).
2; for example, if
you modify colorDesign, then your new function
should be named colorDesign2.| Overview | Schedule | Resources | Assignments | Home |
![]()
DePauw University,
Computer Science Department,
Fall 2006
Maintained by Brian Howard
(bhoward@depauw.edu).
Last updated