<< . .

. 29
( : 45)



. . >>



0.65 while luxo mode has blacker = 0.1 (since the luxo printer has di¬erent physi- Tobin
cal characteristics). Similarly, de¬ne corrected pixels (which we are just about to
discuss) will produce slightly di¬erent results in the two given modes.

11.2. Increasing ht # would make the letter shape and the bounding box taller;
increasing xgap # would move point 5 to the left, thereby making the middle bar shorter;
increasing u# would make the shape and its bounding box wider; increasing s# would
widen the bounding box at both sides without changing the letter shape; increasing o#
would move points 4, 5, and 6 to the right; increasing px # would make the pen thicker
(preserving the top edge of the upper bar, the bottom edge of the lower bar, and the
center of the middle bar and the stem).

11.3. The only possible surprise is the position of y1 , which should match similar
details in the ˜ ™ and the ˜ ™ of Chapter 4:
beginchar("F",14*u#+2s#,ht#,0); pickup logo_pen;
x1=x2=x3=leftstemloc; x4=w-x1+o; x5=x4-xgap;
y2=y5; y3=y4; bot y1=-o; top y3=h; y2=barheight;
draw z1--z3--z4; draw z2--z5;
labels(1,2,3,4,5); endchar;

11.4. The quantity called ss in Chapter 4 is now leftstemloc .
beginchar("M",18*u#+2s#,ht#,0); pickup logo_pen;
x1=x2=leftstemloc; x4=x5=w-x1; x3=w-x3;
y1=y5; y2=y4; bot y1=-o; top y2=h+o; y3=y1+ygap;
draw z1--z2--z3--z4--z5;
labels(1,2,3,4,5); endchar;
beginchar("T",13*u#+2s#,ht#,0); pickup logo_pen;
lft x1=0; x2=w-x1; x3=x4=.5w;
y1=y2=y3; top y1=h; bot y4=-o;
draw z1--z2; draw z3--z4;
labels(1,2,3,4); endchar;

11.5. ˜ ™; possibly also ˜ ™; and Georgia Tobin sug-
gests that ˜ ™ might be a legal term.

11.6. Delete the line of logo.mf that de¬nes barheight#, and insert that line into
each of the parameter ¬les logo10.mf, logo9.mf, logo8.mf. Then other bar-line heights
are possible by providing new parameter ¬les; another degree of “meta-ness” has there-
fore been added to the meta-font.

11.7. (This is tricky.) Insert the lines
if known pixmag: begingroup interim hppp:=pixmag*hppp;
special "title cheapo simulation" endgroup;
extra_endchar:="currentpicture:=currentpicture scaled pixmag;"
& "w:=w*pixmag;" & extra_endchar; fi

right after ˜mode_setup™ in logo.mf, and also include the line

if known pixmag: hppp:=pixmag*hppp; vppp:=pixmag*vppp; fi
Appendix A: Answers to All the Exercises 241


at the very end of that ¬le. Then run with special
gf
\mode="cheapo"; input cheaplogo10
where the ¬le ˜cheaplogo10.mf™ says simply ˜pixmag=10; input logo10™. (The interim
hppp setting and the special command are used to fool into giving the
appropriate extension to the gf ¬le name. Incidentally, you could print with this font on
cheapo at ten-fold magni¬cation if you told TEX to use the font ˜cheaplogo10 scaled
10000™; but on luxo you would simply call this font ˜cheaplogo10™.)
12.1. The changes are straightforward, except for the italic correction (for which a
rough estimate like the one shown here is good enough):
"Right parenthesis";
numeric ht #, dp #; ht # = body height #; .5[ht #, ’dp #] = axis #;
beginchar (")", 7u#, ht #, dp #); italcorr axis # — slant ’ .5u#;
pickup ¬ne.nib ; penpos1 (hair ’ ¬ne , 0);
penpos2 (.75[thin , thick ] ’ ¬ne , 0); penpos3 (hair ’ ¬ne , 0);
lft x1l = lft x3l = u; rt x2r = x1 + 4u; top y1 = h; y2 = .5[y1 , y3 ] = axis ;
¬lldraw z1l {(z2l ’ z1l ) xscaled 3} . . . z2l . . . {(z3l ’ z2l ) xscaled 3}z3l
- - z3r {(z2r ’ z3r ) xscaled 3} . . . z2r . . . {(z1r ’ z2r ) xscaled 3}z1r - - cycle;
penlabels(1, 2, 3); endchar;
We will see in Chapter 15 that it™s possible to guarantee perfect symmetry between left
and right parentheses by using picture transformations.
12.2. When horizontal lines are being typeset, TEX keeps track of the maximum
height and maximum depth of all boxes on the line; this determines whether or not
extra space is needed between baselines. The height and depth are also used to position
an accent above or below a character, and to place symbols in mathematical formulas.
Sometimes boxes are also stacked up vertically, in which case their heights and depths
are just as important as their widths are for horizontal setting.
13.1. (4, 4), (4, 5), (5, 5), (5, 4). (Therefore the command
un¬ll (4, 4) - - (4, 5) - - (5, 5) - - (5, 4) - - cycle
will decrease the value of this pixel by 1.)
13.2. The result would be exactly the same; ¬ll and un¬ll commands can be given
in any order. (After an initial un¬ll command, some pixel values will be ’1, the
others will be zero.)
13.3. un¬ll (4, 1) - - (4, 8) - - (5, 8) - - (5, 1) - - cycle.
13.4. Here are two of the many solutions:
¬ll (0, 3) - - (9, 3) - - (9, 6) - - (6, 6) - - (6, 9) - -
(3, 9) - - (3, 0) - - (6, 0) - - (6, 6) - - (0, 6) - - cycle;
¬ll (0, 3) - - (9, 3) - - (9, 6) - - (0, 6) - - (0, 3) - -
(3, 3) - - (3, 0) - - (6, 0) - - (6, 9) - - (3, 9) - - (3, 3) - - cycle.
(It turns out that any pixel pattern can be obtained by a single, su¬ciently hairy ¬ll
command. But unnatural commands are usually also ine¬cient and unreadable.)
242 Appendix A: Answers to All the Exercises


13.5. The value of the enclosed pixel is increased by 2. (We™ll see later that there™s cullit
undraw
a simpler way to do this.)
withpen
clearit
13.6. True; j ’ k = l ’ m, since k + l = j + m. (What comes up must go down.) withpen
addto
13.7. The tricky part is to remember that ˜erase draw zi - - zj ™ will erase pixels withweight
undraw
near zi and zj . Therefore if z3 - - z4 is drawn before z4 - - z2 , we can™t erase z4 - - z2
cullit
without losing some of z3 - - z4 ; it™s necessary to erase only part of one line. One way undraw
Leban
to solve the problem is to do the following, after de¬ning the points and picking up the
pen as before:

draw z3 - - z4 ; draw z5 - - z6 ;
cullit; pickup pencircle scaled 1.6pt ;
undraw z7 - - 1 [z7 , z5 ]; undraw z2 - - 1 [z2 , z4 ];
2 2
cullit; pickup pencircle scaled .4pt ;
draw z3 - - z1 - - z2 - - z4 ; draw z5 - - z7 - - z8 - - z6 ;
for k = 1 upto 4: draw zk - - zk+4 ; endfor.

(Note that it would not be quite enough to erase only from z7 to 1 [z7 , z5 ]!)
3
It™s also possible to solve this problem without partial erasing, if we use addi-
tional features of that haven™t been explained yet. Let™s consider only the
job of drawing z7 - - z5 - - z6 and z3 - - z4 - - z2 , since the other eight lines can easily be
added later. Alternative Solution 1 uses picture operations:

pen eraser ; eraser = pencircle scaled 1.6pt ;
draw z3 - - z4 ; erase draw z7 - - z5 withpen eraser ; draw z7 - - z5 ;
picture savedpicture ; savedpicture = currentpicture ; clearit;
draw z6 - - z5 ; erase draw z2 - - z4 withpen eraser ; draw z2 - - z4 ;
addto currentpicture also savedpicture .

Alternative Solution 2 is trickier, but still instructive; it uses ˜withweight™ options and
the fact that draw does not increase any pixel values by more than the stated weight
when the path is a straight line:

- - z4 ; undraw z7 - - z5 withpen eraser ;
draw z3
draw z7 - - z5 withweight 2; cullit withweight 2;
- - z5 ; undraw z2 - - z4 withpen eraser ;
draw z6
draw z2 - - z4 withweight 2;

(These alternative solutions were suggested by Bruce Leban.)

13.8. Here™s an analog of the ¬rst solution to the previous exercise:

beginchar ("*", 10pt #, 7pt #, 2pt #);
pair center ; . . . as in the hint
pickup pencircle scaled .4pt ; draw star ;
cullit; pickup pencircle scaled 1.6pt ;
for k = 0 upto 4: undraw subpath(k + .55, k + .7) of star ; endfor
cullit; pickup pencircle scaled .4pt ;
for k = 0 upto 4: draw subpath(k + .47, k + .8) of star ; endfor
labels(0,1,2,3,4); endchar.
Appendix A: Answers to All the Exercises 243


However, as in the previous case, there™s an Alternate Solution 1 by Bruce Leban that Leban
overdraw
is preferable because it doesn™t depend on magic constants like .55 and .47:
begingroup
interim
beginchar . . . as above . . . scaled .4pt ; addto
picture savedpicture ; savedpicture = nullpicture; cull
cullit
pen eraser ; eraser := pencircle scaled 1.6pt ; also
for k = 0 upto 4: endgroup
origin
draw subpath(k, k + 1) of star ; cullit;
undraw subpath(k + 3, k + 4) of star withpen eraser ; cullit;
addto savedpicture also currentpicture ; clearit; endfor
currentpicture := savedpicture ; labels(0,1,2,3,4); endchar.

13.9. It increases pixel values by 1 in the ¬ve lobes of the star, and by 2 in the
central pentagon-like region.

13.10. def overdraw expr c = erase ¬ll c; draw c enddef .

13.11. First we need to generalize the overdraw macro of the previous exercise so
that it applies to arbitrary cycles c, even those that are self-intersecting:

def overdraw expr c = begingroup
picture region ; region := nullpicture;
interim turningcheck := 0; addto region contour c;
cull region dropping (0, 0);
cullit; addto currentpicture also ’region ; cullit;
draw c endgroup enddef ;

(This code uses operations de¬ned later in this chapter; it erases the region of pixels
that would be made nonzero by the command ˜¬ll c™.) The watchband is now formed
by overdrawing its links, one at a time, doing ¬rst the ones that are underneath:

beginchar(M , 1.25in #, .5in #, 0); pickup pencircle scaled .4pt ;
z1 = (20, ’13); z2 = (30, ’6); z3 = (20, 1); z4 = (4, ’7);
z5 = (’12, ’13); z6 = (’24, ’4); z7 = (’15, 6);
path M ; M = (origin . . z1 . . z2 . . z3 . . z4 . . z5 . . z6 . . z7 . .
origin . . ’z7 . . ’z6 . . ’z5 . . ’z4 . . ’z3 . . ’z2 . . ’z1 . . cycle)
scaled (h/26) shifted (.5w, .5h);
def link(expr n) =
overdraw subpath 1 (n, n + 1) of M - -
3
subpath 1 (n + 25, n + 24) of M - - cycle enddef ;
3
for k = 1 upto 12: link(k + 11); link(12 ’ k); endfor endchar;

13.12. The pixel pattern 1 1 is culled to 11, and needs to sort the edges
21 11
as it does this; so the result is simply
row 1: | 0+ 2-
row 0: | 0+ 2-

13.13. The pixel pattern is 1 1 + 1 1 + 1 1 ’ 2 1 = 1 2 before the ¬nal rotation, with
21 21 12 11 43
the reference point at the lower left corner of the 4; after rotation it is 2 3 , with the
14
reference point at the lower right corner of the 4. Rotation causes to sort
244 Appendix A: Answers to All the Exercises


the edges, but the transition values per edge are never more than ±3. You weren™t xscaled-1
expected to know about this limit of ±3, but it accounts for what is actually reported: yscaled-1
save
interim
row 1: | -2++ -1+ 0---
turningcheck
row 0: | -2+ -1+++ 0--- 0-

13.14. ˜V scaled-1™ should be the same as ˜V rotated 180™, because transformations
apply to coordinates rather than to pixel values. (Note, incidentally, that the re¬‚ections
˜V xscaled-1™ and ˜V yscaled-1™ both work, and that ˜V scaled-1™ is the same as
˜V xscaled-1 yscaled-1™.)
13.15. The result is the same as ˜V shifted (2,3)™; the coordinates of a shift are
rounded to the nearest integers when a picture is being shifted.
13.16. row 3: 0+ 4- |
row 2: 0+ 4- |
row 1: 0+ 4- 0+ 2- |
row 0: 0+ 4- 0+ 2- |
(Scaling of pictures must be by an integer.)
13.17. is currently executing instructions after having read as far as line 5
of the ¬le expr.mf.
13.18. The pixel values of currentpicture become 1 if they were ±1, otherwise they
become 0.
13.19. (a) addto V1 also V2 ; cull V1 keeping (2, 2). (b) Same, but cull keeping
(1, 2). (c) Same, but cull keeping (1, 1).
13.20. Subtract one from the other, and cull the result dropping (0, 0); then test to
see if the total weight is zero.
13.21. (a) Same as ˜draw p™, but using q instead of the currently-picked-up pen.
(b) Same e¬ect as ˜draw p; draw p; draw p™ (but faster). (c) Same as ˜draw p
withweight w™, because undraw™s ˜withweight ’1™ is overridden. (d) Same as
˜un¬lldraw c; un¬lldraw c™, but using q instead of currentpen . (e) Same as ˜erase
¬lldraw c™, because the ˜withweight 2™ is overridden. [Since erase has culled all
weights to 0 or 1, there™s no need to “doubly erase.”] (f) Same e¬ect as ˜cullit; addto
currentpicture also currentpicture ™ (but faster).
13.22. vardef safe¬ll expr c = save region ;
picture region ; region =nullpicture;
interim turningcheck := 0;
addto region contour c; cull region dropping (0, 0);
addto currentpicture also region enddef .
13.23. cull currentpicture keeping (1, in¬nity );
picture v; v := currentpicture ;
cull currentpicture keeping (1, 1) withweight 3;
addto currentpicture also v ’ v shifted right
’ v shifted left ’ v shifted up ’ v shifted down ;
cull currentpicture keeping (1, 4).
Appendix A: Answers to All the Exercises 245


13.24. (We assume that currentpicture initially has some con¬guration in which all directiontime
pixel values are zero or one; one means “alive.”)
picture v; def c = currentpicture enddef ;
forever: v := c; showit;
addto c also c shifted left + c shifted right ;
addto c also c shifted up + c shifted down ;
addto c also c ’ v; cull c keeping (5, 7); endfor.
(It is wise not to waste too much computer time watching this program.)
14.1. beginchar ("b", 5pt #, 5pt #, 0);
¬ll ((0, 0) - - quartercircle - - cycle) scaled 10pt ; endchar.
1
14.2. A quartercircle corresponds to a circle whose diameter is 1; the radius is .
2

14.3. beginchar ("c", 5pt #, 5pt #, 0);
pickup pencircle scaled (.4pt + blacker );
draw quartercircle rotated 90 scaled 10pt shifted (5pt , 0); endchar.
14.4. beginchar ("d", 5pt # — sqrt 2, 5pt #, 0);
pickup pencircle scaled (.4pt + blacker );
draw ((0, 0) - - quartercircle - - cycle) rotated 45 scaled 10pt shifted (.5w, 0);
endchar.
14.5. beginchar ("e", 10pt #, 7.5pt #, 2.5pt #);
pickup pencircle scaled (.4pt + blacker );
for D = .2w, .6w, w: draw fullcircle scaled D shifted (.5w, .5[’d, h]);
endfor endchar.
The program for ˜ ™ is similar, but ˜fullcircle scaled D™ is replaced by
unitsquare shifted ’(.5, .5) rotated 45 scaled (D/ sqrt 2).

14.6. There are in¬‚ection points, because there are no bounding triangles for the
˜. . .™ operations in the superellipse macro of Appendix B, unless .5 ¤ s ¤ 1.
14.7. (0, 0) . . (1, 0) & (1, 0) . . (1, 1) & (1, 1) . . (0, 1) & (0, 1) . . (0, 0) & cycle.
Incidentally, if each ˜&™ in this path is changed to ˜. .™, we get a path that goes through
the same points; but it is a path of length 8 that comes to a complete stop at each
corner. In other words, the path remains motionless between times 1 ¤ t ¤ 2, 3 ¤ t ¤ 4,
etc. This length-8 path therefore behaves somewhat strangely with respect to the
˜directiontime™ operation. It™s better to use ˜&™ than to repeat points of a path.
14.8. Let δ1 = z1 ’ z0 , δ2 = z2 ’ z1 , δ3 = z0 ’ z2 ; l1 = |δ1 |, l2 = |δ2 |, l3 = |δ3 |;
ψ1 = arg(δ2 /δ1 ), ψ2 = arg(δ3 /δ2 ), ψ3 = arg(δ1 /δ3 ). The equations to be solved are (—)
and (——) for 1 ¤ k ¤ 3, where ±3 = ±0 and β4 = β1 . These six equations determine
θ1 , θ2 , θ3 and φ1 , φ2 , φ3 .
14.9. The path is of length 9, and it is equivalent to ˜(0, 1) - - (1, 1) - - (1, 2) - -
(0, 2) - - (0, 1){down } . . {right }(1, 0) - - (2, 0) - - (2, 1) - - (1, 1) - - (1, 0)™. Although
unitsquare is a cycle, the cycle is broken when it is used inside a larger path; the
resulting non-cyclic square path goes down when it ends and right when it begins.
246 Appendix A: Answers to All the Exercises


14.10. Yes; for example, ˜z0 . . z1 . . z2 - - z3 ™ would be equivalent to ˜z0 . . z1 . . Bernshte˜
±n
{curl 2}z2 {curl 2} . . {curl 2}z3 ™. But a path like z0 - - z1 - - z2 - - z3 would not be
a¬ected, because all directions would turn out to be the same as before. (The path
˜z0 {curl a} . . {curl b}z1 ™ is a straight line regardless of the values of a and b, because
equations (———) and (——— ) always have the solution θ0 = φ1 = 0 when n = 1.)
14.11. It treats this as ˜((0, 0) . . (3, 3) . . cycle){curl 1}™; i.e., the part up to and
including ˜cycle™ is treated as a subpath (cf. ˜p2™ in Chapter 8). The cycle is broken, after
which we have ˜(0, 0) . . controls (2, ’2) and (5, 1) . . (3, 3) . . controls (1, 5) and (’2, 2) . .
(0, 0){curl 1}™. Finally the ˜{curl 1}™ is dropped, because all control points are known.
(The syntax by itself isn™t really enough to answer this question, as you probably
realize. You also need to be told that the computation of directions and control points
is performed whenever uses the second or third alternative in the de¬nition
of path expression .)
14.12. True. The length of a path is the number of ˜zk . . controls uk and vk+1 . . zk+1 ™
segments that it contains, after all control points have been chosen.
14.13. True if 0 ¤ t ¤ 1, except perhaps for rounding errors; otherwise false. The
path z0 - - z1 expands into ˜z0 . . controls 1/3[z0 , z1 ] and 2/3[z0 , z1 ] . . z1 ™, and the
Bernshte˜ polynomial simpli¬es because t[w, w + δ, w + 2δ, w + 3δ] = w + 3tδ. In-
±n
cidentally, ˜point t of (z0 - - - z1 )™ is usually quite di¬erent from t[z0 , z1 ].
14.14. If p is a cycle, or if p is a path of length ≥ 4, the stated subpath has length 2.
Otherwise the length is max(0, length p ’ 2).
14.15. vardef posttension expr t of p =
save q; path q;
q = point t of p {direction t of p} . . {direction t + 1 of p} point t + 1 of p;
length(postcontrol 0 of q ’ point 0 of q)
/length(postcontrol t of p ’ point t of p) enddef ;
vardef pretension expr t of p =
save q; path q;
q = point t ’ 1 of p {direction t ’ 1 of p} . . {direction t of p} point t of p;
length(precontrol 1 of q ’ point 1 of q)
/length(precontrol t of p ’ point t of p) enddef ;
The stated posttension turns out to be 4.54019.
14.16. The ˜&™ had to be changed to ˜. .™, because point t of p might not be exactly
equal to point u of q.
14.17. Since p intersects itself in¬nitely often at times (t, t), the task may seem im-
possible; but ™s shu¬„ed-binary search procedure provides a way. Namely,
p intersectiontimes reverse p = (0.17227, 0.28339), from which we can deduce that
t = 0.17227 and 1 ’ u = 0.28339.
15.1. (x,-y).
15.2. (x, y) rotated 180, or (x, y) scaled ’1.
15.3. True if and only if xpart t = ypart t = 0. If the stated equation holds for
at least one pair (x, y), it holds for all (x, y). According to the syntax of Chapter 8,
Appendix A: Answers to All the Exercises 247


interprets ˜’(x, y) transformed t™ as (’(x, y)) transformed t. (Inciden- a¬ne transformations
homogeneous
tally, mathematicians call ™s transformers “a¬ne transformations,” and the
parentheses
special case in which the xpart and ypart are zero is called “homogeneous.”) makepath
¬llin
15.4. z1 + z2 . commutativity
capsule
15.5. beginchar(126, 25u#, hheight # + border #, 0); "Dangerous left bend";
currentpicture := dbend re¬‚ectedabout ((.5w, 0), (.5w, h)); endchar;

The same idea can be used to create right parentheses as perfect mirror images of left
parentheses, etc., if the parentheses aren™t slanted.

15.6. Change line 9 to

draw (z1 . . . p) rotatedaround((.5w, .5h), ’45)
withpen pencircle scaled 3/4pt yscaled 1/3 rotated ’15;

15.7. Replace line 10 by

pickup pencircle scaled 3/4pt yscaled 1/3 rotated ’60;
draw (z1 . . . p) transformed t;

16.1. If there are two points zk and zk+1 with maximum y coordinate, the value of
˜peno¬set (’in¬nity , epsilon ) of p™ will be zk and ˜peno¬set (’in¬nity , ’epsilon ) of p™
will be zk+1 ; ˜peno¬set left of p™ will be one or the other. If there™s only one top point,
all three of these formulas will produce it. (Actually also allows pens to
be made with three or more vertices in a straight line. If there are more than two top
vertices, you can use peno¬set to discover the ¬rst and the last, as above; furthermore,
if you really want to ¬nd them all, makepath will produce a path from which they
can be deduced in a straightforward manner.)

16.2. ˜pencircle scaled 1.06060™ is the diamond but ˜pencircle scaled 1.06061™
is the square. (This assumes that ¬llin = 0. If, for example, ¬llin = .1, the change
doesn™t occur until the diameter is 1.20204.) The next change is at diameter 1.5, which
gives a diamond twice the size of the ¬rst.

17.1. (a + 1) + (2a + 2) = 3a + 3 and (2a) + (2a + 1) = 4a + 1, respectively. The
¬nal value of x in the ¬rst case is 2a + 2, hence a = .5x ’ 1; expr will report the answer
as 1.5x (in terms of x™s new value), since it has not been told about ˜a™. In the second
case expr will, similarly, say 2x-1.
This example shows that ± + β is not necessarily equal to β + ±, when ± and β
involve group expressions. evaluates expressions strictly from left to right,
performing the statements within groups as they appear.

<< . .

. 29
( : 45)



. . >>