Annotation of researchv10dc/vol2/ideal/user.ms, revision 1.1.1.1

1.1       root        1: .so ../ADM/mac
                      2: .XX ideal 79 "Ideal \(em A Picture-specification Language"
                      3: ...\" Thu May 1 10:28:25 EDT 1986
                      4: ...\"refer first
                      5: ...TR 103
                      6: ...RP 80-11272-13 11173 39199-11
                      7: ...ND December 17, 1981
                      8: .hy 14         \" set hyphenation: 2=not last lines; 4= no -xx; 8=no xx-
                      9: .ds id \f2ideal\fP
                     10: .ds [. [
                     11: .ds .] ]
                     12: .nr DV 0               \" for .P1/.P2
                     13: .de Ks
                     14: .SP
                     15: .KS
                     16: ..
                     17: .de Ke
                     18: .KE
                     19: .SP
                     20: ..
                     21: .de IS                 \" do not touch these!
                     22: .br
                     23: .nf
                     24: ..
                     25: .de IE
                     26: ..
                     27: .de Ts
                     28: .nr PS -1
                     29: .nr VS -1
                     30: .QS
                     31: ..
                     32: .de Te
                     33: .nr PS +1
                     34: .nr VS +1
                     35: .QE
                     36: ..
                     37: .EQ
                     38: delim $$
                     39: .EN
                     40: ......graphics
                     41: .TL
                     42: Ideal \(em A Picture-specification Language
                     43: .br
                     44: User and Reference Manual\(dg
                     45: .AU "MH 2C-518" 5292
                     46: Christopher J. Van Wyk
                     47: .AI
                     48: .MH
                     49: .AB
                     50: This manual describes how to use the existing implementation of \*(id,
                     51: a programming language to be used for describing
                     52: pictures.
                     53: The main use of \*(id is as a preprocessor to
                     54: .I troff ,
                     55: so that pictures and text may reside in the same
                     56: file and be typeset together.
                     57: .I Ideal
                     58: can also produce device-independent descriptions
                     59: of pictures which, for example, can be displayed through
                     60: the
                     61: .UX
                     62: system plot filters.
                     63: .AE
                     64: .FS
                     65: \(dg This is a revised version of |reference(van wyk ideal cstr).
                     66: .FE
                     67: .NH 1
                     68: Introduction
                     69: .PP
                     70: .I Ideal
                     71: is a language for describing pictures.
                     72: It is intended primarily to operate as a
                     73: preprocessor to
                     74: .I troff |reference(troff latest reference),
                     75: much like
                     76: .I eqn |reference(latest eqn),
                     77: .I tbl |reference(latest tbl)
                     78: and
                     79: .I pic |reference(latest pic).
                     80: .PP
                     81: I have explained the principles that motivate
                     82: the form of \*(id elsewhere|reference(ideal thesis)|reference(ideal acm).
                     83: This document describes how to use
                     84: the existing implementation of \*(id
                     85: and treats several examples in depth.
                     86: .Ts
                     87: Paragraphs like this that appear in smaller
                     88: type may be skipped on first reading:
                     89: they present sidelights that
                     90: may be ignored safely by beginners.
                     91: .Te
                     92: .NH 1
                     93: Overview of \*(id
                     94: .PP
                     95: To take advantage of \*(id's capabilities,
                     96: you must believe that
                     97: .ce 1
                     98: .I "complex numbers are good" .
                     99: .IP \(bu
                    100: Complex numbers have a natural correspondence
                    101: to points in the Cartesian ($x-y$) coordinate
                    102: system.
                    103: .IP \(bu
                    104: Using complex numbers obviates the need for
                    105: distinguishing between ``points'' and ``dimensions.''
                    106: .IP \(bu
                    107: Complex numbers capture readily such common
                    108: operations as translation, rotation, and
                    109: reflection in the plane.
                    110: .LP
                    111: .I Ideal
                    112: programs define pictures by means of
                    113: a system of simultaneous equations in the
                    114: significant points of the picture and
                    115: a set of drawing instructions to be
                    116: carried out with respect to those points.
                    117: .I Ideal
                    118: solves the system of equations,
                    119: then draws the picture using the points
                    120: so determined.
                    121: .PP
                    122: All variables in \*(id programs are complex
                    123: numbers, with the usual operations:
                    124: .IP \(bu
                    125: component-wise addition and subtraction:
                    126: $(a,b) ~ +- ~ (c,d) ~ = ~ (a +- c , b +- d)$
                    127: .IP \(bu
                    128: vector multiplication:
                    129: $(a,b)*(c,d) ~ = ~ (ac - bd , ad + bc)$
                    130: .IP \(bu
                    131: vector division:
                    132: $(a,b)/(c,d) ~ = ~ (ac + bd , -ad + bc)/( c sup 2 + d sup 2 )$
                    133: .IP \(bu
                    134: component manipulation:
                    135: $roman "re" ((a,b)) ~ = ~ a$,
                    136: $roman "im" ((a,b)) ~ = ~ b$,
                    137: and
                    138: $roman "conj" ((a,b)) ~ = ~ (a,-b)$
                    139: .IP \(bu
                    140: vector magnitude calculation:
                    141: $roman "abs" ((a,b)) ~ = ~ sqrt { { a sup 2 } + { b sup 2 } }$
                    142: .IP \(bu
                    143: unit vector function:
                    144: $roman "cis" ( theta ) ~ = ~ cos theta + i sin theta$
                    145: .LP
                    146: A non-standard notation that has proved useful is
                    147: $alpha [ x , y ]$, for complex $x$ and $y$,
                    148: defined by $x + alpha ( y - x )$, and
                    149: meaning ``$alpha$ of the way from $x$ to $y$.''
                    150: .PP
                    151: Scalars are treated as vectors with null imaginary component.
                    152: For example,
                    153: .CW 1
                    154: is treated as
                    155: .CW (1,0) .
                    156: .PP
                    157: The scale of the coordinate system in which \*(id
                    158: programs are written is entirely a matter
                    159: of convenience.
                    160: The \*(id processor proper
                    161: produces output in the same coordinate
                    162: system as the input.
                    163: Postprocessors (``filters'') scale this coordinate
                    164: system to make sense for the device on which the
                    165: picture is displayed.
                    166: .PP
                    167: Some of the pictures below include captions keyed
                    168: to the associated programs.
                    169: Some of the labels are not produced by the program:
                    170: I added them to help explain the picture.
                    171: Such labels are parenthesized.
                    172: For pictures and programs that have not been
                    173: labeled, you may find that labeling them yourself
                    174: helps you understand the program.
                    175: .NH 1
                    176: Elements of the \*(id Language
                    177: .PP
                    178: This section presents statements that make up the
                    179: fundamental units of \*(id programs, so the
                    180: displayed program text represents fragments of
                    181: complete programs.
                    182: Text that appears between
                    183: .CW /*
                    184: and
                    185: .CW */
                    186: is a comment.
                    187: .NH 2
                    188: Boxes
                    189: .PP
                    190: The building blocks of \*(id programs are called
                    191: .I boxes ,
                    192: which readers familiar with programming may think
                    193: of as procedures or subroutines.
                    194: In fact,
                    195: the picture drawn by an \*(id program must itself
                    196: be a box,
                    197: called
                    198: .I main ;
                    199: we suppress this extra level
                    200: of box-nesting for all of Section 3.
                    201: .NH 3
                    202: Defining Boxes
                    203: .PP
                    204: Here is a simple box
                    205: and one instance of it:
                    206: .Ks
                    207: .IS
                    208: ...libfile rect
                    209: ...width 0.5
                    210: ...colwid 8.0
                    211: main {
                    212:        put A:rect {
                    213:                ht = 0.5;
                    214:                wd = 1;
                    215:                sw = 0;
                    216:        };
                    217:        right '(sw) ' at A.sw;
                    218:        right '(nw) ' at A.nw;
                    219:        left ' (se)' at A.se;
                    220:        left ' (ne)' at A.ne;
                    221: }
                    222: .IF
                    223: .P1
                    224: rect {
                    225:        var ne, nw, se, sw,
                    226:                wd, ht;
                    227:        nw = sw + (0,1)*ht;
                    228:        ne = nw + wd;
                    229:        se = sw + wd;
                    230:        conn ne to nw to sw to se to ne;
                    231: }
                    232: .P2
                    233: .Ke
                    234: .LP
                    235: It is called
                    236: .I rect ,
                    237: has six local complex variables:
                    238: .I ne ,
                    239: .I nw ,
                    240: .I se ,
                    241: .I sw ,
                    242: .I wd ,
                    243: and
                    244: .I ht ,
                    245: three equations among these variables,
                    246: and an instruction to draw four lines.
                    247: .NH 3
                    248: Placing Boxes
                    249: .PP
                    250: To ask for an instance of
                    251: .I rect ,
                    252: we use a
                    253: .I \fIput\fP statement with a
                    254: .I "parameter section"
                    255: containing enough additional
                    256: equations that the local variables of
                    257: this instance of
                    258: .I rect
                    259: are determined uniquely.
                    260: For example, we might give the dimensions
                    261: .I ht "" (
                    262: and
                    263: .I wd )
                    264: and one of the corners
                    265: (say
                    266: .I sw ):
                    267: .Ks
                    268: .IS
                    269: ...width 0.25
                    270: main {
                    271:        put rect {
                    272:                sw = 0;
                    273:                ht = 1;
                    274:                wd = 0.5;
                    275:        };
                    276: }
                    277: .IF
                    278: .P1
                    279: put rect {
                    280:        ht = 2;
                    281:        wd = 1;
                    282:        sw = 0;
                    283: };
                    284: .P2
                    285: .Ke
                    286: Any of the following \fIput\fP statements would draw the same rectangle:
                    287: (C programmers will recognize the
                    288: .CW /*
                    289: and
                    290: .CW */
                    291: comment brackets.)
                    292: .P1
                    293: /* giving one corner, one dimension
                    294:    and a relation on the dimensions */
                    295: put rect {
                    296:        ht = 2;
                    297:        wd = 0.5*ht;
                    298:        nw = (0,2);
                    299: };
                    300: .P2
                    301: .P1
                    302: /* giving two adjacent corners
                    303:    and the perpendicular dimension */
                    304: put rect {
                    305:        nw = (0,2);
                    306:        sw = 0;
                    307:        wd = 1;
                    308: };
                    309: .P2
                    310: .P1
                    311: /* giving two diagonal corners
                    312:    and a relation on the dimensions */
                    313: put rect {
                    314:        ne = (1,2);
                    315:        sw = 0;
                    316:        wd = 0.5*ht;
                    317: };
                    318: .P2
                    319: .P1
                    320: /* giving three corners */
                    321: put rect {
                    322:        ne = (1,2);
                    323:        nw = (0,2);
                    324:        se = 1;
                    325: };
                    326: .P2
                    327: .P1
                    328: /* giving the center of a side,
                    329:    a corner, and another dimension */
                    330: put rect {
                    331:        (nw+sw)/2 = (0,1);
                    332:        nw = (0,2);
                    333:        wd = 1;
                    334: };
                    335: .P2
                    336: .LP
                    337: The \fIput\fP statement is to \*(id what a procedure
                    338: call is to a conventional programming language.
                    339: The difference is that none of the variables
                    340: of a box must be specified to be a parameter
                    341: whose value is expected in any call:
                    342: any of the box's variables may be set by the
                    343: \fIput\fP statement, and \*(id will determine the
                    344: rest by means of the equations
                    345: in the definition of the box.
                    346: This means we can give whatever
                    347: information we know about this instance of the box,
                    348: as long as it is enough to determine everything uniquely.
                    349: This mechanism is useful because we often want to
                    350: set down a rectangle by giving one of its corners,
                    351: but not necessarily the same corner each time;
                    352: in a conventional programming language, we would
                    353: need to provide a different procedure for each
                    354: corner, and the code to solve for the other
                    355: corners from it.
                    356: (Almost certainly, not all of the \fIput\fP statements
                    357: above are equally useful; but it is good to be
                    358: able to use any of them when the need arises.)
                    359: .Ts
                    360: Here is how \*(id solves the system of equations
                    361: implicit in a program:
                    362: First, all equations are placed on a queue.
                    363: Every time a box is called, the solutions
                    364: to these equations may\(emand probably will\(embe
                    365: different, so all the equations of a box
                    366: are enqueued separately for each time that
                    367: box is put.
                    368: (Of course, different copies of the equation
                    369: refer to different copies of the variable,
                    370: but \*(id keeps that straight.)
                    371: During processing, \*(id maintains two classes
                    372: of variables: dependent and independent.
                    373: Each dependent variable is represented as a
                    374: linear combination of independent variables
                    375: plus a constant term.
                    376: (Variables whose values are known are a trivial
                    377: case of dependent variables.)
                    378: All variables start out independent.
                    379: As long as there are equations on the queue, \*(id
                    380: examines the head equation:
                    381: if, after substituting for all dependent variables,
                    382: the equation is linear, \*(id determines new
                    383: information from it if possible\(emthat is, \*(id
                    384: tries to make one variable dependent
                    385: on the others, thus reducing the number of
                    386: independent variables\(emor decides
                    387: whether it is redundant or inconsistent;
                    388: if the equation remains non-linear after substitution, \*(id
                    389: adds it to the end of the queue and proceeds.
                    390: If \*(id ever goes through the whole queue without
                    391: discovering any new information, the system cannot
                    392: be solved
                    393: (by \*(id, anyway)
                    394: and \*(id complains bitterly.
                    395: If there are any independent variables left after
                    396: this processing, \*(id will complain too, because
                    397: there is no way they can become known.
                    398: .Te
                    399: .PP
                    400: The variables
                    401: .I wd
                    402: and
                    403: .I ht
                    404: above are complex numbers just like the corners,
                    405: so we can rotate the rectangle
                    406: by giving them complex non-real values:
                    407: .Ks
                    408: .IS
                    409: ...width 0.5
                    410: main {
                    411:        put rect {
                    412:                sw = 0;
                    413:                wd = (1,1)/abs((1,1));
                    414:                ht = 2*wd;
                    415:        };
                    416: }
                    417: .IF
                    418: .P1
                    419: put rect {
                    420:        sw = 0;
                    421:        wd = (1,1)/abs((1,1));
                    422:        ht = 2*wd;
                    423: };
                    424: .P2
                    425: .Ke
                    426: .LP
                    427: (The double parentheses are needed in
                    428: .CW abs((1,1))
                    429: because
                    430: .CW abs(1,1)
                    431: is parsed as a function with two arguments.)
                    432: One point about this example often confuses new users:
                    433: the vectors
                    434: .I wd
                    435: and
                    436: .I ht
                    437: point in the
                    438: .I same
                    439: direction.
                    440: It is in the definition of
                    441: .I rect
                    442: that the $ht$ vector is rotated ninety degrees
                    443: and added to the southern points to arrive
                    444: at the northern points.
                    445: Thus, if we give a
                    446: .I ht
                    447: that is perpendicular to
                    448: .I wd ,
                    449: we get a very flat rectangle.
                    450: .PP
                    451: On the other hand, the definition of
                    452: .I rect
                    453: does not assure that
                    454: .I ht
                    455: and
                    456: .I wd
                    457: will point in the same direction.
                    458: This \fIput\fP statement
                    459: draws a parallelogram:
                    460: .Ks
                    461: .IS
                    462: ...width 0.25
                    463: main {
                    464:        put rect {
                    465:                ht = 1;
                    466:                wd = (1,1)/abs((1,1));
                    467:                sw = 0;
                    468:        };
                    469: }
                    470: .IF
                    471: .P1
                    472: put rect {
                    473:        ht = 1;
                    474:        wd = (1,1)/abs((1,1));
                    475:        sw = 0;
                    476: };
                    477: .P2
                    478: .Ke
                    479: .LP
                    480: Some people who feel that
                    481: a box called
                    482: .I rect
                    483: should draw only rectangles
                    484: are disturbed by this example.
                    485: One remedy is to add another equation
                    486: to the definition of
                    487: .I rect ,
                    488: asserting that two adjacent sides
                    489: are perpendicular; \*(id will complain if this equation
                    490: is not satisfied
                    491: (although it won't stop drawing).
                    492: One such equation is
                    493: .P1
                    494: wd/abs(wd) = ht/abs(ht);
                    495: .P2
                    496: .PP
                    497: Here is a definition for box
                    498: .I arrow
                    499: that keeps the head of the arrow symmetrical
                    500: about its shaft:
                    501: .Ks
                    502: .IS
                    503: arrow {
                    504:        var hd, tl, head, wing;
                    505:        head = 0.2;
                    506:        wing = head*(tl-hd)/abs(tl-hd);
                    507:        conn hd to tl;
                    508:        conn hd + cis(25)*wing to hd to hd + cis(-25)*wing;
                    509: }
                    510: main {
                    511:        put arrow {
                    512:                hd = 0;
                    513:                tl = (1,1);
                    514:        };
                    515: }
                    516: .IF
                    517: .P1
                    518: arrow {
                    519:        var hd, tl, head, wing;
                    520:        head = 0.1;
                    521:        wing = head*(tl-hd)/abs(tl-hd);
                    522:        conn hd to tl;
                    523:        conn hd + cis(25)*wing to hd to hd + cis(-25)*wing;
                    524: }
                    525: .P2
                    526: .Ke
                    527: .LP
                    528: Note the definition of
                    529: .I wing
                    530: in the example above:
                    531: the second part of the expression is a unit vector
                    532: that points from
                    533: .I tl
                    534: to
                    535: .I hd ;
                    536: this is multiplied by
                    537: .I head ,
                    538: the length of the ``wings'' on the arrowhead.
                    539: .Ts
                    540: When a \fIput\fP statement is interpreted, the equations in
                    541: its parameter section are processed before
                    542: the equations in its definition.
                    543: Thus, if there are inconsistent equations
                    544: between the \fIput\fP statement
                    545: and the box definition, the equations in
                    546: the \fIput\fP statement take precedence.
                    547: This can be useful to provide
                    548: default values for variables of a box.
                    549: For instance, if the definition of
                    550: .I rect
                    551: gave such default values to
                    552: .I ht
                    553: and
                    554: .I wd ,
                    555: they would take effect unless overridden
                    556: by equations in the parameter section
                    557: of the \fIput\fP statement.
                    558: .Te
                    559: .Ts
                    560: .I Ideal
                    561: ignores inconsistent equations, but it
                    562: does generate error messages about them.
                    563: To avoid this error message
                    564: about a particular equation, use a
                    565: tilde
                    566: .CW ~
                    567: instead of an equals
                    568: sign in the equation.
                    569: The tilde does
                    570: .I not
                    571: give the equation any lower ``priority''
                    572: than an equation with an equals sign:
                    573: all it does is shut off the error message.
                    574: So, the two ordered systems
                    575: .CW "x = 1" ,
                    576: .CW "x ~ 2"
                    577: and
                    578: .CW "x ~ 2" ,
                    579: .CW "x = 1"
                    580: are
                    581: .I different .
                    582: In the former, $x$ receives the value 1, and no error
                    583: message appears when the second equation is processed;
                    584: in the latter, $x$ receives the value 2, and an error
                    585: is generated when the second equation is encountered.
                    586: .Te
                    587: .NH 2
                    588: Special Boxes\(emCircles and Arcs
                    589: .PP
                    590: Boxes to draw circles and circular arcs are defined
                    591: in special library files.
                    592: .NH 3
                    593: Circles
                    594: .PP
                    595: The box named
                    596: .I circle
                    597: has five local variables:
                    598: .I center ,
                    599: .I radius ,
                    600: .I z1 ,
                    601: .I z2 ,
                    602: and
                    603: .I z3 .
                    604: The last three may be any points on the circle.
                    605: As above, we must give enough information to
                    606: determine a circle;
                    607: giving two points on it is insufficient, and
                    608: giving three collinear points is inconsistent.
                    609: Here are three ways to draw
                    610: a circle of radius one centered at the origin.
                    611: .Ks
                    612: .IS
                    613: ...width 0.5
                    614: ...libfile circle
                    615: dot {
                    616:        var center;
                    617:        center = ZAP.center;
                    618:        put ZAP:circle {
                    619:                radius = 0.1;
                    620:        };
                    621: }
                    622: main {
                    623:        put A:circle {
                    624:                center = 0;
                    625:                radius = 1;
                    626:        };
                    627:        left ' (z1)' at cis(0);
                    628:        right '(z2) ' at cis(135);
                    629:        right '(z3)  ' at cis(245);
                    630:        put dot {center = cis(0);};
                    631:        put dot {center = cis(135);};
                    632:        put dot {center = cis(245);};
                    633: }
                    634: .IF
                    635: .P1
                    636: /* giving center and radius */
                    637: put circle {
                    638:        center = 0;
                    639:        radius = 1;
                    640: };
                    641: .P2
                    642: .Ke
                    643: .P1
                    644: /* giving center and a point on the circle */
                    645: put circle {
                    646:        center = 0;
                    647:        z1 = 1; /* could also have given z2 or z3 */
                    648: };
                    649: .P2
                    650: .P1
                    651: /* giving three points on the circle */
                    652: put circle {
                    653:        z1 = (1,0);
                    654:        z2 = cis(135);
                    655:        z3 = cis(235);
                    656: };
                    657: .P2
                    658: .LP
                    659: Once the circle has been determined, all five of its
                    660: internal variables are known.
                    661: So, if we ask for a circle giving three points, the
                    662: radius and center will be known afterward.
                    663: On the other hand, if we ask for a circle by giving
                    664: the center and the radius, the three points $z1$, $z2$,
                    665: and $z3$, will be known, and will be on the circle,
                    666: but there is no guarantee where they will be.
                    667: .NH 3
                    668: Arcs
                    669: .PP
                    670: Box
                    671: .I arc
                    672: has eight local variables:
                    673: .I center ,
                    674: .I radius ,
                    675: .I start ,
                    676: .I midway ,
                    677: .I end ,
                    678: .I startang ,
                    679: .I midang ,
                    680: and
                    681: .I endang .
                    682: It is an arc centered at point
                    683: .I center
                    684: with radius
                    685: .I radius ,
                    686: starting at point
                    687: .I start
                    688: at an angle
                    689: .I startang ,
                    690: passing through point
                    691: .I midway
                    692: at an angle
                    693: .I midang ,
                    694: and ending at point
                    695: .I end
                    696: at an angle
                    697: .I endang .
                    698: (All angles are measured with respect to $center$,
                    699: in degrees, with the positive $x$-axis taken to be
                    700: zero degrees, and the counterclockwise direction to
                    701: be positive.)
                    702: Note that $midway$ is
                    703: .I not
                    704: necessarily the midpoint of the arc!
                    705: If neither
                    706: .I midway
                    707: nor
                    708: .I midang
                    709: is given, the arc is drawn
                    710: counterclockwise from
                    711: .I start
                    712: to
                    713: .I end .
                    714: Once again, a variety of \fIput\fP statements draw the same arc:
                    715: .Ks
                    716: .IS
                    717: ...libfile arc
                    718: main {
                    719:        put A:arc {
                    720:                start = 1;
                    721:                end = cis(235);
                    722:                center = 0;
                    723:        };
                    724:        left ' (start)' at A.start;
                    725:        right '(midway) ' at cis(180);
                    726:        left ' (end)' at A.end;
                    727:        put dot {center = A.start;};
                    728:        put dot {center = cis(180);};
                    729:        put dot {center = A.end;};
                    730: }
                    731: .IF
                    732: .P1
                    733: /* giving center, radius, and
                    734:    starting and ending angles */
                    735: put arc {
                    736:        center = 0;
                    737:        radius = 1;
                    738:        startang = 0;
                    739:        endang = 235;
                    740: };
                    741: .P2
                    742: .Ke
                    743: .P1
                    744: /* giving center, starting point,
                    745:    and ending angle */
                    746: put arc {
                    747:        center = 0;
                    748:        start = 1;
                    749:        endang = 235;
                    750: };
                    751: .P2
                    752: .Ks
                    753: .IS
                    754: main {
                    755:        put A:arc {
                    756:                start = 1;
                    757:                end = cis(235);
                    758:                center = 0;
                    759:        };
                    760:        left ' (end)' at A.start;
                    761:        right '(midway) ' at cis(180);
                    762:        left ' (start)' at A.end;
                    763:        put dot {center = A.start;};
                    764:        put dot {center = cis(180);};
                    765:        put dot {center = A.end;};
                    766: }
                    767: .IF
                    768: .P1
                    769: /* giving three points on the arc */
                    770: put arc {
                    771:        start = cis(235);
                    772:        midway = -1;
                    773:        end = 0;
                    774: };
                    775: .P2
                    776: .Ke
                    777: .NH 2
                    778: Other Elements of \*(id Pictures
                    779: .PP
                    780: .I Ideal
                    781: pictures also may contain text and splines.
                    782: .NH 3
                    783: Text Captions
                    784: .PP
                    785: There are three commands to place text with respect to a point.
                    786: The
                    787: .I left
                    788: command left-justifies the text with respect to the specified location:
                    789: the text will start there.
                    790: The
                    791: .I right
                    792: command right-justifies the text so that it ends at the specified
                    793: location.
                    794: The default is to center the text at the point.
                    795: (The arrows in this picture point to the locations of the named points.)
                    796: .Ks
                    797: .P1
                    798: left "some text" at x;
                    799: .P2
                    800: .P1
                    801: \&"some centered text" at y;
                    802: .P2
                    803: .P1
                    804: right "some other text" at z;
                    805: .P2
                    806: .IS
                    807: ...colwid 6.0
                    808: ...width 4.0
                    809: arrow {
                    810:        var tl, hd, head, perp, headang;
                    811:        conn tl to hd;
                    812:        perp = head*(tl-hd)/abs(tl-hd);
                    813:        conn hd + cis(headang)*perp to hd to hd + cis(-headang)*perp;
                    814:        head ~ 0.1;
                    815:         headang ~ 25;
                    816:        var start, end;
                    817:        start = tl;
                    818:        end = hd;
                    819: }
                    820: main {
                    821:        var x, y, z;
                    822:        var offset;
                    823:        offset = (1,-1);
                    824:        x = 0;
                    825:        left 'some text' at x;
                    826:        put arrow {
                    827:                start = x + offset;
                    828:                end = x;
                    829:                left ' (x)' at start;
                    830:        };
                    831:        y = 3;
                    832:        'some centered text' at y;
                    833:        put arrow {
                    834:                start = y + offset;
                    835:                end = y;
                    836:                left ' (y)' at start;
                    837:        };
                    838:        z = 6;
                    839:        right 'some other text' at z;
                    840:        put arrow {
                    841:                start = z + offset;
                    842:                end = z;
                    843:                left ' (z)' at start;
                    844:        };
                    845: }
                    846: .IE
                    847: .Ke
                    848: .LP
                    849: To include a double quote mark in a string, escape it with a back-slash.
                    850: If you have a line running through a point at which you place some text,
                    851: you may want to add a space to one end of the text so that the line
                    852: doesn't chop through the text.
                    853: The string may include
                    854: .I troff
                    855: special characters (like
                    856: .CW \e(bu )
                    857: and commands to other preprocessors (notably
                    858: .I eqn ),
                    859: but \*(id should be run before any other preprocessors.
                    860: .NH 3
                    861: Splines
                    862: .PP
                    863: .I Ideal
                    864: provides quadratic splines that are drawn with a
                    865: B-spline basis:
                    866: the user supplies a sequence of guiding points, and \*(id
                    867: draws a smooth curve that is tangent to the polygonal
                    868: path they define at the midpoint of each segment;
                    869: the spline also starts at the first point and ends at the last.
                    870: .Ks
                    871: .IS
                    872: ...colwid 8.0
                    873: ...width 1.0
                    874: ...maxx 2.0
                    875: ...minx -1.0
                    876: ...maxy 2.0
                    877: ...miny 0.0
                    878: main {
                    879:        var x, y, z, w;
                    880:        x = 0;
                    881:        y = 1;
                    882:        z = (-1,1);
                    883:        w = (2,2);
                    884:        spline x to y to z to w;
                    885:        right '(x) ' at x;
                    886:        left ' (y)' at y;
                    887:        right '(z) ' at z;
                    888:        left ' (w)' at w;
                    889:        put dot {center = x;};
                    890:        put dot {center = y;};
                    891:        put dot {center = z;};
                    892:        put dot {center = w;};
                    893: }
                    894: .IF
                    895: .P1
                    896: spline x to y to z to w;
                    897: 
                    898: 
                    899: .P2
                    900: .Ke
                    901: .NH 1
                    902: Putting Boxes Together
                    903: .PP
                    904: In this section we present several complete \*(id
                    905: programs to show how to build up
                    906: pictures from boxes.
                    907: .NH 2
                    908: Naming Instances of Boxes
                    909: .PP
                    910: Most pictures involve more than placements of simple boxes.
                    911: And when pictures involve several boxes, certain geometrical
                    912: relationships should exist among them.
                    913: We can refer to the local variables of a box that has been put\(emall
                    914: we need to do is name the \fIput\fP statement.
                    915: Here is a simple example showing a diagram that could be used to illustrate
                    916: Pythagoras's Theorem for isoceles triangles:
                    917: .Ks
                    918: .IS
                    919: ...libfile rect
                    920: ...width 1.0
                    921: main {
                    922:        put first: rect {
                    923:                sw = 0;
                    924:                ht = wd = 1;
                    925:        };
                    926:        put next: rect {
                    927:                nw = first.se;
                    928:                ht = wd = first.ht;
                    929:        };
                    930:        put last: rect {
                    931:                sw = first.ne;
                    932:                se = next.ne;
                    933:                ht = wd;
                    934:        };
                    935: }
                    936: .IF
                    937: .P1
                    938: main {
                    939:        put first: rect {
                    940:                sw = 0;
                    941:                ht = wd = 1;
                    942:        };
                    943:        put next: rect {
                    944:                nw = first.se;
                    945:                ht = wd = first.ht;
                    946:        };
                    947:        put last: rect {
                    948:                sw = first.ne;
                    949:                se = next.ne;
                    950:                ht = wd;
                    951:        };
                    952: }
                    953: .P2
                    954: .Ke
                    955: .LP
                    956: First we place an instance of
                    957: .I rect
                    958: called
                    959: .I first .
                    960: Then we place another
                    961: .I rect
                    962: with its upper left corner ($ne$)
                    963: at the lower right of
                    964: .I first .
                    965: Finally, we draw a third square,
                    966: two of whose adjacent points are
                    967: identified with points on the first
                    968: two squares placed.
                    969: We could have used any two adjacent points on
                    970: .I last :
                    971: if we had placed
                    972: $last.ne$ at $first.ne$
                    973: and $last.nw$ at $next.ne$, \*(id
                    974: would have figured all the relationships
                    975: out right, although the program might be quite
                    976: inscrutable to humans.
                    977: .PP
                    978: How can we circumscribe a triangle?
                    979: If we name the \fIput\fP statement that produces
                    980: the instance, we can just give its three
                    981: vertices as values for $z1$, $z2$, and $z3$
                    982: in an instance of
                    983: .I circle .
                    984: .Ks
                    985: .IS
                    986: ...libfile circle
                    987: triangle {
                    988:        var z1, z2, z3;
                    989:        conn z1 to z2 to z3 to z1;
                    990: }
                    991: main {
                    992:        put T: triangle {
                    993:                z1 = 0;
                    994:                z2 = 1;
                    995:                z3 = (2,2);
                    996:        };
                    997:        put circle {
                    998:                z1 = T.z1;
                    999:                z2 = T.z2;
                   1000:                z3 = T.z3;
                   1001:        };
                   1002: }
                   1003: .IF
                   1004: .P1
                   1005: triangle {
                   1006:        var z1, z2, z3;
                   1007:        conn z1 to z2 to z3 to z1;
                   1008: }
                   1009: 
                   1010: main {
                   1011:        put T: triangle {
                   1012:                z1 = 0;
                   1013:                z2 = 1;
                   1014:                z3 = (2,2);
                   1015:        };
                   1016:        put circle {
                   1017:                z1 = T.z1;
                   1018:                z2 = T.z2;
                   1019:                z3 = T.z3;
                   1020:        };
                   1021: }
                   1022: .P2
                   1023: .Ke
                   1024: .NH 2
                   1025: Parameter Section Commands
                   1026: .PP
                   1027: Any \*(id statement may appear in the parameter
                   1028: section of a \fIput\fP statement.
                   1029: This section illustrates some uses of this feature.
                   1030: .PP
                   1031: Suppose we will need to draw
                   1032: pictures of a linked list before and after
                   1033: insertion of a new node.
                   1034: We might start with this definition
                   1035: of a
                   1036: .I listnode :
                   1037: .Ks
                   1038: .IS
                   1039: ...width 1.0
                   1040: ...colwid 8.0
                   1041: listnode {
                   1042:        put info: rect {
                   1043:                var hook;
                   1044:                hook = (nw + sw)/2;
                   1045:                ht = lht;
                   1046:                wd = lwd/2;
                   1047:        };
                   1048:        put next: rect {
                   1049:                var c;
                   1050:                c = (nw + se)/2;
                   1051:                sw = info.se;
                   1052:                ht = lht;
                   1053:                wd = lwd/2;
                   1054:        };
                   1055: }
                   1056: main {
                   1057:        put listnode {
                   1058:                info.sw = 0;
                   1059:                var lht, lwd;
                   1060:                lht = 1;
                   1061:                lwd = 2;
                   1062:        };
                   1063: }
                   1064: .IF
                   1065: .P1
                   1066: listnode {
                   1067:        put info: rect {
                   1068:                var hook;
                   1069:                hook = (nw + sw)/2;
                   1070:                ht = lht;
                   1071:                wd = lwd/2;
                   1072:        };
                   1073:        put next: rect {
                   1074:                var c;
                   1075:                c = (nw + se)/2;
                   1076:                sw = info.se;
                   1077:                ht = lht;
                   1078:                wd = lwd/2;
                   1079:        };
                   1080: }
                   1081: .P2
                   1082: .Ke
                   1083: .LP
                   1084: This version of
                   1085: .I listnode
                   1086: depends on
                   1087: .I rect .
                   1088: Notice that it references two variables
                   1089: ($lwd$ and $lht$) that are not local to
                   1090: itself:
                   1091: these variables must be defined in any
                   1092: environment in which $listnode$ is put.
                   1093: (They are global to it.)
                   1094: We have added statements that define new
                   1095: variables ($hook$ in $first$ and $c$ in $next$)
                   1096: that are local to the particular instance of
                   1097: .I rect .
                   1098: .PP
                   1099: Now we draw the list as it is before insertion:
                   1100: .Ks
                   1101: .IS
                   1102: arrow {
                   1103:        var hd, tl, head, wing;
                   1104:        head = 0.2;
                   1105:        wing = head*(tl-hd)/abs(tl-hd);
                   1106:        conn hd to tl;
                   1107:        conn hd + cis(25)*wing to hd to hd + cis(-25)*wing;
                   1108: }
                   1109: ...width 2.0
                   1110: main {
                   1111:        var lht, lwd;
                   1112:        lht = 1;
                   1113:        lwd = 2*lht;
                   1114:        put first: listnode {
                   1115:                info.sw = 0;
                   1116:        };
                   1117:        put last: listnode {
                   1118:                info.sw = 2[first.info.sw,first.next.se];
                   1119:                conn next.sw to next.ne;
                   1120:        };
                   1121:        put new: listnode {
                   1122:                info.nw = 2[first.next.ne,first.next.se];
                   1123:        };
                   1124:        put arrow {
                   1125:                hd = last.info.hook;
                   1126:                tl = first.next.c;
                   1127:        };
                   1128:        put arrow {
                   1129:                hd = new.info.hook;
                   1130:                tl = hd - 1;
                   1131:                right 'new ' at tl;
                   1132:        };
                   1133:        put arrow {
                   1134:                hd = first.info.hook;
                   1135:                tl = hd - 1;
                   1136:                right 'list ' at tl;
                   1137:        };
                   1138: }
                   1139: .IF
                   1140: .P1
                   1141: main {
                   1142:        var lht, lwd;
                   1143:        lht = 1;
                   1144:        lwd = 2*lht;
                   1145:        put first: listnode {
                   1146:                info.sw = 0;
                   1147:        };
                   1148:        put last: listnode {
                   1149:                info.sw = 2[first.info.sw,first.next.se];
                   1150:                conn next.sw to next.ne;
                   1151:        };
                   1152:        put new: listnode {
                   1153:                info.nw = 2[first.next.ne,first.next.se];
                   1154:        };
                   1155:        put arrow {
                   1156:                hd = last.info.hook;
                   1157:                tl = first.next.c;
                   1158:        };
                   1159:        put arrow {
                   1160:                hd = new.info.hook;
                   1161:                tl = hd - 1;
                   1162:                right "new " at tl;
                   1163:        };
                   1164:        put arrow {
                   1165:                hd = first.info.hook;
                   1166:                tl = hd - 1;
                   1167:                right "list " at tl;
                   1168:        };
                   1169: }
                   1170: .P2
                   1171: .Ke
                   1172: .LP
                   1173: Here we have added statements directly to the
                   1174: parameter section of two of the calls to
                   1175: .I arrow
                   1176: to avoid either naming each instance of
                   1177: .I arrow
                   1178: or naming the tails of these arrows so that
                   1179: text could be placed there.
                   1180: We have also added a statement to draw the
                   1181: null pointer in box
                   1182: .I last .
                   1183: .PP
                   1184: The program to draw the list after insertion of the
                   1185: new node remains largely unchanged:
                   1186: the nodes haven't moved; only the arrows hooking them
                   1187: together have moved.
                   1188: .Ks
                   1189: .IS
                   1190: main {
                   1191:        var lht, lwd;
                   1192:        lht = 1;
                   1193:        lwd = 2*lht;
                   1194:        put first: listnode {
                   1195:                info.sw = 0;
                   1196:        };
                   1197:        put last: listnode {
                   1198:                info.sw = 2[first.info.sw,first.next.se];
                   1199:                conn next.sw to next.ne;
                   1200:        };
                   1201:        put new: listnode {
                   1202:                info.nw = 2[first.next.ne,first.next.se];
                   1203:        };
                   1204:        put arrow {
                   1205:                hd = new.info.nw;
                   1206:                tl = first.next.c;
                   1207:        };
                   1208:        put arrow {
                   1209:                hd = last.info.sw;
                   1210:                tl = new.next.c;
                   1211:        };
                   1212:        put arrow {
                   1213:                hd = new.info.hook;
                   1214:                tl = hd - 1;
                   1215:                right 'new ' at tl;
                   1216:        };
                   1217:        put arrow {
                   1218:                hd = first.info.hook;
                   1219:                tl = hd - 1;
                   1220:                right 'list ' at tl;
                   1221:        };
                   1222: }
                   1223: .IF
                   1224: .P1
                   1225: main {
                   1226:        var lht, lwd;
                   1227:        lht = 1;
                   1228:        lwd = 2*lht;
                   1229:        put first: listnode {
                   1230:                info.sw = 0;
                   1231:        };
                   1232:        put last: listnode {
                   1233:                info.sw = 2[first.info.sw,first.next.se];
                   1234:                conn next.sw to next.ne;
                   1235:        };
                   1236:        put new: listnode {
                   1237:                info.nw = 2[first.next.ne,first.next.se];
                   1238:        };
                   1239:        /* These two arrows are different: */
                   1240:        put arrow {
                   1241:                hd = new.info.nw;
                   1242:                tl = first.next.c;
                   1243:        };
                   1244:        put arrow {
                   1245:                hd = last.info.sw;
                   1246:                tl = new.next.c;
                   1247:        }
                   1248:        /* These are the same as before: */
                   1249:        put arrow {
                   1250:                hd = new.info.hook;
                   1251:                tl = hd - 1;
                   1252:                right "new " at tl;
                   1253:        };
                   1254:        put arrow {
                   1255:                hd = first.info.hook;
                   1256:                tl = hd - 1;
                   1257:                right "list " at tl;
                   1258:        };
                   1259: }
                   1260: .P2
                   1261: .Ke
                   1262: .NH 2
                   1263: A Shorter Version
                   1264: .PP
                   1265: The previous example is somewhat long-winded
                   1266: because it demonstrates many features of \*(id
                   1267: that really aren't needed.
                   1268: For instance, it would probably have made better
                   1269: sense to define
                   1270: .I listnode
                   1271: as a basic element rather than building it out
                   1272: of
                   1273: .I rect s.
                   1274: This would reduce the need for delving deep
                   1275: into the internals of boxes from outside
                   1276: (e.g.
                   1277: .I first.info.hook ).
                   1278: Here is the same example reworked:
                   1279: .Ks
                   1280: .IS
                   1281: ...width 2
                   1282: listnode {
                   1283:        var n, s, e, w, ne, nw, se, sw, next;
                   1284:        n = s + (0,1)*lht;
                   1285:        ne = n + 0.5*lwd = nw + lwd;
                   1286:        se = s + 0.5*lwd = sw + lwd;
                   1287:        e = (ne + se)/2;
                   1288:        w = (nw + sw)/2;
                   1289:        next = (ne + s)/2;
                   1290:        conn nw to ne to se to sw to nw;
                   1291:        conn n to s;
                   1292: }
                   1293: 
                   1294: main {
                   1295:        var lht, lwd;
                   1296:        lht = 1;
                   1297:        lwd = 2;
                   1298:        put first: listnode {
                   1299:                sw = 0;
                   1300:        };
                   1301:        put last: listnode {
                   1302:                sw = 2[first.sw,first.se];
                   1303:                conn s to ne;
                   1304:        };
                   1305:        put new: listnode {
                   1306:                nw = 2[first.ne,first.se];
                   1307:        };
                   1308:        put arrow {
                   1309:                hd = new.nw;
                   1310:                tl = first.next;
                   1311:        };
                   1312:        put arrow {
                   1313:                hd = last.sw;
                   1314:                tl = new.next;
                   1315:        };
                   1316:        put arrow {
                   1317:                hd = new.w;
                   1318:                tl = hd - 1;
                   1319:                right "new " at tl;
                   1320:        };
                   1321:        put arrow {
                   1322:                hd = first.w;
                   1323:                tl = hd - 1;
                   1324:                right "list " at tl;
                   1325:        };
                   1326: }
                   1327: .IE
                   1328: .P1
                   1329: listnode {
                   1330:        var n, s, e, w, ne, nw, se, sw, next;
                   1331:        n = s + (0,1)*lht;
                   1332:        ne = n + 0.5*lwd = nw + lwd;
                   1333:        se = s + 0.5*lwd = sw + lwd;
                   1334:        e = (ne + se)/2;
                   1335:        w = (nw + sw)/2;
                   1336:        next = (ne + s)/2;
                   1337:        conn nw to ne to se to sw to nw;
                   1338:        conn n to s;
                   1339: }
                   1340: 
                   1341: main {
                   1342:        var lht, lwd;
                   1343:        lht = 1;
                   1344:        lwd = 2;
                   1345:        put first: listnode {
                   1346:                sw = 0;
                   1347:        };
                   1348:        put last: listnode {
                   1349:                sw = 2[first.sw,first.se];
                   1350:                conn s to ne;
                   1351:        };
                   1352:        put new: listnode {
                   1353:                nw = 2[first.ne,first.se];
                   1354:        };
                   1355:        put arrow {
                   1356:                hd = new.nw;
                   1357:                tl = first.next;
                   1358:        };
                   1359:        put arrow {
                   1360:                hd = last.sw;
                   1361:                tl = new.next;
                   1362:        };
                   1363:        put arrow {
                   1364:                hd = new.w;
                   1365:                tl = hd - 1;
                   1366:                right "new " at tl;
                   1367:        };
                   1368:        put arrow {
                   1369:                hd = first.w;
                   1370:                tl = hd - 1;
                   1371:                right "list " at tl;
                   1372:        };
                   1373: }
                   1374: .P2
                   1375: .Ke
                   1376: Notice that equations need not be just a left side and a right side:
                   1377: they may include several expressions that should be equal.
                   1378: ...........
                   1379: .NH 1
                   1380: Iteration of \*(id Constructs
                   1381: .NH 2
                   1382: Pens
                   1383: .PP
                   1384: In Donald Knuth's \s-2METAFONT\s0|reference(knuth metafont)
                   1385: system, pens are different
                   1386: shapes\(emcircles, ellipses, and polygons\(emthat draw along
                   1387: curves.
                   1388: .I Ideal
                   1389: includes pens as a generalization of this idea:
                   1390: .I any
                   1391: box may be used to draw along a line.
                   1392: For instance, users may define ``dashed'' or ``dotted'' pens.
                   1393: A pen statement looks like this:
                   1394: .SP
                   1395: .P1
                   1396: conn $x$ to $y$
                   1397:        using $n$ $pen$ {
                   1398:                ...
                   1399:        } <$a$,$b$>;
                   1400: .P2
                   1401: (The only keywords in this statement are $conn$, $"to"$, and $using$.)
                   1402: .I Pen
                   1403: may be any box.
                   1404: .I Ideal
                   1405: will place $n$ copies of
                   1406: .I pen
                   1407: in the space from $x$ to $y$.
                   1408: $a$ and $b$ are expressions known to
                   1409: .I pen .
                   1410: The first instance of
                   1411: .I pen
                   1412: will have $a$ at $x$, and
                   1413: the last instance of
                   1414: .I pen
                   1415: will have $b$ at $y$;
                   1416: every instance in between will have
                   1417: its $a$ at the preceding one's $b$,
                   1418: and its $b$ at the succeeding one's $a$,
                   1419: as shown in this picture:
                   1420: .Ks
                   1421: .IS
                   1422: ...colwid 6.0
                   1423: ...width 4.0
                   1424: ...libfile rect
                   1425: pen {
                   1426:        var e, w, c;
                   1427:        var s;
                   1428:        e = r.e;
                   1429:        s = r.s;
                   1430:        w = r.w;
                   1431:        c = r.c;
                   1432:        put r: rect {
                   1433:                ht = wd = 1;
                   1434:        };
                   1435:        left ' \f2a\fP' at w;
                   1436:        right '\f2b\fP ' at e;
                   1437: }
                   1438: main {
                   1439:        put first: pen {
                   1440:                w = 0;
                   1441:                right '\f2x\fP ' at w;
                   1442:                '1' at s+(0,0.1);
                   1443:        };
                   1444:        put second: pen {
                   1445:                w = first.e;
                   1446:                '2' at s+(0,0.1);
                   1447:        };
                   1448:        '...' at (second.e + ipth.w)/2;
                   1449:        put ipth: pen {
                   1450:                w = 2[second.w,second.e];
                   1451:                '\f2i\fP\-1' at s+(0,0.1);
                   1452:        };
                   1453:        put ith: pen {
                   1454:                w = ipth.e;
                   1455:                '\f2i\fP' at s+(0,0.1);
                   1456:        };
                   1457:        put inth: pen {
                   1458:                w = ith.e;
                   1459:                '\f2i\fP+1' at s+(0,0.1);
                   1460:        };
                   1461:        '...' at (inth.e + last.w)/2;
                   1462:        put last: pen {
                   1463:                w = 2[inth.w,inth.e];
                   1464:                '\f2n\fP' at s+(0,0.1);
                   1465:                left ' \f2y\fP' at e;
                   1466:        };
                   1467: }
                   1468: .IE
                   1469: .Ke
                   1470: .PP
                   1471: Here is an example box that contains an angular wavy path:
                   1472: .Ks
                   1473: .IS
                   1474: ...colwid 9.0
                   1475: ...width 1.0
                   1476: wavy {
                   1477:        var start, end, perp, pt1, pt2, ht;
                   1478:        perp = (0,1)*(start - end)/abs(start - end);
                   1479:        pt1 = 0.25[start,end] + perp*ht;
                   1480:        pt2 = 0.75[start,end] - perp*ht;
                   1481:        conn start to pt1 to pt2 to end;
                   1482: }
                   1483: main {
                   1484:        put wavy {
                   1485:                start = 0;
                   1486:                end = 1;
                   1487:                ht = 0.2;
                   1488:                right '(start) ' at start;
                   1489:                left ' (end)' at end;
                   1490:        };
                   1491: }
                   1492: .IE
                   1493: .P1
                   1494: wavy {
                   1495:        var start, end, perp, pt1, pt2, ht;
                   1496:        perp = (0,1)*(start - end)/abs(start - end);
                   1497:        pt1 = 0.25[start,end] + perp*ht;
                   1498:        pt2 = 0.75[start,end] - perp*ht;
                   1499:        conn start to pt1 to pt2 to end;
                   1500: }
                   1501: .P2
                   1502: .Ke
                   1503: .LP
                   1504: Here we use
                   1505: .I wavy
                   1506: as a pen to indicate that part of a rectangle is missing.
                   1507: .Ks
                   1508: .IS
                   1509: main {
                   1510:        var ne, nw, se, sw;
                   1511:        var n1, s1, n2, s2;
                   1512:        sw = 0;
                   1513:        ne = nw + 2;
                   1514:        se = sw + 2;
                   1515:        ne = se + (0,1);
                   1516:        n2 - 0.4 = n1 = 0.6[nw,ne];
                   1517:        s2 - 0.4 = s1 = 0.4[sw,se];
                   1518:        conn n1 to nw to sw to s1;
                   1519:        conn n1 to s1
                   1520:                using int(5*abs(n1-s1)) wavy {
                   1521:                        ht = -0.1;
                   1522:                } <start,end>;
                   1523:        conn n2 to ne to se to s2;
                   1524:        conn n2 to s2
                   1525:                using int(5*abs(n2-s2)) wavy {
                   1526:                        ht = -0.1;
                   1527:                } <start,end>;
                   1528: }
                   1529: .IF
                   1530: .P1
                   1531: main {
                   1532:        var ne, nw, se, sw;
                   1533:        var n1, s1, n2, s2;
                   1534:        ne = nw + 2;
                   1535:        se = sw + 2;
                   1536:        ne = se + (0,1);
                   1537:        n2 - 0.4 = n1 = 0.6[nw,ne];
                   1538:        s2 - 0.4 = s1 = 0.4[sw,se];
                   1539:        conn n1 to nw to sw to s1;
                   1540:        conn n1 to s1
                   1541:                using int(5*abs(n1-s1)) wavy {
                   1542:                        ht = -0.1;
                   1543:                } <start,end>;
                   1544:        conn n2 to ne to se to s2;
                   1545:        conn n2 to s2
                   1546:                using int(5*abs(n2-s2)) wavy {
                   1547:                        ht = -0.1;
                   1548:                } <start,end>;
                   1549: }
                   1550: .P2
                   1551: .Ke
                   1552: .LP
                   1553: We can change
                   1554: .I wavy
                   1555: to contain a smooth wave
                   1556: by changing the word
                   1557: .I conn
                   1558: in the fifth line of its definition to
                   1559: .I spline ,
                   1560: and use the same instructions above to draw
                   1561: the picture with the new pen.
                   1562: .Ks
                   1563: .IS
                   1564: wavy {
                   1565:        var start, end, perp, pt1, pt2, ht;
                   1566:        perp = (0,1)*(start - end)/abs(start - end);
                   1567:        pt1 = 0.25[start,end] + perp*ht;
                   1568:        pt2 = 0.75[start,end] - perp*ht;
                   1569:        spline start to pt1 to pt2 to end;
                   1570: }
                   1571: main {
                   1572:        var ne, nw, se, sw;
                   1573:        var n1, s1, n2, s2;
                   1574:        sw = 0;
                   1575:        ne = nw + 2;
                   1576:        se = sw + 2;
                   1577:        ne = se + (0,1);
                   1578:        n2 - 0.4 = n1 = 0.6[nw,ne];
                   1579:        s2 - 0.4 = s1 = 0.4[sw,se];
                   1580:        conn n1 to nw to sw to s1;
                   1581:        conn n1 to s1
                   1582:                using int(5*abs(n1-s1)) wavy {
                   1583:                        ht = -0.1;
                   1584:                } <start,end>;
                   1585:        conn n2 to ne to se to s2;
                   1586:        conn n2 to s2
                   1587:                using int(5*abs(n2-s2)) wavy {
                   1588:                        ht = -0.1;
                   1589:                } <start,end>;
                   1590: }
                   1591: .IE
                   1592: .Ke
                   1593: .NH 2
                   1594: Pens as For-Statements
                   1595: .PP
                   1596: If \*(id had a for-statement, the pen statement
                   1597: .P1
                   1598: conn $x$ to $y$
                   1599:        using $n$ $pen$ {
                   1600:                ...
                   1601:        } <$a$,$b$>;
                   1602: .P2
                   1603: .LP
                   1604: would be equivalent to
                   1605: .P1
                   1606: for $i$ = 1 to $n$ {
                   1607:        put $pen$ {
                   1608:                $a$ = (($i$-1)/$n$)[$x$,$y$];
                   1609:                $b$ = ($i$/$n$)[$x$,$y$];
                   1610:                ...
                   1611:        };
                   1612: }
                   1613: .P2
                   1614: .Ts
                   1615: This means a pen statement can be used to synthesize
                   1616: a for-statement in an \*(id program.
                   1617: Here is a pen statement to draw a dashed arc:
                   1618: .Ks
                   1619: .IS
                   1620: ...libfile arc
                   1621: main {
                   1622:        conn 0 to 180
                   1623:                using 10 arc {
                   1624:                        center = 0;
                   1625:                        radius = 1;
                   1626:                }<startang, 9+endang>;
                   1627: }
                   1628: .IF
                   1629: .P1
                   1630: conn 0 to 180
                   1631:        using 10 arc {
                   1632:                center = 0;
                   1633:                radius = 1;
                   1634:        }<startang, 9+endang>;
                   1635: .P2
                   1636: .Ke
                   1637: .Te
                   1638: .Ts
                   1639: To draw a set of concentric circles
                   1640: we can say:
                   1641: .Ks
                   1642: .IS
                   1643: ...libfile circle
                   1644: main {
                   1645:        conn 1 to 6
                   1646:                using 5 circle {
                   1647:                        center = 0;
                   1648:                        } <radius, radius+1>;
                   1649: }
                   1650: .IF
                   1651: .P1
                   1652: main {
                   1653:        conn 1 to 6
                   1654:                using 5 circle {
                   1655:                        center = 0;
                   1656:                        } <radius,radius+1>;
                   1657: }
                   1658: .P2
                   1659: .Ke
                   1660: .Te
                   1661: .Ts
                   1662: In the first example, the second expression in angle
                   1663: brackets is important: it means that each ``dash''
                   1664: covers nine degrees.
                   1665: In the second example, this expression is redundant:
                   1666: its only purpose is to prevent \*(id from generating
                   1667: a stream of error messages about inconsistent equations.
                   1668: This contorted way of simulating for-statements
                   1669: is necessary only because pens are meant to do
                   1670: the right thing at each end of and all along a path that is
                   1671: being drawn with some box, and not as general
                   1672: iteration constructs.
                   1673: .Te
                   1674: .Ts
                   1675: Why doesn't \*(id have
                   1676: for-statements?
                   1677: Notice that every variable in an \*(id program
                   1678: is assigned a value exactly once.
                   1679: Obviously the index of a for-statement must be
                   1680: an exception to that rule.
                   1681: Generating the index internally prevents the
                   1682: need to have two kinds of variables\(emchanging
                   1683: and fixed.
                   1684: The local variables of boxes placed by pen statements
                   1685: cannot be referenced outside the pen statement,
                   1686: because the boxes are not named when they are placed.
                   1687: A general for-statement could lead to the need to
                   1688: generate automatically names for different instances of boxes,
                   1689: a hard problem that I don't understand well enough yet.
                   1690: .Te
                   1691: ..........
                   1692: .NH 2
                   1693: Filling Regions
                   1694: .PP
                   1695: Because any box can be used as a pen, we can shade regions.
                   1696: (We can have not only dashed and dotted ink, but checkered paint!)
                   1697: Take box
                   1698: .I wavy ,
                   1699: for instance.
                   1700: First we construct a box
                   1701: .I brush ,
                   1702: which consists of seven copies of
                   1703: .I wavy
                   1704: going horizontally:
                   1705: .Ks
                   1706: .IS
                   1707: wavy {
                   1708:        var start, end, perp, pt1, pt2, ht;
                   1709:        perp = (0,1)*(start - end)/abs(start - end);
                   1710:        pt1 = 0.25[start,end] + perp*ht;
                   1711:        pt2 = 0.75[start,end] - perp*ht;
                   1712:        conn start to pt1 to pt2 to end;
                   1713: }
                   1714: brush {
                   1715:        var top, bot;
                   1716:        var bwd, bht;
                   1717:        var leftpt, rightpt;
                   1718:        leftpt = 0.5*(top+bot) - bwd/2;
                   1719:        rightpt = 0.5*(top+bot) +bwd/2;
                   1720:        conn leftpt to rightpt
                   1721:                using 7 wavy {
                   1722:                        ht = bht;
                   1723:                }<start,end>;
                   1724: }
                   1725: main {
                   1726:        put brush {
                   1727:                leftpt = 0;
                   1728:                rightpt = 7;
                   1729:                bht = 0.3;
                   1730:        };
                   1731: }
                   1732: .IF
                   1733: .P1
                   1734: brush {
                   1735:        var top, bot;
                   1736:        var bwd, bht;
                   1737:        var leftpt, rightpt;
                   1738:        leftpt = 0.5*(top+bot) - bwd/2;
                   1739:        rightpt = 0.5*(top+bot) + bwd/2;
                   1740:        conn leftpt to rightpt
                   1741:                using 7 wavy {
                   1742:                        ht = bht;
                   1743:                }<start,end>;
                   1744: }
                   1745: .P2
                   1746: .Ke
                   1747: Then we use ``brush'' to draw vertically
                   1748: over the region of interest.
                   1749: .Ks
                   1750: .IS
                   1751: background {
                   1752:        conn (0,1) to (0,-1)
                   1753:                using 6 brush {
                   1754:                        bwd = 2;
                   1755:                        bht = 0.1;
                   1756:                        }<top,bot>;
                   1757: }
                   1758: main {
                   1759:        put background {
                   1760:        };
                   1761: }
                   1762: .IF
                   1763: .P1
                   1764: conn (0,1) to (0,-1)
                   1765:        using 6 brush {
                   1766:                bwd = 2;
                   1767:                bht = 0.1;
                   1768:                }<top,bot>;
                   1769: 
                   1770: 
                   1771: 
                   1772: 
                   1773: .P2
                   1774: .Ke
                   1775: .NH 1
                   1776: Opaque Boxes
                   1777: .PP
                   1778: .I Ideal
                   1779: includes statements to blot out pieces
                   1780: of a picture.
                   1781: In this section we will sometimes place opaque boxes
                   1782: without explicitly drawing any background.
                   1783: In such cases, assume
                   1784: that we have painted over
                   1785: the area with pens as above.
                   1786: .NH 2
                   1787: Opaque Polygons
                   1788: .PP
                   1789: .I Ideal
                   1790: needs to know the vertices of a polygon in order
                   1791: to opaque the area it covers.
                   1792: The vertices are specified as a list in a
                   1793: .I boundary
                   1794: statement.
                   1795: For instance, to opaque a rectangular region using the
                   1796: .I rect
                   1797: box defined in Section 3, we could use the following statement:
                   1798: .Ks
                   1799: .IS
                   1800: ...libfile rect
                   1801: wavy {
                   1802:        var start, end, perp, pt1, pt2, ht;
                   1803:        perp = (0,1)*(start - end)/abs(start - end);
                   1804:        pt1 = 0.25[start,end] + perp*ht;
                   1805:        pt2 = 0.75[start,end] - perp*ht;
                   1806:        conn start to pt1 to pt2 to end;
                   1807: }
                   1808: brush {
                   1809:        var top, bot;
                   1810:        var bwd, bht;
                   1811:        var leftpt, rightpt;
                   1812:        leftpt = 0.5*(top+bot) - bwd/2;
                   1813:        rightpt = 0.5*(top+bot) +bwd/2;
                   1814:        conn leftpt to rightpt
                   1815:                using 7 wavy {
                   1816:                        ht = bht;
                   1817:                }<start,end>;
                   1818: }
                   1819: background {
                   1820:        conn (0,1) to (0,-1)
                   1821:                using 7 brush {
                   1822:                        bwd = 2;
                   1823:                        bht = 0.1;
                   1824:                        }<top,bot>;
                   1825: }
                   1826: main {
                   1827:        put background {
                   1828:        };
                   1829:        put rect {
                   1830:                opaque;
                   1831:                boundary = sw, se, ne, nw;
                   1832:                sw = (-0.4,-0.4);
                   1833:                wd = ht = 1;
                   1834:        };
                   1835: }
                   1836: .IF
                   1837: .P1
                   1838: put rect {
                   1839:        opaque;
                   1840:        boundary= sw, se, ne, nw;
                   1841:        sw = (-0.4,-0.4);
                   1842:        wd = ht = 1;
                   1843: };
                   1844: 
                   1845: 
                   1846: 
                   1847: 
                   1848: .P2
                   1849: .Ke
                   1850: .LP
                   1851: The sides of the rectangle are drawn by
                   1852: .I rect :
                   1853: they are not supplied automatically by the opaquing routine.
                   1854: If we wanted to save only the interior of the rectangle,
                   1855: we could use almost the same statement:
                   1856: .Ks
                   1857: .IS
                   1858: ...minx -1.0
                   1859: ...maxx 1.0
                   1860: ...miny -1.0
                   1861: ...maxy 1.0
                   1862: main {
                   1863:        put background {
                   1864:        };
                   1865: put rect {
                   1866:        opaque exterior;
                   1867:        boundary = sw, se, ne, nw;
                   1868:        sw = (-0.4,-0.4);
                   1869:        wd = ht = 1;
                   1870: };
                   1871: }
                   1872: .IF
                   1873: .P1
                   1874: put rect {
                   1875:        opaque exterior;
                   1876:        boundary = sw, se, ne, nw;
                   1877:        sw = (-0.4,-0.4);
                   1878:        wd = ht = 1;
                   1879: };
                   1880: .P2
                   1881: .Ke
                   1882: .PP
                   1883: If we plan to opaque a lot of rectangles,
                   1884: we should include a
                   1885: .I boundary
                   1886: in the definition of
                   1887: .I rect .
                   1888: Such a default
                   1889: .I boundary
                   1890: would be referenced only if the parameter section
                   1891: of the \fIput\fP statement included an opaque statement
                   1892: .I and
                   1893: did not include its own
                   1894: .I boundary .
                   1895: .NH 2
                   1896: Opaque Circular Arc Polygons
                   1897: .PP
                   1898: The edges of opaque regions can also be circular arcs.
                   1899: .Ts
                   1900: This generalization of the simple boundary statement
                   1901: is the most recent addition to \*(id.
                   1902: It avoids treating circles and their sectors and segments
                   1903: as special cases, and makes opaquing circular
                   1904: arc polygons much easier.
                   1905: .Te
                   1906: .LP
                   1907: To specify a circular arc edge, one gives its endpoints
                   1908: and a point through which it passes;
                   1909: this ``pass-through'' point is marked in the boundary
                   1910: list by the symbol ``\f8^\fP''.
                   1911: For example, the boundary list for the sector shown below is
                   1912: .Ks
                   1913: .IS
                   1914: ...libfile arc
                   1915: main {
                   1916:        put background {
                   1917:        };
                   1918: put arc {
                   1919:        center = (-1,-1);
                   1920:        radius = 2;
                   1921:        startang = 30;
                   1922:        endang = 60;
                   1923:        boundary = center,
                   1924:                center+radius*cis(startang),
                   1925:                ^center+radius*cis(0.5*(startang+endang)),
                   1926:                center+radius*cis(endang);
                   1927:        opaque;
                   1928:        conn start to center to end;
                   1929: };
                   1930: }
                   1931: .IF
                   1932: .P1
                   1933: boundary = center, cis(30), ^ cis(45), cis(60);
                   1934: 
                   1935: 
                   1936: 
                   1937: 
                   1938: 
                   1939: .P2
                   1940: .Ke
                   1941: .PP
                   1942: Another common opaque arc is the segment:
                   1943: .Ks
                   1944: .IS
                   1945: main {
                   1946:        put background {
                   1947:        };
                   1948: put arc {
                   1949:        center = (-1,-1);
                   1950:        radius = 2;
                   1951:        startang = 0;
                   1952:        endang = 90;
                   1953:        boundary = start,
                   1954:                ^center + radius*cis(0.5*(startang+endang)),
                   1955:                end;
                   1956:        opaque;
                   1957:        conn start to end;
                   1958: };
                   1959: }
                   1960: .IF
                   1961: .P1
                   1962: boundary = cis(0), ^ cis(45), cis(90);
                   1963: 
                   1964: 
                   1965: 
                   1966: 
                   1967: 
                   1968: 
                   1969: 
                   1970: 
                   1971: 
                   1972: 
                   1973: .P2
                   1974: .Ke
                   1975: .PP
                   1976: One can construct an opaque circle out of two semicircular edges:
                   1977: .Ks
                   1978: .IS
                   1979: ...libfile circle
                   1980: main {
                   1981:        put background {
                   1982:        };
                   1983: put circle {
                   1984:        radius = 0.5;
                   1985:        center = 0;
                   1986:        opaque;
                   1987: };
                   1988: put circle {
                   1989:        radius = 1;
                   1990:        center = 0;
                   1991:        opaque exterior;
                   1992: };
                   1993: }
                   1994: .IF
                   1995: .P1
                   1996: boundary = cis(0), ^ cis(90), cis(180), ^ cis(270);
                   1997: 
                   1998: 
                   1999: 
                   2000: 
                   2001: 
                   2002: 
                   2003: .P2
                   2004: .Ke
                   2005: .LP
                   2006: Here, the outer circle has an opaque exterior,
                   2007: while the inner circle has an opaque interior.
                   2008: .NH 2
                   2009: Order is Important
                   2010: .PP
                   2011: Without the ability to opaque,
                   2012: the order in which boxes are put does not matter.
                   2013: But when some boxes are opaque, order obviously
                   2014: .I does
                   2015: matter.
                   2016: Put statements are executed
                   2017: in the order in which they appear in the box definition.
                   2018: When an opaque box is drawn, the opaquing is done
                   2019: .I first ,
                   2020: then the lines of the box are drawn;
                   2021: so, for instance, an opaque
                   2022: .I listnode
                   2023: does include the line down its middle separating its
                   2024: .I info
                   2025: field from its
                   2026: .I next
                   2027: field.
                   2028: .NH 2
                   2029: Some Hard Facts
                   2030: .PP
                   2031: Neither text nor splines can be used to opaque objects,
                   2032: nor will they be clipped properly if they are in a
                   2033: picture and an opaque box is placed over them.
                   2034: .Ts
                   2035: The problem with text is that \*(id operates as a
                   2036: .I troff
                   2037: preprocessor,
                   2038: so it cannot determine anything about the size of the
                   2039: text, and it needs to know that if it is to do anything
                   2040: involving opaquing and text.
                   2041: .Te
                   2042: .Ts
                   2043: The problem with splines is more subtle.
                   2044: When a line or circular arc is chopped,
                   2045: it is easy to specify the lines or circular arcs that remain.
                   2046: But when a spline is chopped, the guiding points of the resulting curve pieces
                   2047: are hard to determine.
                   2048: .Te
                   2049: .NH 1
                   2050: Paper Commands
                   2051: .PP
                   2052: .I Ideal
                   2053: includes two commands that are analogous
                   2054: to the way people draw on paper.
                   2055: .NH 2
                   2056: Construct
                   2057: .PP
                   2058: The
                   2059: .I construct
                   2060: statement looks just like a \fIput\fP statement,
                   2061: with the keyword
                   2062: .I put
                   2063: replaced by
                   2064: .I construct .
                   2065: It is best to think of it as laying a sheet of
                   2066: tracing paper over the current drawing.
                   2067: Anything constructed will be drawn on this sheet.
                   2068: When you return to the layer underneath,
                   2069: you may refer to any of the local variables
                   2070: (for example, with a \fIput\fP statement), but the lines and curves
                   2071: in the constructed picture don't show.
                   2072: .Ks
                   2073: .IS
                   2074: ...maxy 2.0
                   2075: ...minx -1.0
                   2076: ...maxx 1.0
                   2077: ...libfile rect arrow
                   2078: main {
                   2079:        construct A: rect {
                   2080:                sw = 0;
                   2081:                wd = ht = 1;
                   2082:        };
                   2083:        construct B: rect {
                   2084:                n = A.s - (0,1);
                   2085:                wd = ht = 1;
                   2086:        };
                   2087:        'top' at A.c;
                   2088:        'bottom' at B.c;
                   2089:        put arrow {
                   2090:                hd = B.n;
                   2091:                tl = A.s;
                   2092:        };
                   2093: }
                   2094: .IF
                   2095: .P1
                   2096: main {
                   2097:        construct A: rect {
                   2098:                sw = 0;
                   2099:                wd = ht = 1;
                   2100:        };
                   2101:        construct B: rect {
                   2102:                n = A.s - (0,1);
                   2103:                wd = ht = 1;
                   2104:        };
                   2105:        'top' at A.c;
                   2106:        'bottom' at B.c;
                   2107:        put arrow {
                   2108:                hd = B.n;
                   2109:                tl = A.s;
                   2110:        };
                   2111: }
                   2112: .P2
                   2113: .Ke
                   2114: .LP
                   2115: Here we have used ``invisible boxes'' to place the
                   2116: arrow around the text without drawing the boxes.
                   2117: .NH 2
                   2118: Draw
                   2119: .PP
                   2120: The
                   2121: .I construct
                   2122: command may also be used to localize the
                   2123: effects of opaque boxes.
                   2124: We saw above how to draw a filled polygon:
                   2125: paint over the area, then opaque the exterior
                   2126: of the polygon.
                   2127: But how can we draw
                   2128: .I two
                   2129: filled polygons in the same picture?
                   2130: .PP
                   2131: One solution is to
                   2132: construct them both, then use the
                   2133: .I draw
                   2134: command to add them to the main picture.
                   2135: The
                   2136: .I draw
                   2137: command transfers the contents of the
                   2138: named sheet of tracing paper to the sheet below.
                   2139: .Ks
                   2140: .IS
                   2141: ...libfile circle
                   2142: ...width 2.0
                   2143: ...colwid 10.0
                   2144: null {
                   2145: }
                   2146: pentagon {
                   2147:        var center, radius,
                   2148:                pt1, pt2, pt3, pt4, pt5;
                   2149:        pt1 = center + radius;
                   2150:        pt2 = center + cis(72)*radius;
                   2151:        pt3 = center + cis(144)*radius;
                   2152:        pt4 = center + cis(-144)*radius;
                   2153:        pt5 = center + cis(-72)*radius;
                   2154:        conn pt1 to pt2 to pt3 to pt4 to pt5 to pt1;
                   2155:        boundary = pt1, pt2, pt3, pt4, pt5;
                   2156: }
                   2157: main {
                   2158:        construct A: null {
                   2159:                conn (0,1) to 0
                   2160:                        using 7 brush {
                   2161:                                bwd = 1;
                   2162:                                bht = 0.1;
                   2163:                                }<top,bot>;
                   2164:                put pentagon {
                   2165:                        center = (0,0.5);
                   2166:                        radius = (0,0.5);
                   2167:                        opaque exterior;
                   2168:                };
                   2169:        };
                   2170:        construct B: null {
                   2171:                conn (0.5,0.5) to (1.5,0.5)
                   2172:                        using 5 brush {
                   2173:                                bwd = (0,1);
                   2174:                                bht = 0.1;
                   2175:                                }<top,bot>;
                   2176:                put circle {
                   2177:                        center = (1,0.5);
                   2178:                        radius = 0.5;
                   2179:                        opaque exterior;
                   2180:                };
                   2181:        };
                   2182:        draw A;
                   2183:        draw B;
                   2184: }
                   2185: .IF
                   2186: .P1
                   2187: null {
                   2188: }
                   2189: 
                   2190: pentagon {
                   2191:        var center, radius,
                   2192:                pt1, pt2, pt3, pt4, pt5;
                   2193:        pt1 = center + radius;
                   2194:        pt2 = center + cis(72)*radius;
                   2195:        pt3 = center + cis(144)*radius;
                   2196:        pt4 = center + cis(-144)*radius;
                   2197:        pt5 = center + cis(-72)*radius;
                   2198:        conn pt1 to pt2 to pt3 to pt4 to pt5 to pt1;
                   2199:        boundary = pt1, pt2, pt3, pt4, pt5;
                   2200: }
                   2201: 
                   2202: main {
                   2203:        construct A: null {
                   2204:                conn (0,1) to 0
                   2205:                        using 7 brush {
                   2206:                                bwd = 1;
                   2207:                                bht = 0.1;
                   2208:                                }<top,bot>;
                   2209:                put pentagon {
                   2210:                        center = (0,0.5);
                   2211:                        radius = (0,0.5);
                   2212:                        opaque exterior;
                   2213:                };
                   2214:        };
                   2215:        construct B: null {
                   2216:                conn (0.5,0.5) to (1.5,0.5)
                   2217:                        using 5 brush {
                   2218:                                bwd = (0,1);
                   2219:                                bht = 0.1;
                   2220:                                }<top,bot>;
                   2221:                put circle {
                   2222:                        center = (1,0.5);
                   2223:                        radius = 0.5;
                   2224:                        opaque exterior;
                   2225:                };
                   2226:        };
                   2227:        draw A;
                   2228:        draw B;
                   2229: }
                   2230: .P2
                   2231: .Ke
                   2232: .LP
                   2233: Even \fIput\fP statements can be added to the parameter sections
                   2234: of
                   2235: .I construct
                   2236: (and \fIput\fP) statements!
                   2237: Believe it or not, box
                   2238: .I null
                   2239: defined above is one of the most useful:
                   2240: it gives us a way to name a set of commands and variables
                   2241: so that we may reference them later, yet it doesn't
                   2242: require us to define a box that will be used only once.
                   2243: .PP
                   2244: Given
                   2245: .I construct
                   2246: and
                   2247: .I draw ,
                   2248: why do we need a special box
                   2249: .I hole
                   2250: to opaque a circular area without drawing anything?
                   2251: Why not just construct an opaque circle, then draw it
                   2252: on the main picture?
                   2253: The problem is that the effect of opaquing is localized
                   2254: just as much as the drawing, so an opaque constructed
                   2255: circle won't opaque anything that lies underneath.
                   2256: ........
                   2257: .NH 1
                   2258: Library Files
                   2259: .PP
                   2260: Library files are available to draw common figures and for special
                   2261: figures like circles and arcs.
                   2262: To include a library file as part of an \*(id program,
                   2263: include the line
                   2264: .P1
                   2265: \&...libfile $name$
                   2266: .P2
                   2267: in your \*(id program (between the
                   2268: .CW .IS
                   2269: and
                   2270: .CW .IE
                   2271: lines that mark its
                   2272: start and end.)
                   2273: This section describes available library files that have been alluded
                   2274: to up to now.
                   2275: .NH 2
                   2276: Rectangle
                   2277: .PP
                   2278: File
                   2279: .I rect
                   2280: contains the definition of box
                   2281: .I rect ,
                   2282: which looks like the definition in Section 3, with
                   2283: five more variables:  $n$, $s$, $e$, $w$, and $c$,
                   2284: which are the four compass points and the center,
                   2285: respectively.
                   2286: .P1
                   2287: rect {
                   2288:        var ne, nw, sw, se,
                   2289:        n, e, w, s, c,
                   2290:        ht, wd;
                   2291:        ne = se + (0,1)*ht;
                   2292:        nw = sw + (0,1)*ht;
                   2293:        ne = nw + wd;
                   2294:        n = (ne+nw)/2;
                   2295:        s = (se+sw)/2;
                   2296:        e = (ne+se)/2;
                   2297:        w = (nw+sw)/2;
                   2298:        c = (ne+sw)/2;
                   2299:        ht ~ 1;
                   2300:        wd ~ 1.5;
                   2301:        boundary = ne, nw, sw, se;
                   2302:        conn ne to nw to sw to se to ne;
                   2303: }
                   2304: .P2
                   2305: .NH 2
                   2306: Arrow
                   2307: .PP
                   2308: File
                   2309: .I arrow
                   2310: contains the definition of box
                   2311: .I arrow
                   2312: as given in Section 3.
                   2313: .P1
                   2314: arrow {
                   2315:        var tl, hd, head, perp, headang;
                   2316:        conn tl to hd;
                   2317:        perp = head*(tl-hd)/abs(tl-hd);
                   2318:        conn hd + cis(headang)*perp to hd to hd + cis(-headang)*perp;
                   2319:        head ~ 0.1;
                   2320:        headang ~ 25;
                   2321: }
                   2322: .P2
                   2323: .NH 2
                   2324: Wavy
                   2325: .PP
                   2326: Library file
                   2327: .I wavy
                   2328: contains the definition for the familiar
                   2329: .I wavy .
                   2330: .P1
                   2331: wavy {
                   2332:        var start, end, perp, pt1, pt2, ht;
                   2333:        perp = (0,1)*(start - end)/abs(start - end);
                   2334:        pt1 = 0.25[start,end] + perp*ht;
                   2335:        pt2 = 0.75[start,end] - perp*ht;
                   2336:        conn start to pt1 to pt2 to end;
                   2337: }
                   2338: .P2
                   2339: .NH 2
                   2340: Dash
                   2341: .PP
                   2342: Library file
                   2343: .I dash
                   2344: contains the definition of box
                   2345: .I dash ,
                   2346: which may be useful for drawing dashed lines:
                   2347: .P1
                   2348: dash {
                   2349:        var start, end;
                   2350:        conn start to 0.25[start,end];
                   2351:        conn 0.75[start,end] to end;
                   2352: }
                   2353: .P2
                   2354: ..........
                   2355: .NH 2
                   2356: Circles
                   2357: .PP
                   2358: Box
                   2359: .I circle
                   2360: resides in a library file of the same name, and
                   2361: has the local variables described in Section 3:
                   2362: $center$, $radius$, $z1$, $z2$, and $z3$.
                   2363: .Ts
                   2364: Box
                   2365: .I circle
                   2366: actually consists of variable declarations
                   2367: and a put of box
                   2368: .I CIRCLE .
                   2369: So, if you will have many circles of a particular radius,
                   2370: it might be easier for you to define your own, say, $circle3$:
                   2371: .P1
                   2372: ...libfile CIRCLE
                   2373: circle {
                   2374:        var center, radius, z1, z2, z3;
                   2375:        put CIRCLE {
                   2376:                radius = 3;
                   2377:        }
                   2378: }
                   2379: .P2
                   2380: .Te
                   2381: .NH 2
                   2382: Arcs
                   2383: .PP
                   2384: Box
                   2385: .I arc
                   2386: is contained in a library file of the same name,
                   2387: with local variables as described in Section 3:
                   2388: $center$, $radius$, $start$, $midway$, $end$,
                   2389: $startang$, $midang$, and $endang$.
                   2390: .Ts
                   2391: As above,
                   2392: .I arc
                   2393: calls on
                   2394: a box called
                   2395: .I ARC .
                   2396: .Te
                   2397: .NH 1
                   2398: Examples
                   2399: .NH 2
                   2400: B-Trees
                   2401: .PP
                   2402: This example depicts a B-tree|reference(btree) whose nodes have many children.
                   2403: .Ks
                   2404: .IS
                   2405: ...colwid 6.0
                   2406: ...width 3.0
                   2407: ...libfile rect
                   2408: arrow {
                   2409:        var tl, hd, headvec, head;
                   2410:        headvec = hd + head*(tl - hd)/abs(tl - hd);
                   2411:        conn tl to hd;
                   2412:        conn hd + cis(20)*(headvec - hd)
                   2413:                to hd
                   2414:                to hd + cis(-20)*(headvec - hd);
                   2415: }
                   2416: 
                   2417: dot {
                   2418:        var s, e;
                   2419:        '\(bu' at 0.5[s, e] - (0,0.1);
                   2420: }
                   2421: 
                   2422: per {
                   2423:        var s, e;
                   2424:        '.' at 0.5[s, e];
                   2425: }
                   2426: 
                   2427: main {
                   2428: var rw, rh;
                   2429: rw = 2;
                   2430: rh = 1;
                   2431: var hmv, vmv;
                   2432: hmv = 0.6;
                   2433: vmv = 0.3;
                   2434: var ah;
                   2435: ah = 0.2;
                   2436: put root:rect{
                   2437:        sw = (0,1);
                   2438:        wd = rw;
                   2439:        ht = 1;
                   2440:        };
                   2441: put next:rect{
                   2442:        sw = youngest.sw + 2*(hmv, vmv);
                   2443:        wd = rw;
                   2444:        ht = rh;
                   2445:        };
                   2446: put youngest:rect{
                   2447:        sw = bro.sw + (hmv, vmv);
                   2448:        wd = rw;
                   2449:        ht = rh;
                   2450:        opaque;
                   2451:        };
                   2452: put bro:rect{
                   2453:        sw = eldest.sw + (hmv, vmv);
                   2454:        wd = rw;
                   2455:        ht = rh;
                   2456:        opaque;
                   2457:        };
                   2458: put eldest:rect{
                   2459:        im(nw) = im(3[root.nw,root.sw]);
                   2460:        re(0.5[nw, next.nw]) = re(0.5[root.nw, root.ne]);
                   2461:        wd = rw;
                   2462:        ht = rh;
                   2463:        opaque;
                   2464:        put arrow{
                   2465:                head = ah;
                   2466:                tl = 0.0[sw, se] + 0.5 * (nw - sw);
                   2467:                hd = tl - (0, 1) * cis(-27);
                   2468:        };
                   2469:        put arrow{
                   2470:                head = ah;
                   2471:                tl = 0.33[sw, se] + 0.5 * (nw -sw);
                   2472:                hd = tl - (0,1) * cis(-9);
                   2473:        };
                   2474:        put arrow{
                   2475:                head = ah;
                   2476:                tl = 0.67[sw, se] + 0.5 * (nw - sw);
                   2477:                hd = tl - (0,1) * cis(9);
                   2478:        };
                   2479:        put arrow{
                   2480:                head = ah;
                   2481:                tl = 1.0[sw, se] + 0.5 * (nw -sw);
                   2482:                hd = tl - (0,1) * cis(27);
                   2483:        };
                   2484:        };
                   2485: put arrow{
                   2486:        head = ah;
                   2487:        tl=root.sw + 0.5 * (root.nw - root.sw);
                   2488:        hd=eldest.nw;
                   2489: };
                   2490: put arrow{
                   2491:        head = ah;
                   2492:        tl=0.1[root.sw,root.se] + 0.5 * (root.nw - root.sw);
                   2493:        hd=bro.nw;
                   2494: };
                   2495: put a:arrow{
                   2496:        head = ah;
                   2497:        tl=0.2[root.sw,root.se] + 0.5 * (root.nw - root.sw);
                   2498:        hd=youngest.nw;
                   2499: };
                   2500: put b:arrow{
                   2501:        head = ah;
                   2502:        tl = 0.5[root.ne, root.se];
                   2503:        hd = next.nw;
                   2504: };
                   2505: put arrow{
                   2506:        head = ah;
                   2507:        hd = root.nw;
                   2508:        tl = 0.5[root.nw, root.ne] + (0, 1.0);
                   2509: };
                   2510: conn next.nw to youngest.nw using 3 dot{}<s, e>;
                   2511: conn next.se to youngest.se using 3 dot{}<s, e>;
                   2512: conn b.tl to a.tl using 4 per{}<s, e>;
                   2513: }
                   2514: .IE
                   2515: .Ke
                   2516: .P1
                   2517: \&...libfile rect
                   2518: arrow {
                   2519:        var tl, hd, headvec, head;
                   2520:        headvec = hd + head*(tl - hd)/abs(tl - hd);
                   2521:        conn tl to hd;
                   2522:        conn hd + cis(20)*(headvec - hd)
                   2523:                to hd
                   2524:                to hd + cis(-20)*(headvec - hd);
                   2525: }
                   2526: 
                   2527: dot {
                   2528:        var s, e;
                   2529:        '\e(bu' at 0.5[s, e] - (0,0.1);
                   2530: }
                   2531: 
                   2532: per {
                   2533:        var s, e;
                   2534:        '.' at 0.5[s, e];
                   2535: }
                   2536: 
                   2537: main {
                   2538:        var rw, rh;
                   2539:        rw = 2;
                   2540:        rh = 1;
                   2541:        var hmv, vmv;
                   2542:        hmv = 0.6;
                   2543:        vmv = 0.3;
                   2544:        var ah;
                   2545:        ah = 0.2;
                   2546:        put root: rect {
                   2547:                sw = (0,1);
                   2548:                wd = rw;
                   2549:                ht = 1;
                   2550:        };
                   2551:        put next: rect {
                   2552:                sw = youngest.sw + 2*(hmv, vmv);
                   2553:                wd = rw;
                   2554:                ht = rh;
                   2555:        };
                   2556:        put youngest: rect {
                   2557:                sw = bro.sw + (hmv, vmv);
                   2558:                wd = rw;
                   2559:                ht = rh;
                   2560:                opaque;
                   2561:        };
                   2562:        put bro: rect {
                   2563:                sw = eldest.sw + (hmv, vmv);
                   2564:                wd = rw;
                   2565:                ht = rh;
                   2566:                opaque;
                   2567:        };
                   2568:        put eldest: rect {
                   2569:                im(nw) = im(3[root.nw,root.sw]);
                   2570:                re(0.5[nw, next.nw]) = re(0.5[root.nw, root.ne]);
                   2571:                wd = rw;
                   2572:                ht = rh;
                   2573:                opaque;
                   2574:                put arrow {
                   2575:                        head = ah;
                   2576:                        tl = 0.0[sw, se] + 0.5 * (nw - sw);
                   2577:                        hd = tl - (0, 1) * cis(-27);
                   2578:                };
                   2579:                put arrow {
                   2580:                        head = ah;
                   2581:                        tl = 0.33[sw, se] + 0.5 * (nw -sw);
                   2582:                        hd = tl - (0,1) * cis(-9);
                   2583:                };
                   2584:                put arrow {
                   2585:                        head = ah;
                   2586:                        tl = 0.67[sw, se] + 0.5 * (nw - sw);
                   2587:                        hd = tl - (0,1) * cis(9);
                   2588:                };
                   2589:                put arrow {
                   2590:                        head = ah;
                   2591:                        tl = 1.0[sw, se] + 0.5 * (nw -sw);
                   2592:                        hd = tl - (0,1) * cis(27);
                   2593:                };
                   2594:        };
                   2595:        put arrow {
                   2596:                head = ah;
                   2597:                tl=root.sw + 0.5 * (root.nw - root.sw);
                   2598:                hd=eldest.nw;
                   2599:        };
                   2600:        put arrow {
                   2601:                head = ah;
                   2602:                tl=0.1[root.sw,root.se] + 0.5 * (root.nw - root.sw);
                   2603:                hd=bro.nw;
                   2604:        };
                   2605:        put a: arrow {
                   2606:                head = ah;
                   2607:                tl=0.2[root.sw,root.se] + 0.5 * (root.nw - root.sw);
                   2608:                hd=youngest.nw;
                   2609:        };
                   2610:        put b: arrow {
                   2611:                head = ah;
                   2612:                tl = 0.5[root.ne, root.se];
                   2613:                hd = next.nw;
                   2614:        };
                   2615:        put arrow {
                   2616:                head = ah;
                   2617:                hd = root.nw;
                   2618:                tl = 0.5[root.nw, root.ne] + (0, 1.0);
                   2619:        };
                   2620:        conn next.nw to youngest.nw using 3 dot{}<s, e>;
                   2621:        conn next.se to youngest.se using 3 dot{}<s, e>;
                   2622:        conn b.tl to a.tl using 4 per{}<s, e>;
                   2623: }
                   2624: .P2
                   2625: .NH 2
                   2626: A Sector Grid
                   2627: .PP
                   2628: Norm Schryer used this figure to show how numerical integration
                   2629: is used to find the area of planar regions.
                   2630: .Ks
                   2631: .IS
                   2632: ...colwid 8.0
                   2633: ...width 2.0
                   2634: ...libfile hole
                   2635: gridline {
                   2636:        var a,b;
                   2637:        var neg, pos;
                   2638:        conn a - neg to a + pos;
                   2639: }
                   2640: 
                   2641: main {
                   2642:        var n;
                   2643:        n = 21;
                   2644:        conn (0,0) to (0,1+1/(n-1)) using n gridline {neg = 0; pos = 1;} <a,b>;
                   2645:        conn (0,0) to (1+1/(n-1),0) using n gridline {neg = 0; pos = (0,1);} <a,b>;
                   2646:        put hole {
                   2647:                radius = 1;
                   2648:                center = (0,0);
                   2649:                opaque exterior;
                   2650:        };
                   2651: }
                   2652: .IF
                   2653: .P1
                   2654: 
                   2655: 
                   2656: 
                   2657: 
                   2658: 
                   2659: \&...libfile hole
                   2660: gridline {
                   2661:        var a,b;
                   2662:        var neg, pos;
                   2663:        conn a - neg to a + pos;
                   2664: }
                   2665: 
                   2666: main {
                   2667:        var n;
                   2668:        n = 21;
                   2669:        conn (0,0) to (0,1+1/(n-1))
                   2670:                using n gridline {
                   2671:                        neg = 0;
                   2672:                        pos = 1;
                   2673:                } <a,b>;
                   2674:        conn (0,0) to (1+1/(n-1),0)
                   2675:                using n gridline {
                   2676:                        neg = 0;
                   2677:                        pos = (0,1);
                   2678:                } <a,b>;
                   2679:        put hole {
                   2680:                radius = 1;
                   2681:                center = (0,0);
                   2682:                opaque exterior;
                   2683:        };
                   2684: }
                   2685: .P2
                   2686: .Ke
                   2687: .NH 2
                   2688: Polygon Clipping
                   2689: .PP
                   2690: This example from |reference(pavlidis image processing)
                   2691: illustrates all possible positions of a line
                   2692: segment with respect to a polygon.
                   2693: .Ks
                   2694: .ps 8
                   2695: .EQ
                   2696: delim $$
                   2697: gsize 8
                   2698: define P12 " P sub 1 ( P sub 2 ) "
                   2699: define P21 " P sub 2 ( P sub 1 )"
                   2700: .EN
                   2701: .IS
                   2702: ...width 4.5
                   2703: ...colwid 6.0
                   2704: ...libfile circle
                   2705: box spot{
                   2706:        var loc;
                   2707:        put circle{
                   2708:                var center, radius;
                   2709:                center = loc;
                   2710:                radius = 0.02;
                   2711:                opaque;
                   2712:                };
                   2713:        }
                   2714: box vert{
                   2715:        var midd, llength;
                   2716:        conn midd+llength to midd-llength;
                   2717:        }
                   2718: box poly{
                   2719:        var c1,p1,p2,p3,p4,p5,r1,tp,bp,ta,tb;
                   2720:        p1 = c1+r1;
                   2721:        p2 = cis(65)[c1,p1];
                   2722:        p3 = cis(170)[c1,p1];
                   2723:        p4 = cis(190)[c1,p1];
                   2724:        p5 = cis(300)[c1,p1];
                   2725:        tp = c1+(0,ta)*r1;
                   2726:        bp = c1+(0,tb)*r1;
                   2727:        conn p1 to p2;
                   2728:        conn p2 to p3;
                   2729:        conn p3 to p4;
                   2730:        conn p4 to p5;
                   2731:        conn p5 to p1;
                   2732:        put vert{ midd=c1; llength=(0,1.6)*r1; };
                   2733:        put spot{ loc=tp; };
                   2734:        put spot{ loc=bp; };
                   2735:        left '$P12$' at tp+0.1;
                   2736:        left '$P21$' at bp+0.1;
                   2737:        }
                   2738: ...minx -1
                   2739: ...maxx 6
                   2740: ...miny -1
                   2741: ...maxy 12
                   2742: box main {
                   2743:        put poly{
                   2744:                c1 =(1,9); r1 = (1,0); ta=1.1; tb=1.4;
                   2745:                left '$++--$' at p2-1.5;
                   2746:                right '(a)' at c1-(0.7,1.2);
                   2747:                };
                   2748:        put poly{
                   2749:                c1 =(3.5,9); r1 = (1,0); ta=1.1; tb=0.2;
                   2750:                left '$+---$' at p2+0.5;
                   2751:                left '$(-+--)$' at p2+(0.5,-0.15);
                   2752:                right '(b)(b1)' at c1-(0.7,1.2);
                   2753:                };
                   2754:        put poly{
                   2755:                c1 =(1,5); r1 = (1,0); ta=1.1; tb=-1;
                   2756:                left '$+--+$' at p2-1.5;
                   2757:                left '$(-++-)$' at p2-(1.5,0.15);
                   2758:                right '(c)(c1)' at c1-(0.7,1.2);
                   2759:                };
                   2760:        put poly{
                   2761:                c1 =(3.5,5); r1 = (1,0); ta=0.2; tb=-1;
                   2762:                left '$---+$' at p2+(0.5,-0.3);
                   2763:                left '$(--+-)$' at p2+(0.5,-0.45);
                   2764:                right '(d)(d1)' at c1-(0.7,1.2);
                   2765:                };
                   2766:        put poly{
                   2767:                c1 =(1,1); r1 = (1,0); ta=-1; tb=-1.4;
                   2768:                left '$--++$' at p4-(0,0.5);
                   2769:                right '(e)' at c1-(0.7,1.2);
                   2770:                };
                   2771:        put poly{
                   2772:                c1 =(3.5,1); r1 = (1,0); ta=0.2; tb=-0.2;
                   2773:                left '$----$' at p1+0.2;
                   2774:                right '(f)' at c1-(0.7,1.2);
                   2775:                };
                   2776: }
                   2777: .IE
                   2778: .Ke
                   2779: .ps
                   2780: .P1
                   2781: \&.ps 8
                   2782: .EQ
                   2783: delim off
                   2784: .EN
                   2785: \&.EQ
                   2786: gsize 8
                   2787: define P12 " P sub 1 ( P sub 2 ) "
                   2788: define P21 " P sub 2 ( P sub 1 )"
                   2789: \&.EN
                   2790: \&...libfile circle
                   2791: \&...minx -1
                   2792: \&...maxx 6
                   2793: \&...miny -1
                   2794: \&...maxy 12
                   2795: box spot{
                   2796:        var loc;
                   2797:        put circle{
                   2798:                var center, radius;
                   2799:                center = loc;
                   2800:                radius = 0.02;
                   2801:                opaque;
                   2802:                };
                   2803:        }
                   2804: box vert{
                   2805:        var midd, llength;
                   2806:        conn midd+llength to midd-llength;
                   2807:        }
                   2808: box poly{
                   2809:        var c1,p1,p2,p3,p4,p5,r1,tp,bp,ta,tb;
                   2810:        p1 = c1+r1;
                   2811:        p2 = cis(65)[c1,p1];
                   2812:        p3 = cis(170)[c1,p1];
                   2813:        p4 = cis(190)[c1,p1];
                   2814:        p5 = cis(300)[c1,p1];
                   2815:        tp = c1+(0,ta)*r1;
                   2816:        bp = c1+(0,tb)*r1;
                   2817:        conn p1 to p2;
                   2818:        conn p2 to p3;
                   2819:        conn p3 to p4;
                   2820:        conn p4 to p5;
                   2821:        conn p5 to p1;
                   2822:        put vert{ midd=c1; llength=(0,1.6)*r1; };
                   2823:        put spot{ loc=tp; };
                   2824:        put spot{ loc=bp; };
                   2825:        left '$P12$' at tp+0.1;
                   2826:        left '$P21$' at bp+0.1;
                   2827:        }
                   2828: box main {
                   2829:        put poly{
                   2830:                c1 =(1,9); r1 = (1,0); ta=1.1; tb=1.4;
                   2831:                left '$++--$' at p2-1.5;
                   2832:                right '(a)' at c1-(0.7,1.2);
                   2833:                };
                   2834:        put poly{
                   2835:                c1 =(3.5,9); r1 = (1,0); ta=1.1; tb=0.2;
                   2836:                left '$+---$' at p2+0.5;
                   2837:                left '$(-+--)$' at p2+(0.5,-0.15);
                   2838:                right '(b)(b1)' at c1-(0.7,1.2);
                   2839:                };
                   2840:        put poly{
                   2841:                c1 =(1,5); r1 = (1,0); ta=1.1; tb=-1;
                   2842:                left '$+--+$' at p2-1.5;
                   2843:                left '$(-++-)$' at p2-(1.5,0.15);
                   2844:                right '(c)(c1)' at c1-(0.7,1.2);
                   2845:                };
                   2846:        put poly{
                   2847:                c1 =(3.5,5); r1 = (1,0); ta=0.2; tb=-1;
                   2848:                left '$---+$' at p2+(0.5,-0.3);
                   2849:                left '$(--+-)$' at p2+(0.5,-0.45);
                   2850:                right '(d)(d1)' at c1-(0.7,1.2);
                   2851:                };
                   2852:        put poly{
                   2853:                c1 =(1,1); r1 = (1,0); ta=-1; tb=-1.4;
                   2854:                left '$--++$' at p4-(0,0.5);
                   2855:                right '(e)' at c1-(0.7,1.2);
                   2856:                };
                   2857:        put poly{
                   2858:                c1 =(3.5,1); r1 = (1,0); ta=0.2; tb=-0.2;
                   2859:                left '$----$' at p1+0.2;
                   2860:                right '(f)' at c1-(0.7,1.2);
                   2861:                };
                   2862: }
                   2863: .P2
                   2864: .NH 1
                   2865: Acknowledgements
                   2866: .PP
                   2867: My thanks to all who read drafts of this manual and
                   2868: criticized constructively:
                   2869: Al Aho,
                   2870: Lorinda Cherry,
                   2871: Eric Grosse,
                   2872: Steve Johnson,
                   2873: Brian Kernighan,
                   2874: John Mashey,
                   2875: Doug McIlroy,
                   2876: and
                   2877: Theo Pavlidis;
                   2878: and to early users of \*(id, especially
                   2879: Eric Grosse,
                   2880: Theo Pavlidis,
                   2881: Norm Schryer,
                   2882: and
                   2883: Peter Weinberger.
                   2884: .NH 1
                   2885: References
                   2886: .LP
                   2887: |reference_placement
                   2888: .FC
                   2889: .BP
                   2890: .2C
                   2891: .EQ
                   2892: delim $$
                   2893: gsize 10
                   2894: .EN
                   2895: .........
                   2896: .NH 1
                   2897: Ideal Reference Manual
                   2898: .PP
                   2899: .I Ideal
                   2900: programs are usually interpolated into
                   2901: .I troff
                   2902: input files.
                   2903: .Tm .IF        S
                   2904: Each program must be preceded by a
                   2905: .CW .IS
                   2906: line, and followed by
                   2907: either a
                   2908: .CW .IE
                   2909: line or a
                   2910: .CW .IF
                   2911: line.
                   2912: The
                   2913: .CW .IE
                   2914: line directs that further text will
                   2915: follow the picture, while the
                   2916: .CW .IF
                   2917: line leaves the current
                   2918: position as it was when the
                   2919: .CW .IS
                   2920: line was encountered.
                   2921: .PP
                   2922: In this description, italicized names refer to nonterminal grammar symbols.
                   2923: A parenthesized construct followed by a star means zero or
                   2924: more repetitions of the construct within.
                   2925: Comments may appear in \*(id programs between
                   2926: .CW /*
                   2927: and
                   2928: .CW */
                   2929: brackets
                   2930: (which nest), and between
                   2931: .CW #
                   2932: and newline.
                   2933: .NH 2
                   2934: Elements of the \*(id Language
                   2935: .PP
                   2936: .I Ideal
                   2937: expects to be presented with a collection of boxes.
                   2938: .I Ideal
                   2939: prepares instructions to draw the picture specified by box
                   2940: .I main .
                   2941: If no such box exists, no picture is drawn, but the definitions
                   2942: that did appear are remembered.
                   2943: A box looks like this:
                   2944: .P1
                   2945: $identifier$ {
                   2946:        $(statement)*$
                   2947: }
                   2948: .P2
                   2949: .LP
                   2950: The sections below describe allowed statements.
                   2951: An $identifier$ is a sequence of letters and digits that starts with a letter.
                   2952: A $string$ is a sequence of characters between double quotes.
                   2953: .NH 3
                   2954: Variable Declarations
                   2955: .P1
                   2956: var $identifier$ $( font CW "," identifier)*$ ;
                   2957: .P2
                   2958: .PP
                   2959: This declares complex variables for which space will be allocated whenever
                   2960: the box in which this statement appears is instantiated.
                   2961: These declarations should appear before any other statements,
                   2962: though this order is not enforced at the moment.
                   2963: .NH 3
                   2964: Equations
                   2965: .P1
                   2966: $expr$ = $expr$ $( ~ font CW "=" ~ expr)*$ ;
                   2967: $expr$ ~ $expr$ $( ~ font CW "~" ~ expr)*$ ;
                   2968: .P2
                   2969: .PP
                   2970: These statements declare relations that should exist among the named variables.
                   2971: Equations that involve more than two expressions to be equated are processed left to right.
                   2972: The second form (an equation with a
                   2973: .CW ~
                   2974: instead of an equals sign)
                   2975: requests that no error message be generated if the equation is inconsistent.
                   2976: Built-in operators include
                   2977: .CW + ,
                   2978: .CW -
                   2979: (both unary and binary),
                   2980: .CW * ,
                   2981: and
                   2982: .CW / ,
                   2983: with unary minus binding more tightly than multiplication
                   2984: and division, which in turn bind more tightly than addition or subtraction.
                   2985: Parentheses may be used to enforce a particular order of evaluation.
                   2986: The expression
                   2987: .P1
                   2988: ( $expr sub 1$ , $expr sub 2$ )
                   2989: .P2
                   2990: .LP
                   2991: has as real part the real part of $expr sub 1$ and as imaginary
                   2992: part the real part of $expr sub 2$.
                   2993: (The parentheses in this example are not metacharacters.)
                   2994: The expression
                   2995: .P1
                   2996: $expr sub 1$ [ $expr sub 2$ , $expr sub 3$ ]
                   2997: .P2
                   2998: .LP
                   2999: is evaluated as $expr sub 2 + expr sub 1 * ( expr sub 3 - expr sub 2 )$,
                   3000: that is
                   3001: ``$expr sub 1$ of the way from $expr sub 2$ to $expr sub 3$.''
                   3002: Built-in functions are described below.
                   3003: .NH 4
                   3004: Manipulating Complex Numbers
                   3005: .P1
                   3006: re ( $expr$ )
                   3007: im ( $expr$ )
                   3008: conj ( $expr$ )
                   3009: .P2
                   3010: .PP
                   3011: These functions return, respectively, the real part, the imaginary part,
                   3012: and the complex conjugate of $expr$.
                   3013: .NH 4
                   3014: Absolute Value
                   3015: .P1
                   3016: abs ( $expr$ )
                   3017: .P2
                   3018: .PP
                   3019: This returns the absolute value of $expr$.
                   3020: .NH 4
                   3021: Unit Vector Functions
                   3022: .P1
                   3023: cis ( $expr$ )
                   3024: E ( $expr$ )
                   3025: unit ( $expr$ )
                   3026: .P2
                   3027: .PP
                   3028: Function $font CW "cis" ()$ returns a unit vector in the direction
                   3029: of its argument,
                   3030: which is interpreted as an angle.
                   3031: For $theta$ in radians, $font CW "cis" ~ theta$ is defined as
                   3032: $e sup { i theta } ~ == ~ cos ~ theta ~ + ~ i sin ~ theta$,
                   3033: and
                   3034: $font CW "E" (x)$ is defined as $font CW "cis" ~ 2 pi x$.
                   3035: If $theta$ is in degrees, which it usually is in
                   3036: .I ideal
                   3037: programs (see below),
                   3038: .I ideal
                   3039: makes the necessary conversion
                   3040: so that $font CW "cis" ()$ and $font CW "E" ()$ work right.
                   3041: .PP
                   3042: Function $font CW "unit" ()$ returns a unit vector in the direction
                   3043: of its argument,
                   3044: which is a vector.
                   3045: For $z$ a complex number,
                   3046: $font CW "unit" (z) ~ == ~ z / font CW "abs" (z)$.
                   3047: .NH 4
                   3048: Floating Truncation
                   3049: .P1
                   3050: int ( $expr$ )
                   3051: .P2
                   3052: .PP
                   3053: This function returns the integer part of the real part of $expr$.
                   3054: .NH 4
                   3055: Inverse Trigonometric Function
                   3056: .P1
                   3057: angle ( $expr$ )
                   3058: .P2
                   3059: .PP
                   3060: This function returns the arctangent of $font CW "im" (expr)/ font CW "re" (expr)$.
                   3061: .NH 3
                   3062: Square Root Function
                   3063: .P1
                   3064: sqrt ( $expr$ )
                   3065: .P2
                   3066: .PP
                   3067: This function returns the square root of its complex argument.
                   3068: .NH 3
                   3069: Line Drawing
                   3070: .P1
                   3071: conn $expr$ to $expr$ $($ to $~ expr)*$ ;
                   3072: .P2
                   3073: .PP
                   3074: This statement directs that lines be drawn between each successive
                   3075: pair of points.
                   3076: .NH 3
                   3077: Box Placement
                   3078: .P1
                   3079: $[ident sub 1 font CW ":" ]$ put $ident sub 2$ { $(statement)*$ } ;
                   3080: put $ident sub 1$ : $ident sub 2$ { $(statement)*$ } ;
                   3081: .P2
                   3082: .PP
                   3083: This statement directs that box $ident sub 2$ be instantiated with the
                   3084: statements in braces prepended to those already present in its definition.
                   3085: If $ident sub 1$ is present in the statement (the optional first form,
                   3086: or the second form), the instantiated box's name is $ident sub 1$,
                   3087: and a local variable $x$ of the box may be referenced as $ident sub 1$.$x$.
                   3088: .NH 3
                   3089: Pen Drawing
                   3090: .P1
                   3091: conn $expr sub 1$ to $expr sub 2$ using $expr sub 3$
                   3092:        $identifier$ { $(statement)*$ }
                   3093:        < $expr sub 4$ , $expr sub 5$ > ;
                   3094: .P2
                   3095: .PP
                   3096: This statement is shorthand for the following loop:
                   3097: .P1 0
                   3098: for i = 1 to $expr sub 3$ by 1
                   3099:        put $identifier$ {
                   3100:                $expr sub 4$ = ((i-1)/$expr sub 3$)
                   3101:                        [$expr sub 1$,$expr sub 2$];
                   3102:                $expr sub 5$ = (i/$expr sub 3$)
                   3103:                        [$expr sub 1$,$expr sub 2$];
                   3104:                $(statement)*$
                   3105:        };
                   3106: .P2
                   3107: .LP
                   3108: Note that it is different from mere text expansion because the upper limit
                   3109: ($expr sub 3$) may not be known explicitly when the program is written.
                   3110: Note too that \*(id does
                   3111: .I not
                   3112: include a for-statement!
                   3113: .NH 3
                   3114: Drawing Splines
                   3115: .P1
                   3116: spline $expr$ to $expr$ $( font CW "to" ~ expr)*$ ;
                   3117: .P2
                   3118: .PP
                   3119: This statement draws a spline guided by the named points in order.
                   3120: .NH 3
                   3121: Placing Captions
                   3122: .P1
                   3123: left $string$ at $expr$;
                   3124: $string$ at $expr$;
                   3125: right $string$ at $expr$;
                   3126: .P2
                   3127: .PP
                   3128: Use these statements to place $string$ at $expr$.
                   3129: The default is to center the string at $expr$.
                   3130: The keyword $"left"$ causes the string to start at $expr$,
                   3131: while the keyword $"right"$ causes the string to end there.
                   3132: .NH 3
                   3133: Constructing and Drawing Boxes
                   3134: .P1
                   3135: construct $ident sub 1$ :
                   3136:        $ident sub 2$ { $(statement)*$ } ;
                   3137: $ident sub 1$ : construct
                   3138:        $ident sub 2$ { $(statement)*$ } ;
                   3139: draw $identifier$ ;
                   3140: .P2
                   3141: .PP
                   3142: The first two of these statements are like the $put$ statements defined above,
                   3143: but they add to a picture named $ident sub 1$, instead of to the current picture.
                   3144: The third directs that the named picture (created by a $construct$ command)
                   3145: be added to the current picture.
                   3146: .NH 3
                   3147: Statements Related to Opaquing
                   3148: .P1
                   3149: boundary = $expr$ , $expr$ $( font CW "," expr)+$ ;
                   3150: opaque [ interior ] ;
                   3151: opaque exterior ;
                   3152: .P2
                   3153: .PP
                   3154: The $boundary$ statement specifies the vertices of a polygon
                   3155: to be opaqued.
                   3156: The first $opaque$ statement directs that the interior of the polygon
                   3157: be opaque.
                   3158: The second directs that the exterior be made opaque.
                   3159: If no boundary list is given for a circle, it will opaque a
                   3160: circular region.
                   3161: To get an opaque circular region without drawing the circle,
                   3162: use the box $hole$ instead.
                   3163: Two other boxes are available for opaquing: $sector$ opaques
                   3164: a sector of an arc and $segment$ opaques a segment of an arc.
                   3165: The variables in these boxes are the same as in $arc$.
                   3166: .NH 2
                   3167: Command-Line Options
                   3168: .PP
                   3169: These options may appear on the command line.
                   3170: .NH 3
                   3171: Selecting the Postprocessor
                   3172: .IP
                   3173: .CW -p
                   3174: .br
                   3175: .CW -4
                   3176: .br
                   3177: .CW -n
                   3178: .PP
                   3179: .I Ideal
                   3180: usually prepares output for processing by
                   3181: .I troff ;
                   3182: all output dimensions are expressed in inches so that
                   3183: .I troff
                   3184: can do the appropriate thing for any typesetter.
                   3185: The
                   3186: .CW -p
                   3187: option directs that the output be generic
                   3188: .I plot
                   3189: output.
                   3190: The
                   3191: .CW -4
                   3192: option causes the output to appear on the screen of a 4014.
                   3193: Both options cause a screen erase at each
                   3194: .CW .IS ,
                   3195: but only the
                   3196: .CW -4
                   3197: option causes a pause for input at each
                   3198: .CW .IE .
                   3199: The screen erase at
                   3200: .CW .IS
                   3201: lines may be suppressed by including the line
                   3202: .P1
                   3203: \&...noerase
                   3204: .P2
                   3205: and may be restored by the line
                   3206: .P1
                   3207: \&...yeserase
                   3208: .P2
                   3209: Option
                   3210: .CW -n
                   3211: directs that the raw
                   3212: .I ideal
                   3213: output remain uninterpreted,
                   3214: so it can be run through
                   3215: .I nroff
                   3216: without harm.
                   3217: .........
                   3218: .NH 3
                   3219: Quality Option
                   3220: .IP
                   3221: .CW -q
                   3222: .PP
                   3223: When
                   3224: .I ideal
                   3225: is used to prepare figures for typeset text,
                   3226: one has a choice of how to draw horizontal and vertical lines.
                   3227: Without the
                   3228: .CW -q
                   3229: option,
                   3230: .I ideal
                   3231: uses rule characters,
                   3232: which draw the lines fast, but may not be accurate.
                   3233: Giving the
                   3234: .CW -q
                   3235: option causes
                   3236: .I ideal
                   3237: to draw all lines,
                   3238: including horizontal and vertical lines, using dots;
                   3239: this takes longer, but is more accurate.
                   3240: .NH 3
                   3241: Angle Processing
                   3242: .IP
                   3243: .CW -r
                   3244: .PP
                   3245: .I Ideal
                   3246: expects angles in degrees.
                   3247: The
                   3248: .CW -r
                   3249: option causes
                   3250: .I ideal
                   3251: to expect them in radians instead.
                   3252: (See also the section on Angle Processing as a command to
                   3253: .I ideal ,
                   3254: below.)
                   3255: .NH 3
                   3256: Including Library Files
                   3257: .IP
                   3258: .CW -l\fIlibfile\fP
                   3259: .PP
                   3260: This causes
                   3261: .I ideal
                   3262: to read the named library file before it begins processing
                   3263: the input files or the standard input.
                   3264: (See also the section on Including Library Files as a command to
                   3265: .I ideal ,
                   3266: below.)
                   3267: .NH 2
                   3268: Commands to Control
                   3269: .I Ideal
                   3270: Processing
                   3271: .PP
                   3272: These commands affect decisions that must be made during the processing of
                   3273: an
                   3274: .I ideal
                   3275: program.
                   3276: They should appear after the
                   3277: .CW .IS
                   3278: delimiter,
                   3279: each on a separate line beginning with three dots.
                   3280: .NH 3
                   3281: Forgetting a Box
                   3282: .P1
                   3283: \&...forget $(boxname)*$
                   3284: .P2
                   3285: .PP
                   3286: All box definitions except the definition of $main$ survive across
                   3287: .CW .IS\fR/\fP.IE
                   3288: boundaries.
                   3289: If you won't need a box again, and memory space is tight, you can
                   3290: use the $forget$ command to reclaim the space its definition requires.
                   3291: Because of implementation deficiencies, at most five names of boxes may
                   3292: appear on one $forget$ line.
                   3293: There is no way to remember the $main$.
                   3294: .NH 3
                   3295: Angle Processing
                   3296: .P1
                   3297: \&...degrees
                   3298: .P2
                   3299: .P1
                   3300: \&...radians
                   3301: .P2
                   3302: .PP
                   3303: .I Ideal
                   3304: expects angles (arguments to $roman "cis"$
                   3305: and the result of $angle$)
                   3306: to appear in degrees,
                   3307: unless it was invoked with the
                   3308: .CW -r
                   3309: option on the command line,
                   3310: in which case it expects angles in radians.
                   3311: These two commands may be used to switch back and forth between
                   3312: degrees and radians.
                   3313: Only one convention may be used within a single
                   3314: .I ideal
                   3315: program,
                   3316: that is between
                   3317: .CW .IS
                   3318: and
                   3319: .CW .IE .
                   3320: .NH 3
                   3321: Including Files
                   3322: .P1
                   3323: \&...libfile $(file)*$
                   3324: \&...include $(file)*$
                   3325: .P2
                   3326: .PP
                   3327: The first command directs that the named library files be interpolated so
                   3328: that their box definitions may be used.
                   3329: The second is a way to include one's own files.
                   3330: The following library files are available:
                   3331: .I arc ,
                   3332: .I arrow ,
                   3333: .I circle ,
                   3334: .I dash ,
                   3335: .I rect ,
                   3336: and
                   3337: .I wavy.
                   3338: .NH 2
                   3339: Commands to the Postprocessor
                   3340: .PP
                   3341: Each of these commands must appear
                   3342: between the
                   3343: .CW .IS
                   3344: and
                   3345: .CW .IE
                   3346: delimiters
                   3347: on a separate line that begins with
                   3348: three dots.
                   3349: .NH 3
                   3350: Defining the Bounding Box
                   3351: .P1
                   3352: \&...minx $number$
                   3353: \&...miny $number$
                   3354: \&...maxx $number$
                   3355: \&...maxy $number$
                   3356: .P2
                   3357: .PP
                   3358: The
                   3359: .I ideal
                   3360: processor computes the minimum and maximum extent of the
                   3361: picture in both $x$- and $y$-directions so that the bounding box
                   3362: (hence, the picture) can be scaled to the desired width.
                   3363: These commands allow you to override
                   3364: .I ideal 's
                   3365: computed bounding box.
                   3366: They are useful when the computed bounding box is too large or too small.
                   3367: .I Ideal
                   3368: cannot compute the bounding box of a string, so it doesn't try,
                   3369: and this may be too liberal.
                   3370: .PP
                   3371: Normally these dimensions are computed anew for each picture produced
                   3372: by
                   3373: .I ideal .
                   3374: Use the line
                   3375: .P1
                   3376: \&...obbox
                   3377: .P2
                   3378: between subsequent
                   3379: .CW .IS
                   3380: and
                   3381: .CW .IE\fR/\fP.IF
                   3382: lines to keep the
                   3383: bounding box of the previous picture.
                   3384: .NH 3
                   3385: Setting the Picture Width
                   3386: .P1
                   3387: \&...width $number$
                   3388: .P2
                   3389: .PP
                   3390: This command causes the bounding box to be scaled to a width of $number$
                   3391: inches.
                   3392: (If not specified, the default is four inches.)
                   3393: It persists across
                   3394: .CW .IS\fR/\fP.IE
                   3395: boundaries.
                   3396: .NH 3
                   3397: Setting the Picture Height
                   3398: .P1
                   3399: \&...height $number$
                   3400: .P2
                   3401: .PP
                   3402: This command causes the bounding box to be scaled to a height of $number$
                   3403: inches.
                   3404: This allows one to impose a different scale on the horizontal and vertical
                   3405: dimensions of a picture.
                   3406: The setting persists across
                   3407: .CW .IS\fR/\fP.IE
                   3408: boundaries.
                   3409: ........
                   3410: .NH 3
                   3411: Setting the Column Width
                   3412: .P1
                   3413: \&...colwid $number$
                   3414: .P2
                   3415: .PP
                   3416: This command gives the width of the column in which the picture will appear
                   3417: so that it can be centered in the column.
                   3418: (If not specified, the default is six inches.)
                   3419: The setting persists across
                   3420: .CW .IS\fR/\fP.IE
                   3421: boundaries.
                   3422: .NH 3
                   3423: Using Postprocessor Commands to Scale Pictures
                   3424: .PP
                   3425: The bounding box and width information can be adjusted
                   3426: to scale the picture or move it on the page.
                   3427: .I Ideal
                   3428: does not check that the entire picture is in fact
                   3429: contained in the bounding box, and it cannot check
                   3430: that the column width is correct:
                   3431: it uses the bounding box information to scale the
                   3432: picture to the width requested,
                   3433: then uses the column width to center the bounding box.
                   3434: .PP
                   3435: For example, to produce figures at the right of the
                   3436: page,
                   3437: .I ideal
                   3438: was told that the column was nine inches wide.
                   3439: Since the pictures are typically no more than two inches
                   3440: wide, they lie within the actual six inch column.
                   3441: .PP
                   3442: Suppose one's
                   3443: figures are drawn in the unit square,
                   3444: though some pieces lie a little outside,
                   3445: and one wants one inch to correspond to one in \*(id's
                   3446: coordinate system.
                   3447: One could set the six parameters as follows:
                   3448: .P1
                   3449: \&...minx 0
                   3450: \&...miny 0
                   3451: \&...maxx 1
                   3452: \&...maxy 1
                   3453: \&...width 1
                   3454: \&...colwid 6
                   3455: .P2
                   3456: .LP
                   3457: This gives a way for
                   3458: users to get exact scale
                   3459: representations of their pictures.
                   3460: .NH 2
                   3461: Obsolete Features
                   3462: .PP
                   3463: These holdovers from earlier implementations are not guaranteed to survive.
                   3464: .NH 3
                   3465: Options on the
                   3466: .CW .IS
                   3467: Line
                   3468: .PP
                   3469: One could specify the bounding box on the
                   3470: .CW .IS
                   3471: line by
                   3472: .P1
                   3473: \&.IS minx maxy maxx miny
                   3474: .P2
                   3475: .LP
                   3476: The bounding box commands to the postprocessor are now preferred.
                   3477: .NH 3
                   3478: Changes to Keywords
                   3479: .PP
                   3480: The keyword $box$ used to be required before a box definition.
                   3481: .PP
                   3482: The keyword $boundary$ has replaced $bdlist$.
                   3483: .PP
                   3484: The function $angle$ used to be called $atan2$.
                   3485: .NH 3
                   3486: String Delimiters
                   3487: .PP
                   3488: Strings used to be delimited by single quotes.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.