Summary:
In this laboratory, you will explore techniques for iterating over lists
using the map and for-each
procedures.
Reference:
(for-each
proc!
lst)
proc! to each element of the
given list. Called primarily for side effects.
(map
func
lst)
func to the corresponding element of
lst.
a. If your library does not include definitions
for all the spot functions, add the definitions of
spot-new, spot-col,
spot-row, spot-color,
image-render-spot!,
image-scaled-render-spot!,
spot-htrans, and spot-vtrans
to your definitions pane. Most of these definitions can be found
at the end of the lab on
spot lists. The rest can be found at the end of this lab.
b. Load your library.
c. Create a list of six to ten spots and call it
my-stamp. If you're not feeling particularly creative,
you can use the following.
(define my-stamp
(list (spot-new 2 0 "blue")
(spot-new 0 1 "blue")
(spot-new 1 1 "blue")
(spot-new 2 1 "blue")
(spot-new 3 1 "blue")
(spot-new 4 1 "blue")
(spot-new 2 2 "blue")
(spot-new 1 3 "blue")
(spot-new 3 3 "blue")
(spot-new 1 4 "blue")
(spot-new 3 4 "blue")))
d. Add the following definitions (taken from the reading) to your definitions pane.
;;; Procedure:
;;; image-render-stamp!
;;; Parameters:
;;; image, an image
;;; stamp, a list of spots
;;; Purpose:
;; Draw the stamp on the image.
;;; Produces:
;;; image, the same image
(define image-render-stamp!
(lambda (image stamp)
(for-each (lambda (spot) (image-render-spot! image spot)) stamp)
image))
;;; Procedure:
;;; image-render-big-stamp!
;;; Parameters:
;;; image, an image id
;;; stamp, a list of spots
;;; Purpose:
;;; Render a stamp (a list of spots) "bigger".
;;; Produces:
;;; image, the same image
;;; Preconditions:
;;; Each scaled spot can be safely rendered.
(define image-render-big-stamp!
(lambda (image stamp)
(for-each (lambda (spot) (image-scaled-render-spot! image spot 20)) stamp)
image))
;;; Procedure:
;;; image-scaled-render-stamp!
;;; Parameters:
;;; image, an image
;;; stamp, a list of spots.
;;; factor, a number
;;; Purpose:
;; Draw all of the spots in the stamp on the image, with each spot
;;; scaled by factor.
;;; Produces:
;;; image, the same image
;;; Preconditions:
;;; factor >= 1
;;; The position of the scaled spot is within the bounds of the image.
;;; Postconditions:
;;; The image now contains a rendering of each spot.
(define image-scaled-render-stamp!
(lambda (image stamp scale)
(for-each (lambda (spot) (image-scaled-render-spot! image spot scale))
stamp)
image))
a. Create a new 200x200 image and call it canvas.
b. Using image-render-stamp!, render
my-stamp on canvas.
c. Using image-render-big-stamp!, render my-stamp on
canvas.
Recall that we can horizontally translate each spot in a list
of spots using (map (lambda (spot) (spot-htrans spot
and that you can vertically translate each spot using offset)) stamp)(map
(lambda (spot) (spot-vtrans spot .
offset))
stamp)
a. Confirm that (map (lambda (spot) (spot-htrans spot 7)) my-stamp)
translates each spot seven spaces to the right. That is, execute the
instruction and read the results.
b. Confirm that (map (lambda (spot) (spot-vtrans spot 11)) my-stamp) translates each spot eleven spaces down.
Once again, execute the instruction and read the results.
c. Create a new image and render each of the translated figures using
image-render-stamp!.
a. Write a procedure, (,
that translates each spot in stamp-htrans
stamp offset)stamp
horizontally by offset.
b. Write a procedure, (,
that translates each spot in stamp-vtrans
stamp offset)stamp
vertically by offset.
c. Write a procedure, (, that translates each
spot in stamp-translate
stamp hoffset
voffset)stamp horizontally by
hoffset and vertically by
voffset.
a. Create a 200x200 image called canvas.
b. What do you expect (stamp-htrans my-stamp -2) to do?
c. Check your answer experimentally.
d. What do you expect the following code to do?
>(image-render-stamp! canvas (stamp-htrans my-stamp -2))
e. Check your answer experimentally.
f. As you should have discovered, trying to draw the left-translated
figure will result in an error, since some of the pixels are outside
the boundary of the image. Fix this problem by rewriting
image-render-spot! so that if the spot is to be drawn outside
of the bounds of the image, nothing happens. (That is, a spot is
not drawn and an error message is not produced.)
g. Verify that your revised procedure now lets us draw the portion of the left-translated figure that is still on screen.
a. What do you expect the value of aardvark to be after the following definition?
>(define aardvark (map (lambda (offset) (stamp-htrans my-stamp offset)) (list 1 2 4 8)))
b. Check your answer experimentally.
c. As you should have discovered, these instructions create a list of lists of spots.
d. What effect do you expect the following command to have?
>(image-render-stamp! canvas aardvark)
e. Check your answer experimentally.
f. What effect do you expect the following command to have?
>(for-each (lambda (stamp) (image-render-stamp! canvas stamp)) aardvark)
g. Check your answer experimentally.
h. What effect do you expect the following command to have?
>(for-each (lambda (factor) (image-scaled-render-stamp! canvas my-stamp factor)) (list 1 2 3 4 5))
i. Check our answer experimentally.
Those with extra time may choose to do the extra problems, which focus on programming tasks, or the explorations, which focus on the application of procedures to image creation. Those who do the programming oriented exercises might start with extra 1 or with extra 3.
a. Write a procedure, (, that gets the spot that corresponds
to the given position in the image. That is, if the color at
position (image-get-spot
image col
row)col,row)
is c, then image-get-spot
will return (.
col row
c)
Hint: You will probably need to use
image-get-pixel, and spot-new.
b. Write a procedure, ( that
gets spots from the given row, but only at the selected columns.
For example,
image-get-stamp-from-row
image
row cols)
>(image-get-stamp-from-row 10 (list 1 2 3 4 5))
will get the spots at positions (1,10), (2,10), (3,10), (4,10), and (5,10).
Note that you will need to use map to write
this procedure.
Pick a group of interesting positions in picture and,
by using image-get-stamp-from-row, turn them
into a list of spots. Name the result another-stamp.
For example,
> (define another-stamp
(append (image-get-stamp-from-row 100 (list 10 11 12 13 14 15))
(image-get-stamp-from-row 101 (list 11 12 13 14 15))
(image-get-stamp-from-row 102 (list 12 13 14 15))
(image-get-stamp-from-row 103 (list 13 14 15))
(image-get-stamp-from-row 104 (list 14 15))
(image-get-stamp-from-row 105 (list 15)))
b. Render a copy of the stamp elsewhere in the image.
c. Render another copy of the stamp elsewhere in the image.
a. Write a procedure, (, that
“mirrors” the stamp given by stamp-hmirror
stamp col)stamp
around the vertical line through col.
For example, if a spot is at (1,2), and we horizontally mirror that
spot around column 5, we get a spot at (9,2) with the same color.
(How did we get 9 from 1? 1 is 4 less than 5, so it mirrors to 4
greater than 5.) Similarly, a spot at (8,3) would mirror to (2,3).
A spot in column 5 would stay where it is.
b. Write a similar procedure, (stamp-vmirror
, the
mirrors the figure given by stamp row)stamp around the
horizontal line through row.
Explorations are intended for students interested in further exploring the design aspects of these techniques. They also provide students who finish early with extra activities that may challenge them in different ways.
In this lab, you've discovered how to write concise code that lets you render the same list of spots in multiple scales and with multiple offsets.
Create a simple stamp, and, from that stamp, create an interesting image by both offsetting and scaling the stamp.
This lab depends on a variety of procedures that you should have defined in the lab on representing stamps as lists of spots. However, some of you may have not had time to complete all of those problems and others of you may not be sure of your answers. Grab most of the procedures from that lab, and the rest from here.
;;; Procedure:
;;; spot-htrans
;;; Parameters:
;;; spot, a spot
;;; offset, a number
;;; Purpose:
;;; Translate the spot horizontally by offset. If offset is positive,
;;; the spot is translated right. If offset is negative, the spot
;;; is translated left.
;;; Produces:
;;; new-spot, a spot
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (spot-col new-spot) = (spot-col spot) + offset
(define spot-htrans
(lambda (spot offset)
(spot-new (+ (spot-col spot) offset) (spot-row spot) (spot-color spot))))
;;; Procedure:
;;; spot-vtrans
;;; Parameters:
;;; spot, a spot
;;; offset, a number
;;; Purpose:
;;; Translate the spot vertically by offset. If offset is positive,
;;; the spot is translated down. If offset is negative, the spot
;;; is translated up.
;;; Produces:
;;; new-spot, a spot
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; (spot-row new-spot) = (spot-row spot) + offset
(define spot-vtrans
(lambda (spot offset)
(spot-new (spot-col spot) (+ (spot-row spot) offset) (spot-color spot))))