Annotation of researchv10dc/vol2/ideal/user.ms, revision 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.