Define the
below
operation for painters. Below
takes two painters as arguments. The resulting painter, given a frame, draws with the first painter in the bottom of the frame and with the second painter in the top. Define below
in two different ways -- first by writing a procedure that is analogous to the beside
procedure given above, and again in terms of beside
and suitable rotation operations (from exercise 2.50). Here's the procedure
beside
:
(define (beside painter1 painter2) (let ((split-point (make-vect 0.5 0.0))) (let ((paint-left (transform-painter painter1 (make-vect 0.0 0.0) split-point (make-vect 0.0 1.0))) (paint-right (transform-painter painter2 split-point (make-vect 1.0 0.0) (make-vect 0.5 1.0)))) (lambda (frame) (paint-left frame) (paint-right frame)))))This takes two painters and applies transformations to them such that the first painter is squashed into the left-hand side of a frame, while the second painter is squashed into the right-hand side of the frame... Assuming, of course, that the frame is orientated normally. I.e. with the
origin
at the bottom left-hand corner, edge1
defining the bottom side of the frame, going from left to right, and edge2
defining the left side of the frame, going from bottom to top. We can express this mapping graphically as follows:
We can use a similar pattern to this for our first version of below
, except we want the mapping produced to divide the frame into two horizontal stripes, one above the other. Graphically this is:
To do this we need a different split-point
, (0, 0.5) instead of (0.5, 0), and this split-point
needs to split edge2
rather than edge1
. And we need to rename a few variables. Other than that, it's pretty similar:
(define (below painter1 painter2) (let ((split-point (make-vect 0.0 0.5))) (let ((paint-down (transform-painter painter1 (make-vect 0.0 0.0) (make-vect 1.0 0.0) split-point)) (paint-up (transform-painter painter2 split-point (make-vect 1.0 0.5) (make-vect 0.0 1.0)))) (lambda (frame) (paint-down frame) (paint-up frame)))))And putting this to the test with...
((below wave spiral) window)...gives: Now onto the second version... As we noted,
beside
puts its first painter on the left-hand side of the frame and its second on the right-hand side. We want below
to put the first painter underneath the second painter. Graphically we can view this as the following rotation:
This rotation is a 90° anti-clockwise rotation. Fortunately, we've already been given a procedure for doing this, rotate90
, which was introduced in the section "Transforming and combining painters". Unfortunately, as the image above shows, this translation also has the effect of rotating the contents of the painters by 90° anti-clockwise. We need to compensate for this by rotating each of the painters themselves by 90° clockwise, which is equivalent to rotating by 270° anti-clockwise and is encapsulated in the procedure rotate270
which we defined in exercise 2.50.Here's what we get when we put these two sets of rotations together:
(define (below painter1 painter2) (rotate90 (beside (rotate270 painter1) (rotate270 painter2))))As you'd expect, this gives identical results to the first version above.
No comments:
Post a Comment