Unit 20

twenty
high-level operations on pictures
Recap: vector graphics constructors




[box width height]
Creates a picture with a box
[group pictures …]
Makes a compound picture from existing pictures
[translate point pictures …]
A new picture with all pictures shifted by point
[scale size-or-point pictures …]
A new picture with all pictures grown/shrunk/stretched




If size-or-point is an integer, picture is uniformly grown/shrunk
If size-or-point is a point, the pictures are stretched horizontally by the
point’s X coordinate, and vertically by its Y coordinate
[paint color pictures …]
Renders pictures filled with color
[ink brush pictures …]
Renders pictures outlined with brush
New: vector graphics accessors

The bounding box of a picture is the smallest
(unrotated) box that completely encloses the
picture

[left-edge picture]
[right-edge picture]
[top-edge picture]
[bottom-edge picture]



Returns the X coordinate of the left/right edge of
picture’s bounding box
Returns the Y coordinate of the top/bottom edge of
picture’s bounding box
[width picture]
[height picture]


objects in picture
The width/height in pixels of picture’s bounding box
[center picture]

The center point of picture’s bounding box
bounding box
Stacking boxes

How do we write a procedure to
stack one picture on top of another?
[stack-top [box 40 40]
[box 100 100]

[define stack-top
[top base →
[group base
[translate [point 0
[− [top-edge base]
[bottom-edge top]]]
top]]]]
Stacking boxes

How do we do the reverse
[stack-bottom [box 40 40]
[box 100 100]

[define stack-bottom
[bottom base →
[group base
[translate [point 0
[− [bottom-edge base]
[top-edge bottom]]]
top]]]]
Handling variable numbers of objects

How do we make it handle more than
two arguments?
[stack [box 10 10]
[box 20 20]
[box 30 30]]

[define stack
[pictures … →
[fold stack-top
[group]
«an empty group»
pictures]]]
Stacking horizontally

[define stack-right
[base right →
[group base
[translate [point [− [right-edge base]
[left-edge right]]]
right]]]]

[define splay
[pictures … →
[fold stack-right
[group]
pictures]]]
Fixing the position of an object

Stack-top, etc. all leave the object in the
coordinate system of the base



So unlike box, they don’t return a picture centered
around the origin
How do we recenter an existing picture around the
origin?
[define recenter
[picture →
[translate [− [center picture]]
picture]]]
Prairie School stained glass patterns

Frank Lloyd Wright


Designs emphasized
strong horizontals and
verticals
Common motifs



Deformed grids
Symmetry (vertical
and horizontal)
Repeated patterns
Making deformed grids

We’d like to be able to
express this picture
simply and clearly


Without having to write 35
calls to box
We’ll start by just trying to
get the leading (the black
lines) right, without
worrying about color
Making the leading

The design consists
of almost identical
rows of boxes



Each row is a fixed
design
But the height varies
from row to row
Start by writing code
to make one row
Making the top row of boxes

[define top-row
[splay [box 10 10]
[box 10 10]
[box 15 10]
[box 60 10]
[box 15 10]
[box 10 10]
[box 10 10]]]
Making an arbitrary row

[define row
[height →
[splay [box 10 height]
[box 10 height]
[box 15 height]
[box 60 height]
[box 15 height]
[box 10 height]
[box 10 height]]]]
Making the leading

[stack [row 10]
[row 15]
[row 190]
[row 15]
[row 10]]
What’s wrong with this?

[splay [row 10]
[row 15]
[row 190]
[row 15]
[row 10]]

If we want to change the design we
have to redefine row
We’d like to have a procedure that



Takes the widths and heights of the
rows and columns as arguments
And makes the picture
Making the heights be a parameter
How do we change:
 [splay [row 10]
[row 15]
[row 190]
[row 15]
[row 10]]
into just:
 [leading [list 10 15 190 15 10]] ?
Making the heights be a parameter

[define leading
[heights →
[splay
[map row
heights]]]]

Well, almost:


Generates ArgumentTypeException
What’s wrong?


Splay wants to take several pictures as
arguments
Now one list of pictures
Fixing the bug


How do we fix it?
[define leading
[heights →
[apply splay
[map row
heights]]]]
Making the heights be a parameter

Okay, what should we change next?

We still need to redefine row any time we
want to change the design

How do we change it so we can just say:
[leading
[list 10 10 15 60 15 10 10]
[list 10 15 190 15 10]]
i.e. so we can pass it both the widths and
the heights as arguments?
Making the widths be a parameter

Now the width need to be an
argument to row

[define leading
[widths heights →
[apply splay
[map [height →
[row widths height]]
heights]]]]
Fixing the row procedure

This time, row will take as arguments





A list of widths
A single height
It needs to make a box for each width
And splay all the boxen together
[define row
[widths height →
[apply splay
[map [width →
[box width height]]
widths]]]]
Live hacking exercise

Okay, now we have the leading


But no color
How do we specify the colors for each of the
boxes?


Big list of colors
Procedure to compute color for each box


But what are the arguments to the procedure?
Width and height?



But what if we have identically sized boxes with
different colors?
Position?

In x, y coordinates?

Or in grid position?
A new procedure will be useful

[up-to n proc] returns (as a list) the values of
proc when called on the numbers [0 1 2 … n-1]