Fundamentals of Computer Science I: Media Computing (CS151.01 2008S)
Primary: [Front Door] [Syllabus] - [Academic Honesty] [Instructions]
Current: [Outline] [EBoard] [Reading] [Lab] [Assignment]
Groupings: [Assignments] [EBoards] [Examples] [Exams] [Handouts] [Labs] [Outlines] [Projects] [Readings]
References: [A-Z] [Primary] [Scheme Report (R5RS)] [Scheme Reference] [DrScheme Manual]
Related Courses: [CSC151.02 2008S (Davis)] [CSC151 2007F (Rebelsky)] [CSC151 2007S (Rebelsky)] [CSCS151 2005S (Stone)]
Summary: In this laboratory, you will further explore the techniques for making geometric images.
a. Create a new 200x200 image and call it canvas
.
b. If you have not already done so, add the procedures from the reading to your library. You can find the code for these procedures at the end of this lab.
c. In your DrFu window, load your library.
a. Test each of the two basic procedures from
the reading:
draw-three-parallel-lines!
and
draw-circle!
.
b. Look at each of the examples in the introduction to the corresponding reading, predict what you think the example code will do, and then run the example in DrFu.
c. The reading provides four procedures that draw parallel lines (with
some variation between them),
draw-parallel-lines!
,
draw-colored-parallel-lines!
,
draw-sin-with-parallel-lines!
, and
draw-parallel-lines-with-decreasing-spacing!
.
Make sure you understand what each of the procedures is supposed
to do, and then try using each with two different sets of parameters.
a. Make a copy of draw-sin-with-parallel-lines!
and
rename it draw-func-with-parallel-lines!
. Make
sure that this renamed copy still works.
b. Revise the procedure to graph cosine, rather than sine.
c. Revise the procedure to graph the sum of sine and cosine, rather than the sine (or cosine).
d. Revise the procedure to graph a function of your choice.
e. Revise the function so that it draws each line in a different color (based on the column of the line or the height of the line, as you choose).
In the reading, we considered how one might use different brushes for neighboring parallel lines, but never finished the procedure to do that. Here's a header for that procedure.
(define draw-parallel-lines-with-many-brushes! (lambda (image brushes n start-col start-row end-col end-row hoff voff) ...))
a. Finish writing the procedure. You should look at the definition of some
of the other parallel line procedures (such as
draw-parallel-lines!
) to figure out what belongs.
b. What do you expect the following call to generate?
>
(define some-brushes (list "Circle (01)" "Circle (03)" "Circle (05)" "Circle (07)" "Circle (09)" "Circle (11)"))
>
(draw-parallel-lines-with-many-brushes! canvas some-brushes 12 10 10 100 10 0 15)
c. Check your answer experimentally.
d. Here's a slight variation of the previous set of instructions in which we use a different list of brushes. (We also change the orientation of the lines.) What effect do you expect this change to the brushes to have?
>
(define more-brushes (append some-brushes (cdr (reverse (cdr some-brushes)))))
>
(draw-parallel-lines-with-many-brushes! canvas more-brushes 12 10 10 10 100 15 0)
e. Check your answer experimentally.
f. Extend the procedure so that it varies both color and brushes.
In the reading, we explored a procedure in which each space between lines
is half of the space between lines to the left. Some callers might prefer
to have a different ratio, such as 3/4 or 1/3. Let's rewrite the procedure
to permit the caller to specify that parameter, which we'll call
ratio
. Here's the start of the new procedure,
with a somewhat shorter name.
(define draw-geometric-progression! (lambda (image col start-row end-row spacing ratio close-enough) ...))
a. Write that procedure.
b. What do you expect the following set of instructions to do?
>
(define new-canvas (image-new 200 200))
>
(image-show new-canvas)
>
(context-set-brush! "Circle (01)")
>
(draw-geometric-progression! new-canvas 5 10 190 80 0.5 2)
>
(context-update-displays!)
c. Check your answer experimentally.
d. Consider the following variant of the previous instructions, using a smaller ratio. How do you expect the generated image to differ?
>
(define new-canvas (image-new 200 200))
>
(image-show new-canvas)
>
(context-set-brush! "Circle (01)")
>
(draw-geometric-progression! new-canvas 5 10 190 80 0.4 2)
>
(context-update-displays!)
e. Check your answer experimentally.
f. Consider the following variant of the previous instructions, using a larger ratio. How do you expect the generated image to differ?
>
(define new-canvas (image-new 200 200))
>
(image-show new-canvas)
>
(context-set-brush! "Circle (01)")
>
(draw-geometric-progression! new-canvas 5 10 190 80 0.75 2)
>
(context-update-displays!)
g. Check your answer experimentally.
As you probably discovered in the final problem of the previous exercise, if the caller isn't careful, the final lines in the progression are drawn off the side of the image, which causes an error.
a. Update draw-geometric-progression!
so that
it stops for two reasons: the spacing is less than or equal to
close-enough
(as before) or the line to be drawn is
outside the right-hand boundary of the image.
b. Rerun the final example from the previous exercise to confirm that you have corrected the error.
c. While draw-geometric-progression!
is designed
for progressions in which the spacing between subsequent lines decreases,
we should also be able to make it draw progressions in which the spacing
increases. Write instructions for generating a sequence of lines in which
the first line appears in column 3, the next in column 5 (spacing of 2),
the next in column 9 (spacing of 4), the next in column 17 (spacing of 8),
and the spacing continues to double.
In the introduction to the corresponding reading, after drawing three parallel lines, we then generalized that technique. However, although we drew three concentric circles, we never generalized that technique.
a. Write a procedure, (
, that draws a
sequence of draw-bullseye!
image
n
col
row
outer-radius
delta-radius
)n
concentric circles, all
with the same center, in which the outermost circle is radius of
outer-radius
and each subsequent circle has a
radius that is delta-radius
smaller.
b. As we saw in the reading, it can also be interesting to draw a
sequence of circles that do not share a center, but have a progression
of centers as well as a progression of smaller radii. Write a
procedure, (
,
that draws a sequence of draw-circle-sequence!
image
n
col
row
radius
d-col
d-row
d-radius
)n
circles, the first of which is centered at
(col
,row
) with
radius radius
, and each subsequent one
has the column offset by d-col
, row
offset by d-row
, and radius offset by
d-radius
.
c. Rewrite draw-bullseye!
so that its body is a call to
draw-circle-sequence!
.
You need not do the extra problems in order. Read through them and decide which is most worth your time.
In the corresponding reading, we wrote a procedure,
draw-parallel-lines!
, using direct recursion. It
is also possible to write this procedure using a clever combination of
map
, iota
, and an anonymous function.
Try rewriting draw-parallel-lines!
using this
strategy.
Consider a function,
(
, that draws
draw-left-bounded-circles!
image
n
col
row
radius
delta-radius
)n
circles, each of which has a left edge at
column col
, the outermost circle has radius
radius
and each subsequent circle has a radius
that is delta-radius
smaller than the previous
circle.
a. Write this procedure using direct recursion.
b. Can you write this procedure with a call to
draw-circle-sequence!
? Why or why not?
Rewrite draw-circle-sequence!
so that it adds some
interesting variant. It might draw the circles in different colors,
using a nonlinear offset of radii or centers, or anything else you
deem appropriate.
Create an image that you find aesthetically appealing with a few calls to
one of the variants of draw-parallel-lines!
. You should feel
free to change brush and foreground color between calls.
A number of artists have created interesting images using concentric
circles and other geometric shapes. One of the more famous is French
artist Robert Delaunay. Find a few of Delaunay's works and see if you
can make something that resembles a portion of a work using a variant
of draw-circle-sequence!
.
;;; Procedure: ;;; draw-circle! ;;; Parameters: ;;; image, an image ;;; col, an integer ;;; row, an integer ;;; radius, an integer ;;; Purpose: ;;; Draws a circle with the specified in the current brush and color, centered at (col,row). ;;; Produces: ;;; [Nothing; Called for the side effect] ;;; Preconditions: ;;; 0 <= col < (image.width image) ;;; 0 <= row < (image.height image) ;;; 0 < radius ;;; Postconditions: ;;; The image now contains the specified circle. (The circle may not be visible.) (define draw-circle! (lambda (image col row radius) (image-select-ellipse! image selection-replace (- col radius) (- row radius) (+ radius radius) (+ radius radius)) (image-stroke! image) (image-select-nothing! image))) ;;; Procedure: ;;; draw-three-parallel-lines! ;;; Parameters: ;;; image, an image ;;; start-col, an integer ;;; start-row, an integer ;;; end-col, an integer ;;; end-row, an integer ;;; hoffset, an integer ;;; voffset, an integer ;;; Purpose: ;;; Draw three parallel lines, with the first from (start-col,start-row) ;;; to (end-col,end-row) and the starting point of the next two offset ;;; horizontally by hoffset (and 2*hoffset) and vertically by voffset ;;; (and 2*voffset). ;;; Produces: ;;; [Nothing; Called for the side effect.] ;;; Preconditions: ;;; All three parallel lines can be drawn on the image. ;;; Postcondtions: ;;; The image has been appropriately modified. (define draw-three-parallel-lines! (lambda (image start-col start-row end-col end-row hoffset voffset) (image-draw-line! image start-col start-row end-col end-row) (image-draw-line! image (+ hoffset start-col) (+ voffset start-row) (+ hoffset end-col) (+ voffset end-row)) (image-draw-line! image (+ (* 2 hoffset) start-col) (+ (* 2 voffset) start-row) (+ (* 2 hoffset) end-col) (+ (* 2 voffset) end-row)))) ;;; Procedure: ;;; draw-parallel-lines! ;;; Parameters: ;;; image, an image ;;; n, an integer ;;; start-col, an integer ;;; start-row, an integer ;;; end-col, an integer ;;; end-row, an integer ;;; hoffset, an integer ;;; voffset, an integer ;;; Purpose: ;;; Draw n parallel lines, with the first from (start-col,start-row) ;;; to (end-col,end-row) and each subsequent one offset by the ;;; appropriate multiple of hoffset and voffset. ;;; Produces: ;;; [Nothing; Called for the side effect.] ;;; Preconditions: ;;; All parallel lines can be drawn on the image. ;;; Postcondtions: ;;; The image has been appropriately modified. (define draw-parallel-lines! (lambda (image n start-col start-row end-col end-row hoffset voffset) (cond ((> n 0) (image-draw-line! image start-col start-row end-col end-row) (draw-parallel-lines! image (- n 1) (+ hoffset start-col) (+ voffset start-row) (+ hoffset end-col) (+ voffset end-row) hoffset voffset))))) ;;; Procedure: ;;; position->color ;;; Parameters: ;;; col, an integer ;;; row, an integer ;;; Purpose: ;;; Compute a color based on col and row. ;;; Produces: ;;; color, an RGB color ;;; Preconditions: ;;; [No additional] ;;; Postconditions: ;;; Different col/row combinations are likely to give different colors. ;;; Nearby col/row combinations may give similar colors. (define position->color (lambda (col row) (rgb-new (+ 128 (* 128 (sin (* pi row 0.0625)))) (+ 128 (* 128 (cos (* pi col 0.0625)))) (+ 128 (* 128 (sin (* pi (+ row col) 0.0625))))))) (define draw-colored-parallel-lines! (lambda (image n start-col start-row end-col end-row hoff voff) (cond ((> n 0) (context-set-fgcolor! (position->color start-col start-row)) (image-draw-line! image start-col start-row end-col end-row) (draw-colored-parallel-lines! image (- n 1) (+ hoff start-col) (+ voff start-row) (+ hoff end-col) (+ voff end-row) hoff voff))))) ;;; Procedure: ;;; draw-sin-with-parallel-lines! ;;; Parameters: ;;; image, an image ;;; n, an integer ;;; offset, an integer ;;; start-col, an integer ;;; mid-row, an integer ;;; Purpose: ;;; Draw a sequence of parallel lines, with the height of the ;;; parallel line dependent on the column. ;;; Produces: ;;; [Nothing, called for the side effect.] (define draw-sin-with-parallel-lines! (lambda (image n offset start-col mid-row) (cond ((> n 0) (image-draw-line! image start-col mid-row start-col (+ mid-row (* mid-row (sin (* n pi 0.01))))) (draw-sin-with-parallel-lines! image (- n 1) offset (+ start-col offset) mid-row))))) ;;; Procedure: ;;; draw-parallel-lines-with-decreasing-spacing! ;;; Parameters: ;;; image, an image ;;; col, an integer ;;; start-row, an integer ;;; end-row, an integer ;;; spacing ;;; close-enough ;;; Purpose: ;;; Draw a sequence of vertical lines (each running from start-row ;;; to end-row) starting at col, then spaced by spacing from col, ;;; then by spacing/2 from that column, then spacing/4 from that ;;; column, and so on and so forth until the distance between columns ;;; is less than or equal to close-enough. ;;; Produces: ;;; [Nothing. Called for the side effects.] (define draw-parallel-lines-with-decreasing-spacing! (lambda (image col start-row end-row spacing close-enough) (image-draw-line! image col start-row col end-row) (if (> spacing close-enough) (draw-parallel-lines-with-decreasing-spacing! image (+ col spacing) start-row end-row (/ spacing 2) close-enough))))
Primary: [Front Door] [Syllabus] - [Academic Honesty] [Instructions]
Current: [Outline] [EBoard] [Reading] [Lab] [Assignment]
Groupings: [Assignments] [EBoards] [Examples] [Exams] [Handouts] [Labs] [Outlines] [Projects] [Readings]
References: [A-Z] [Primary] [Scheme Report (R5RS)] [Scheme Reference] [DrScheme Manual]
Related Courses: [CSC151.02 2008S (Davis)] [CSC151 2007F (Rebelsky)] [CSC151 2007S (Rebelsky)] [CSCS151 2005S (Stone)]
Copyright (c) 2007-8 Janet Davis, Matthew Kluber, and Samuel A. Rebelsky. (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.