# Laboratory: Project Ideas

Summary: In this laboratory, you will explore the three new approaches to making images that were covered in the corresponding reading.

## Preparation

Make a copy of `project-ideas-lab.scm`, which contains much of the code from the reading.

## Exercises on Color Trees

### Exercise 1: Color Tree Basics

a. What effect do you expect the following instructions to have?

````>` `(define t1 (cons "grey" (cons "red" "black")))`
`>` `(define image1 (ctree->image t1 200 200))`
`>` `(image-show image1)`
```

c. What effect do you expect the following instructions to have?

````>` `(define t2 (cons (cons "red" t1) t1))`
`>` `(define image2 (ctree->image t2 200 200))`
`>` `(image-show image2)`
```

e. What effect do you expect the followings instruction to have?

````>` `(define image3 (image-new 200 200))`
`>` `(image-render-color-tree! image3 t1 0 0 100 100)`
`>` `(image-render-color-tree! image3 t1 100 100 50 25)`
`>` `(image-render-color-tree! image3 t1 100 150 25 25)`
`>` `(image-show image3)`
```

g. Create one or two color trees of your own and render them.

### Exercise 2: New Ways to Render Color Trees

a. The base case for `image-render-color-tree!` is to render the area as a rectangle. What do you expect to happen if we change the call to `image-select-rectangle!` to `image-select-ellipse!`?

b. Check your answer experimentally. Then restore the call to `image-select-rectangle!`.

c. As written, the width used in recursive calls during horizontal splits is `(/ width 2)`. What do you expect to have happen if we change that to `(/ width 2.5)`? (Assume we change it for both recursive calls.)

e. As written, the top edge used in recursive calls for vertical splits is `(+ top (/ height 2))`. What do you expect to have happend if we use `(+ top (/ height 1.5))`?

### Exercise 3: A Simple Series of Images

Look at the code for `series-1`.

a. What do you expect `(series-1 5 100 100)` to produce?

c. What do you expect `(series-1 42 100 100)` to produce?

e. Do you expect `(series-1 43 100 100)` to be similar to or very different from the image you got using 42? How do you expect it to differ?

g. How do you expect `(series-1 43 500 500)` to differ?

i. How do you expect `(series-1 43 800 100)` to relate to the previous two images?

## Exercises on Fractals

### Exercise 4: Simple Fractal Activities

a. Use `fractal-rectangle!` to draw a 200x200 blue rectangle on `canvas`, using a recursion level of 0.

b. Use `fractal-rectangle!` to draw a 200x200 red rectangle using a recursion level of 1. (Don't be surprised if it looks pretty boring.)

c. Use `fractal-rectangle!` to draw a 200x200 green rectangle using a recursion level of 2. (Again, don't be surprised if it's boring.)

d. After those three exercises, you are probably ready to do something a bit more interesting. Here's a modified version of `fractal-rectangle!` in which we've changed the recursive calls for the top-middle, left-middle, right-middle, and bottom-middle subrectangles so that they use the complement of the color.

```(define fractal-rectangle-c!
(lambda (image color left top right bottom level)
(cond
; Base case: We're at a level in which we just draw the rectangle.
((= level 0)
(context-set-fgcolor! color)
(image-select-rectangle! image REPLACE
left top
(- right left)
(- bottom top))
(image-fill-selection! image)
(image-select-nothing! image)
(context-update-displays!))
; Recursive case: Break the rectangle into a few parts and recurse
; on each.
(else
(let* ((midcol1 (round (+ left (/ (- right left) 3))))
(midcol2 (round (- right (/ (- right left) 3))))
(midrow1 (round (+ top (/ (- bottom top) 3))))
(midrow2 (round (- bottom (/ (- bottom top) 3)))))
; First row of squares
(fractal-rectangle-c! image
color
left top
midcol1 midrow1
(- level 1))
(fractal-rectangle-c! image
(rgb-complement color)
midcol1 top
midcol2 midrow1
(- level 1))
(fractal-rectangle-c! image
color
midcol2 top
right midrow1
(- level 1))
; Second row of squares
(fractal-rectangle-c! image
(rgb-complement color)
left midrow1
midcol1 midrow2
(- level 1))
(fractal-rectangle-c! image
color
midcol1 midrow1
midcol2 midrow2
(- level 1))
(fractal-rectangle-c! image
(rgb-complement color)
midcol2 midrow1
right midrow2
(- level 1))
; Third row of squares
(fractal-rectangle-c! image
color
left midrow2
midcol1 bottom
(- level 1))
(fractal-rectangle-c! image
(rgb-complement color)
midcol1 midrow2
midcol2 bottom
(- level 1))
(fractal-rectangle-c! image
color
midcol2 midrow2
right bottom
(- level 1))
)))))
```

Put this new version at the end of your definitions pane.

Use this procedure to draw a 200x200 rectangle fractal with black as the initial color and a recursion level of 1. Once you've done that, try it with a recursion level of 2.

e. Predict what will happen if you draw a 200x200 rectangle with yellow as the initial color and a recursion level of 3. Then check your prediction experimentally.

f. Here is a procedure that averages two RGB colors.

```;;; Procedure:
;;;   rgb-average
;;; Parameters:
;;;   c1, an RGB color
;;;   c2, an RGB color
;;; Purpose:
;;;   Compute the "average" of two RGB colors.
;;; Produces:
;;;   c_ave, an RGB color
;;; Preconditions:
;;; Postconditions:
;;;   (rgb-red c_ave) is the average of (rgb-red c1) and (rgb-red c2)
;;;   (rgb-green c_ave) is the average of (rgb-green c1) and (rgb-green c2)
;;;   (rgb-blue c_ave) is the average of (rgb-blue c1) and (rgb-blue c2)
(define rgb-average
(lambda (c1 c2)
(rgb-new (quotient (+ (rgb-red c1) (rgb-red c2)) 2)
(quotient (+ (rgb-green c1) (rgb-green c2)) 2)
(quotient (+ (rgb-blue c1) (rgb-blue c2)) 2))))
```

And here is a rewritten `fractal-rectangle!` that averages the colors in the top-middle, left-middle, right-middle, and bottom-middle subrectangles with black and the colors in the other five subrectangles with white.

```(define fractal-rectangle-a!
(lambda (image color left top right bottom level)
(cond
; Base case: We're at a level in which we just draw the rectangle-a.
((= level 0)
(context-set-fgcolor! color)
(image-select-rectangle! image REPLACE
left top
(- right left)
(- bottom top))
(image-fill-selection! image)
(image-select-nothing! image)
(context-update-displays!))
; Recursive case: Break the rectangle-a into a few parts and recurse
; on each.
(else
(let* ((midcol1 (round (+ left (/ (- right left) 3))))
(midcol2 (round (- right (/ (- right left) 3))))
(midrow1 (round (+ top (/ (- bottom top) 3))))
(midrow2 (round (- bottom (/ (- bottom top) 3)))))
; First row of squares
(fractal-rectangle-a! image
(rgb-average color RGB-WHITE)
left top
midcol1 midrow1
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-BLACK)
midcol1 top
midcol2 midrow1
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-WHITE)
midcol2 top
right midrow1
(- level 1))
; Second row of squares
(fractal-rectangle-a! image
(rgb-average color RGB-BLACK)
left midrow1
midcol1 midrow2
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-WHITE)
midcol1 midrow1
midcol2 midrow2
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-BLACK)
midcol2 midrow1
right midrow2
(- level 1))
; Third row of squares
(fractal-rectangle-a! image
(rgb-average color RGB-WHITE)
left midrow2
midcol1 bottom
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-BLACK)
midcol1 midrow2
midcol2 bottom
(- level 1))
(fractal-rectangle-a! image
(rgb-average color RGB-WHITE)
midcol2 midrow2
right bottom
(- level 1))
)))))
```

g. What do you expect to have happen if we draw a 200x200 level-2 fractal rectangle whose initial color is blue? Check your answer experimentally.

h. What do you expect to have happen if we draw a 200x200 level-3 fractal rectangle whose initial color is green? Check your answer experimentally.

i. Let's change the computation of the intermediate boundaries so that `midcol1` is 1/4 of the way across, `midcol2` is 1/2 of the way across, `midrow1` is 1/4 of the way down, and `midrow2` is 1/2 of the way down. Add the following to the end of your definitions pane.

```(define fractal-rectangle-u!
(lambda (image color left top right bottom level)
(cond
; Base case: We're at a level in which we just draw the rectangle-u.
((= level 0)
(context-set-fgcolor! color)
(image-select-rectangle! image REPLACE
left top
(- right left)
(- bottom top))
(image-fill-selection! image)
(image-select-nothing! image)
(context-update-displays!))
; Recursive case: Break the rectangle-u into a few parts and recurse
; on each.
(else
(let* ((midcol1 (round (+ left (/ (- right left) 4))))
(midcol2 (round (+ midcol1 (/ (- right left) 4))))
(midrow1 (round (+ top (/ (- bottom top) 4))))
(midrow2 (round (+ midrow1 (/ (- bottom top) 4)))))
; First row of squares
(fractal-rectangle-u! image
(rgb-average color color-white)
left top
midcol1 midrow1
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-black)
midcol1 top
midcol2 midrow1
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-white)
midcol2 top
right midrow1
(- level 1))
; Second row of squares
(fractal-rectangle-u! image
(rgb-average color color-black)
left midrow1
midcol1 midrow2
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-white)
midcol1 midrow1
midcol2 midrow2
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-black)
midcol2 midrow1
right midrow2
(- level 1))
; Third row of squares
(fractal-rectangle-u! image
(rgb-average color color-white)
left midrow2
midcol1 bottom
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-black)
midcol1 midrow2
midcol2 bottom
(- level 1))
(fractal-rectangle-u! image
(rgb-average color color-white)
midcol2 midrow2
right bottom
(- level 1))
)))))
```

j. What do you expect to have happen if we draw a 200x200 level-2 fractal rectangle whose initial color is red? Check your answer experimentally. What about a level-3 fractal?

k. Change the computation of the intermediate boundaries so that `midcol1` is 1/4 of the way across, `midcol2` is 3/4 of the way across, `midrow1` is 1/4 of the way down, and `midrow2` is 3/4 of the way down.

l. Draw one final level-3 fractal.

### Exercise 5: Varying Parameters

Sometimes it is difficult to envision how you make 1000 variations of an image. But, as is often the case, the problem is a bit easier if you break it down into parts. Suppose we want all of our images to be based on the “spin a polygon” technique. In building different images, we can vary

• the number of sides (that is, the type of polygon);
• the angle at which the turtle is drawn;
• the number of copies we draw; and
• the color we use to draw the polygons.

(We probably can't vary the side length, since that should depend on the size of the image.)

Now, how do we turn one number (the `n` we're using to describe the image) into four different numbers (or six, if we change the red, green, and blue components separately)? We can use `mod`

```(define series-2
(lambda (n width height)
(let* ((canvas (image-new width height))
(t (turtle-new canvas))
(side-length (/ (+ width height) 12))
(sides (+ 3 (mod n 4)))
(angle (* 5 (mod n 5)))
(copies (+ 5 (* 2 (mod n 7))))
(red (* 256/11 (mod n 11)))
(green (* 256/13 (mod n 13)))
(blue (- 256 red)))
(turtle-set-color! t (rgb-new red green blue))
(turtle-teleport! t (/ width 3) (/ height 3))
(turtle-spin-polygon! t side-length sides angle copies)
(image-show canvas)
canvas)))
```

a. Try this procedure with a variety of values for `n`, `width`, and `height`

b. In your own words, explain how the procedure works to vary the drawing.

c. Can we be sure that this procedure creates 1000 different drawings for the values of `n` from 0 to 999? Why or why not?

Copyright (c) 2007-10 Janet Davis, Matthew Kluber, Samuel A. Rebelsky, and Jerod Weinman. (Selected materials copyright by John David Stone and Henry Walker and used by permission.)

This material is based upon work partially supported by the National Science Foundation under Grant No. CCLI-0633090. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.

This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License. To view a copy of this license, visit `http://creativecommons.org/licenses/by-nc/2.5/` or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.