On this page:
3.1 Introduction
3.2 Example
3.3 Vectors
vect?
make-vect
vector-xcor
vector-ycor
vector-add
vector-sub
vector-scale
zero-vector
3.4 Frames
frame?
make-frame
frame-origin
frame-edge1
frame-edge2
make-relative-frame
frame-coord-map
3.5 Segments
segment?
make-segment
segment-start
segment-end
vects->segments
3.6 Primitive Painters
painter/  c
number->painter
color->painter
segments->painter
vects->painter
procedure->painter
bitmap->painter
load-painter
3.7 Higher Order Painters
transform-painter
flip-horiz
flip-vert
rotate90
rotate180
rotate270
beside
below
above3
superpose
3.8 Simple Built-In Painters
black
white
gray
diagonal-shading
mark-of-zorro
einstein
escher
3.9 Painting
paint
paint-hi-res
paint-hires

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

(vect? v)  boolean?

  v : any/c
Returns #t if v is a vect, #f otherwise.

procedure

(make-vect x y)  vect?

  x : real?
  y : real?
Constructs a vect with the given coordinates.

procedure

(vector-xcor v)  real?

  v : vect?
Returns the x-coordinate.

procedure

(vector-ycor v)  real?

  v : vect?
Returns the y-coordinate.

procedure

(vector-add v w)  vect?

  v : vect?
  w : vect?
Adds the two vects by adding their coordinates pairwise.

procedure

(vector-sub v w)  vect?

  v : vect?
  w : vect?
Subtracts the two vects by subtracting their coordinates pairwise.

procedure

(vector-scale s v)  vect?

  s : real?
  v : vect?
Scales the vect by multiplying each coordinate of v with the number s.

An alias for (make-vect 0.0 0.0)

3.4 Frames🔗ℹ

A frame is descibed by three vectors.

    ^

    | frame edge2 vector

    |

   _|__________>

   /|         frame edge1 vector

  /

 /

/ frame origin pointer

procedure

(frame? f)  boolean?

  f : any/c
Returns #t is f is a frame, #f otherwise.

procedure

(make-frame origin edge1 edge2)  frame?

  origin : vect?
  edge1 : vect?
  edge2 : vect?
Constructs a frame from a frame origin vector and two frame edge vectors.

procedure

(frame-origin f)  vect?

  f : frame?

procedure

(frame-edge1 f)  vect?

  f : frame?

procedure

(frame-edge2 f)  vect?

  f : frame?
Extracts the origin, first edge or second edge from a frame.

procedure

(make-relative-frame origin corner1 corner2)

  (frame? . -> . frame?)
  origin : vect?
  corner1 : vect?
  corner2 : vect?
The function make-relative-frame provides a convenient way to transform frames. Given a frame and three points: origin, corner1, and corner2 (expressed in frame coordinates), it returns a new frame with those corners.

procedure

(frame-coord-map f)  (vect? . -> . vect?)

  f : frame?
Each frame determines a system of "frame coordinates" (x,y) where (0,0) is the origin of the frame, x represents the displacement along the first edge (as a fraction of the length of the edge) and y is the displacement along the second edge.

The frame coordinate map is returned by frame-coord-map. E.g. these expression return the same value:

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

(segment? s)  boolean?

  s : any/c
Returns #t if s is a segment, #f otherwise.

procedure

(make-segment from to)  segment?

  from : vect?
  to : vect?
Constructs a segment from from to to.

procedure

(segment-start s)  vect?

  s : segment?

procedure

(segment-end s)  vect?

  s : segment?
Returns the start and the end of a segment s respectively.

procedure

(vects->segments lov)  (listof segment?)

  lov : (sequence/c vect?)
Partitions consecutive vect in lov into chunks of size 2 and returns a list of segments where each segment is constructed by each chunk. If lov’s length is odd, the last element will be discarded.

Example:
> (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.

A contract that recognizes a painter. This is the same as (-> frame? any/c).

procedure

(number->painter color)  painter/c

  color : (and/c natural-number/c (<=/c 255))
Constructs a painter that fills the frame with a gray color indicated by the number. 0 is black and 255 is white.

procedure

(color->painter color)  painter/c

  color : (is-a?/c color%)
Constructs a painter that fills the frame with the given color.

procedure

(segments->painter los)  painter/c

  los : (sequence/c segment?)
Constructs a painter that draws a stick figure given by the segments (w.r.t. the unit square).

procedure

(vects->painter los)  painter/c

  los : (sequence/c vect?)
Constructs a painter that draws a stick figure given by the vects (w.r.t. the unit square).

procedure

(procedure->painter f)  painter/c

  f : procedure?
Creates painters from procedures. We assume that the procedure f is defined on the unit square.

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%))
Uses an image given by bm (either a path to the image or a bitmap object) to create a painter.

3.7 Higher Order Painters🔗ℹ

procedure

(transform-painter origin corner1 corner2)

  (painter/c . -> . painter/c)
  origin : vect?
  corner1 : vect?
  corner2 : vect?
Returns a function that takes a painter as argument and returns a painter that is just like the original painter but is on the transformed frame characterized by origin, corner1, and corner2.

procedure

(flip-horiz p)  painter/c

  p : painter/c
Returns a painter that flips the image horizontally.

procedure

(flip-vert p)  painter/c

  p : painter/c
Returns a painter that flips the image vertically.

procedure

(rotate90 p)  painter/c

  p : painter/c

procedure

(rotate180 p)  painter/c

  p : painter/c

procedure

(rotate270 p)  painter/c

  p : painter/c
Returns a painter that rotates the image.

procedure

(beside p1 p2)  painter/c

  p1 : painter/c
  p2 : painter/c
Constructs a painter that paints the images side-by-side.

procedure

(below p1 p2)  painter/c

  p1 : painter/c
  p2 : painter/c
Constructs a painter that paints the first image below the second.

procedure

(above3 p1 p2 p3)  painter/c

  p1 : painter/c
  p2 : painter/c
  p3 : painter/c
Constructs a painter that paints the images one above the other.

procedure

(superpose p1 p2)  painter/c

  p1 : painter/c
  p2 : painter/c
Constructs a painter that paints the two images on top of each other.

3.8 Simple Built-In Painters🔗ℹ

The following painter values are built-in:

value

black : painter/c

value

white : painter/c

value

gray : painter/c

Fills the frame with black (0), white (255) or gray (150).

Fills the frame with a shades of gray. The color transition goes from black in the upper left corner is black, to gray in the bottom right corner.

Draws the Mark of Zorro.

Draws an image of Einstein.

procedure

(escher)  painter/c

Draws Escher’s Square Limit.

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
Returns an image snip that contains the painter’s image with the specified width and height.

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
Aliases of paint. They are provided for compatibility with old texts.