3 SICP Picture Language
(require sicp-pict) | package: sicp |
3.1 Introduction
The SICP Picture Language is a small language for drawing pictures. It shows the power of data abstraction and closure. The picture language stems from Peter Henderson’s 1982 paper "Functional Geometry" and was included by Hal Abelson in "Structure and Interpretation of Computer Programs".
The basic concept of the picture language is a painter, which draws its image (shifted and scaled) within a frame given by a parallelogram. Painters can be combined to construct new painters.
Before using this package, read section 2.2.4 of SICP, which is an excellent introduction to the ideas of the picture language. This manual is meant as a reference guide.
Peter Henderson has written an updated version of Functional Geometry, which explains how to construct the Escher fish image.
3.2 Example
Using sicp-pict from a #lang sicp program:
#lang sicp (#%require sicp-pict) (paint einstein)
Using sicp-pict from a #lang racket program:
#lang racket (require sicp-pict) (paint einstein)
From the REPL:
> (require sicp-pict) > (paint (number->painter 0)) > (paint diagonal-shading) > (paint (below (beside diagonal-shading (rotate90 diagonal-shading)) (beside (rotate270 diagonal-shading) (rotate180 diagonal-shading)))) > (paint einstein)
3.3 Vectors
A mathematical vector is called a vect here, in order to avoid confusion with the builtin vectors of Scheme.
procedure
(vector-xcor v) → real?
v : vect?
procedure
(vector-ycor v) → real?
v : vect?
procedure
(vector-add v w) → vect?
v : vect? w : vect?
procedure
(vector-sub v w) → vect?
v : vect? w : vect?
procedure
(vector-scale s v) → vect?
s : real? v : vect?
value
3.4 Frames
^ |
| frame edge2 vector |
| |
_|__________> |
/| frame edge1 vector |
/ |
/ |
/ frame origin pointer |
procedure
(make-frame origin edge1 edge2) → frame?
origin : vect? edge1 : vect? edge2 : vect?
procedure
(frame-origin f) → vect?
f : frame?
procedure
(frame-edge1 f) → vect?
f : frame?
procedure
(frame-edge2 f) → vect?
f : frame?
procedure
(make-relative-frame origin corner1 corner2)
→ (frame? . -> . frame?) origin : vect? corner1 : vect? corner2 : vect?
procedure
(frame-coord-map f) → (vect? . -> . vect?)
f : frame?
The frame coordinate map is returned by frame-coord-map. E.g. these expression return the same value:
((frame-coord-map a-frame) (make-vect 0 0))
(frame-origin a-frame)
3.5 Segments
A pair of vects determines a directed line segment (or simply a segment) which runs from the endpoint of the first vect to the endpoint of the second vect.
procedure
(make-segment from to) → segment?
from : vect? to : vect?
procedure
(segment-start s) → vect?
s : segment?
procedure
(segment-end s) → vect?
s : segment?
procedure
(vects->segments lov) → (listof segment?)
lov : (sequence/c vect?)
> (vects->segments (list (make-vect 1 2) (make-vect 3 4) (make-vect 5 6) (make-vect 7 8)))
(list
(segment (vect 1 2) (vect 3 4))
(segment (vect 3 4) (vect 5 6))
(segment (vect 5 6) (vect 7 8)))
3.6 Primitive Painters
Painters take a frame and draw an image, transformed to fit inside the frame.
Note that our implementation doesn’t have a concept of pictures, so picture->painter which is commonly found in other implementations doesn’t exist in our implementation. If you wish to load an image file, use bitmap->painter.
procedure
(number->painter color) → painter/c
color : (and/c natural-number/c (<=/c 255))
procedure
(color->painter color) → painter/c
color : (is-a?/c color%)
procedure
(segments->painter los) → painter/c
los : (sequence/c segment?)
procedure
(vects->painter los) → painter/c
los : (sequence/c vect?)
procedure
(procedure->painter f) → painter/c
f : procedure?
Then to plot a point p in the target frame, we find the inverse image T^-1(p) of p under the transformation that maps the unit square to the target, and find the value of f at T-1(p).
procedure
(bitmap->painter bm) → painter/c
bm : (or/c path-string? (is-a?/c bitmap%))
procedure
(load-painter bm) → painter/c
bm : (or/c path-string? (is-a?/c bitmap%))
3.7 Higher Order Painters
procedure
(transform-painter origin corner1 corner2)
→ (painter/c . -> . painter/c) origin : vect? corner1 : vect? corner2 : vect?
procedure
(flip-horiz p) → painter/c
p : painter/c
3.8 Simple Built-In Painters
The following painter values are built-in:
value
value
3.9 Painting
Painting turns a painter into an image snip which can be displayed in DrRacket automatically.
procedure
(paint p [#:width width #:height height]) → (is-a?/c image-snip%)
p : painter/c width : (and/c positive? integer?) = 200 height : (and/c positive? integer?) = 200
procedure
(paint-hi-res p [ #:width width #:height height]) → (is-a?/c image-snip%) p : painter/c width : (and/c positive? integer?) = 200 height : (and/c positive? integer?) = 200
procedure
(paint-hires p [ #:width width #:height height]) → (is-a?/c image-snip%) p : painter/c width : (and/c positive? integer?) = 200 height : (and/c positive? integer?) = 200