Make changes to the square limit of wave shown in figure 2.9 by working at each of the levels described above. In particular:
- Add some segments to the primitive
wave painter of exercise 2.49 (to add a smile, for example).
- Change the pattern constructed by
corner-split (for example, by using only one copy of the up-split and right-split images instead of two).
- Modify the version of
square-limit that uses square-of-four so as to assemble the corners in a different pattern. (For example, you might make the big Mr. Rogers look outward from each corner of the square.)
Before we get started, let's see what our current procedures give us. We're going to be modifying the
wave painter, so we'll show what that looks like with
square-limit. If we try
((square-limit wave 4) window) we get:
Now let's add a smile and a pair of eyes to the
wave painter. I quickly sketched out what I wanted to add as follows:
From this we can work out the coordinates for the eyes and smile and then add in another three sets of connected segments using
build-segments-list as we did in exercise 2.49. The extended
wave painter looks like this, with the new connected segment sets added at the bottom:
(define wave
(segments->painter
(append (build-segments-list (make-vect 0.0 0.85)
(make-vect 0.15 0.6)
(make-vect 0.3 0.65)
(make-vect 0.4 0.65)
(make-vect 0.35 0.85)
(make-vect 0.4 1.0))
(build-segments-list (make-vect 0.6 1.0)
(make-vect 0.65 0.85)
(make-vect 0.6 0.65)
(make-vect 0.75 0.65)
(make-vect 1.0 0.35))
(build-segments-list (make-vect 1.0 0.15)
(make-vect 0.6 0.45)
(make-vect 0.75 0.0))
(build-segments-list (make-vect 0.6 0.0)
(make-vect 0.5 0.3)
(make-vect 0.4 0.0))
(build-segments-list (make-vect 0.25 0.0)
(make-vect 0.35 0.5)
(make-vect 0.3 0.6)
(make-vect 0.15 0.4)
(make-vect 0.0 0.65))
(build-segments-list (make-vect 0.4 0.9)
(make-vect 0.45 0.9)
(make-vect 0.45 0.85)
(make-vect 0.4 0.85)
(make-vect 0.4 0.9))
(build-segments-list (make-vect 0.55 0.9)
(make-vect 0.6 0.9)
(make-vect 0.6 0.85)
(make-vect 0.55 0.85)
(make-vect 0.55 0.9))
(build-segments-list (make-vect 0.4 0.75)
(make-vect 0.45 0.7)
(make-vect 0.55 0.7)
(make-vect 0.6 0.75)))))
Trying this out with
(wave window) gives:
...and
((square-limit wave 4) window) gives:
Next we can work on
corner-split. The exercise suggests only using one copy of the
up-split and
right-split images, instead of two. This is a nice straightforward change. Here's the original
corner-split:
(define (corner-split painter n)
(if (= n 0)
painter
(let ((up (up-split painter (- n 1)))
(right (right-split painter (- n 1))))
(let ((top-left (beside up up))
(bottom-right (below right right))
(corner (corner-split painter (- n 1))))
(beside (below painter top-left)
(below bottom-right corner))))))
As you can see it defines
top-left as applying
beside with
up as both parameter values and
bottom-right as applying
below with
right as both parameter values. We can see the effect of
corner-split by applying it to the updated
wave via
((corner-split wave 4) window):
All we need to do is to remove these definitions and replace usages of
top-left and
bottom-right with
up and
right respectively. If we do this (and collapse the
let statements as the nesting is no longer needed) we get:
(define (corner-split painter n)
(if (= n 0)
painter
(let ((up (up-split painter (- n 1)))
(right (right-split painter (- n 1)))
(corner (corner-split painter (- n 1))))
(beside (below painter up)
(below right corner)))))
Testing this with
((corner-split wave 4) window) now gives:
...and
((square-limit wave 4) window) now gives:
Finally we can look at changing
square-limit. The exercise suggests making
"the big Mr. Rogers look outward from each corner of the square". If we look at the quadrants as they're shown in
section 2.2.4 we can see that Mr. Rodgers currently looks inward at the center of the square. E.g. in the top-right quadrant Mr. Rodgers' face is in the bottom-left-hand corner and looks towards the left.
Now there are at least a couple of ways in which you could interpret this suggested change depending upon what orientation of the head you end up with in each quadrant. I decided to go with the simplest - I'll have Mr. Rodgers' face have the correct orientation in the bottom-right quadrant. I.e. in the bottom-right quadrant Mr. Rodgers' face will be in the bottom-left-hand corner and look towards the left. This then reduces the problem to simply swapping over the contents of opposite corners of the square. So we take the original
square-limit of:
(define (square-limit painter n)
(let ((combine4 (square-of-four flip-horiz identity
rotate180 flip-vert)))
(combine4 (corner-split painter n))))
...and then swap the top-left corner with the bottom-right and the top-right corner with the bottom-left to give:
(define (square-limit painter n)
(let ((combine4 (square-of-four flip-vert rotate180
identity flip-horiz)))
(combine4 (corner-split painter n))))
When we try this out with
((square-limit wave 4) window) we now get: