Fundamentals of Computer Science I: Media Computing (CS151.02 2007F)
Primary: [Front Door] [Glance] - [Academic Honesty] [Instructions]
Current: [Outline] [EBoard] [Reading] [Lab] [Assignment]
Groupings: [Assignments] [EBoards] [Examples] [Exams] [Handouts] [Labs] [Outlines] [Projects] [Readings] [Reference]
Reference: [Scheme Report (R5RS)] [Scheme Reference] [DrScheme Manual]
Related Courses: [CSC151.01 2007F (Davis)] [CSC151 2007S (Rebelsky)] [CSCS151 2005S (Stone)]
Due: 4 p.m., Tuesday, 13 November 2007
Summary: In this assignment, you will develop procedures that allow us to use files to store information about simple shapes and to reproduce those shapes from the stored information.
Purposes: To give you more experience with files. To help you think about yet more representations of images.
Expected Time: Two to three hours.
Collaboration: We encourage you to work in groups of size three. You may, however, work alone or work in a group of size two or size four. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.
Submitting:
Email your answer to <rebelsky@grinnell.edu>. The title of your email
should have the form CSC151.02 2007F Assignment 13: Shape-Based Drawing and
should contain your answers to all parts of the assignment. Scheme code
should be in the body of the message.
Warning: So that this assignment is a learning experience for everyone, we may spend class time publicly critiquing your work.
As you've just seen in the exam, it can be useful to describe images as a sequence of simple drawing objects, such as circles and squares. There are many ways that we can represent such objects. In Scheme, one of the most natural techniques is to use a list. However, it can be difficult to make those lists persist between invocations of Scheme. We might also want to provide a slightly more human-readable approach to representing these objects.
Here's one such technique: We use a file to store the drawing
objects in an image. Each line of the file represents one object.
A line begins with the name of the object, such
as "filled ellipse", "empty circle",
"line",
or "filled square". The remaining values on the line depend
on the kind of object.
empty ellipse, which is stroked, is followed
by the color, the brush, the left edge, the top edge, the
width, and the height of the ellipse.
filled ellipse, which is filled, is followed by the
color, the left edge, the top edge, the width, and the height
of the ellipse.
empty circle, which is stroked, is followed by
the color, the brush, the left edge, the top edge, and
the diameter of the circle.
filled circle, which is filled, is followed by the
color, the left edge, the right edge, and the diameter
of the circle.
empty rectangle, which is stroked, is followed by the
color, the brush, the left edge, the top edge, the width, and
the height of the rectangle.
filled rectangle, which is filled, is followed by the
color, the left edge, the top edge, the width, and
the height of the rectangle.
empty square, which is stroked, is followed by the
color, the brush, the left edge, the top edge, and the side length
of the square.
filled square, which is filled, is followed by the color,
the left edge, the top edge, and the side length of the box.
line is followed by the color, the brush, the starting
column, the starting row, the ending column, and the ending
row of the line.
For example, here's a simple drawing:
"empty ellipse" "red" "Circle (03)" 10 10 80 40 "filled square" "rich blue" 30 30 80 "line" "green" "Circle Fuzzy (11)" 0 90 100 20
The first goal is to read these values from a file and draw them. Here's a start.
(define image.read-object!
(lambda (image port)
(let* ((type (read port))
(stroked? (list.contains?
(list "empty ellipse" "empty circle"
"empty rectangle" "empty square"
"line")
type))
(color (read port))
(brush (if stroked? (read port) (envt.get-brush))))
(cond
((list.contains? (list "empty ellipse" "filled ellipse") type)
(let* ((left (read port))
(top (read port))
(width (read port))
(height (read port)))
(image.select-ellipse! image
selection.replace
left top width height)
(if stroked?
(image.stroke! image)
(image.fill! image))
(image.select-nothing! image)))
((list.contains? (list "empty square" "filled square") type)
(let* ((left (read port))
(top (read port))
(side (read port)))
(image.select-rectangle! image
selection.replace
left top side side)
(if stroked?
(image.stroke! image)
(image.fill! image))
(image.select-nothing! image)))
((equal? type "line")
(let* ((start-col (read port))
(start-row (read port))
(end-col (read port))
(end-row (read port)))
(image.draw-line! image start-col start-row end-col end-row)))))))You can find the helper procedures at the end of this assignment.
a. Right now, image.read-object! reads the
color to use and the brush to use but then ignores both. Update
the procedure so that it sets the brush and color before drawing.
b. Right now, image.read-object! only does about
half of the desired shapes. Extend it to do the other shapes.
c. Write a procedure, (image.load-objects! image filename),
that reads and renders every object in the named file.
d. Write procedures that let us write each kind of object from Scheme. For example,
(define empty-rectangle.write
(lambda (port color brush left top width height)
(write "empty rectangle" port)
(display " " port)
(write (if (rgb? color) (rgb->cname color) color) port)
(display " " port)
(write brush port)
(display " " port)
(write left port)
(display " " port)
(write top port)
(display " " port)
(write width port)
(display " " port)
(write height port)
(newline port)))
We will evaluate your assignment primarily on its correctness: Does it correctly read and write these kinds of values. However, since this program can be written with very repetitious code, we will also look to ways to avoid repetition. (You'll note that the sample code avoids some repetition by doing only one selection for related object. However, it also repeats some code. Can you do better?)
You are likely to find the following procedures useful.
(define list.contains?
(lambda (lst val)
(and (not (null? lst))
(or (equal? (car lst) val)
(list.contains? (cdr lst) val)))))
Primary: [Front Door] [Glance] - [Academic Honesty] [Instructions]
Current: [Outline] [EBoard] [Reading] [Lab] [Assignment]
Groupings: [Assignments] [EBoards] [Examples] [Exams] [Handouts] [Labs] [Outlines] [Projects] [Readings] [Reference]
Reference: [Scheme Report (R5RS)] [Scheme Reference] [DrScheme Manual]
Related Courses: [CSC151.01 2007F (Davis)] [CSC151 2007S (Rebelsky)] [CSCS151 2005S (Stone)]
Copyright © 2007 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.