pic is rarely your first choice as a drawing tool. With pic you can draw lines and a limited variety of shapesno color, no shadingbut you can create a complex and detailed picture, if you're willing to work at it. pic was developed before
everyone had personal computers with sophisticated, mouse-based drawing packages. Today, troff users with graphics terminals can use mouse-based programs such as xcip. These programs provide many of the capabilitiesexcept for colorof the
sophisticated packages, and they don't require a knowledge of pic. xcip produces pic code, whichand here's the pointyou can edit if you know pic.
pic is no substitute for a sophisticated drawing tool. It doesn't have color. It provides shading only inside boxes, circles, and ellipses. It doesn't even let you draw a randomly wiggly line.
To draw a box, type
.PS box ht 1 wid 1.25 .PE
The result is
This example specifies a height and a width. If you don't specify themyou're not required tothe box will be three-quarters inch high and one-half inch wide.
You can draw circles. For example,
.PS circle rad .5 .PE
produces
You can draw ellipses, too. For example,
.PS ellipse ht .5 wid 1.25 .PE
produces
The default pic unit is inches. pic has default sizes for boxes, circles, and ellipses. The pic default sizes are listed in the "Controlling Size" section later in this chapter.
troff recognizes pic code by its opening and closing macros: .PS and .PE. ms includes a .PF macro for picture flyback. This macro restores you to your last position on the page (vertically and horizontally) before the picturewhere you were before
you invoked pic. This feature is rarely used; some pic users surround their pic code with display macros and specify no-fill mode. For example,
.DS .nf .PS .box ht 1 wid 1.25 . . .PE .DE
This might look like overkill, but mm likes it.
The .PS macro also can be used to do the following:
.PS < filename |
Sources in a pic file; imports an external file called filename and allows it to be processed as if filename were part of your text file. |
.PS wid ht |
Enables you to specify the width or the heightor bothof the final picture |
To insert comments in pic code, begin a line with #.
Whatever you do, don't include any spacing requests.sp, .ls, .vs, .SP, and .Pinside your pic code. pic does its own spacing, and it gets really annoyed if you interfere. Use the move command instead.
You can put labels in these basic pic shapes. Consider the following code:
.PS box ht .75 wid .75 "A Square" move box ht .75 wid .75 "Another" "Square" .PE
It produces
Each line of text is enclosed in its own set of quotation marks.
pic attempts to center your text, both vertically and horizontally, which isn't helpful if you want to label a line. For example,
.PS line right 1i "line" .PE
comes out looking like
Fortunately, pic recognizes the words above and below, so you can position your text so that it is more readable. If you have two lines of text, pic puts one above the line and one below it. For example,
.PS line right 1i "over" "under" .PE
produces
pic doesn't object if you want to specify the font and point size for your text, so long as you keep the specifications inside the quotation marks. For example,
.PS line right 1i "\f(HB\s12over" "under\fP\s0" .PE
produces
The preceding examples are troff escape sequences and are discussed further in Chapter 21, "Basic Formatting with troff/nroff."
pic assumes that all objects it draws should touch one another. Therefore, if you specify
.PS box ht .5 wid 1 "Box 1" box ht .5 wid 1 "Box 2" .PE
you will get
Fortunately, pic has a move command, which you can use to separate the boxes. For example,
.PS box ht .5 wid 1 "Box 1" move box ht .5 wid 1 "Box 2" .PE
produces
The move command's default direction is to the right. Its default distance is one-half inch. You can change these defaults by specifying a direction and a distance, as in
.PS box ht .5 wid 1 "Box 1" move left 2i box ht .5 wid 1 "Box 2" .PE
Now the boxes look like
Note that the distance between the two boxes is actually one inch, not the two inches you specified in the move command. The reason is that pic measures from center to center, not from edge to edge.
pic is especially suited for charts and flow diagrams. Consider the following code:
.PS box; line; box move right li box; arrow; box .PE
It produces
As you can see from the code and the figure, arrow is a synonym for line.
The following commands are useful as well:
line -> |
Draws an arrowhead at the end of the arrow. It doesn't necess-arily point to the right. |
line <- |
Draws an arrowhead at the beginning of the arrow. It doesn't necessarily point to the left. |
line <-> |
Draws arrowheads on both ends of the arrow. |
Suppose that you want Box 2 directly under Box 1. Consider the following code:
.PS box "Box 1" move down box "Box 2" .PE
It produces
The problem with this code is that pic moves half an inch from wherever it left off drawing the first box, which in this case is the middle of the box top. To place Box 2 correctly, you have to move down another one-half inch and to the left:
.PS box "Box 1" move left .375i move down .75i box "Box 2" .PE
Figure 25.1 shows you the result.
Figure 25.1. Two boxes positioned correctly.
This is a nuisance, to say the least, because in a complicated drawing you quickly lose track of where pic begins and ends each element of the drawing. You can use reference points with pic so that you know where each element of your drawing will be
placed. They are discussed in the next section.
To avoid having to think like pican exercise that can be dangerous to your mental healthyou can refer to parts of objects that you've drawn. pic recognizes all of the following:
.l left |
.ne northeast |
.r right |
.nw northwest |
upper |
bottom |
lower |
start |
.t top |
end |
.n north |
1st |
.e east |
2nd |
.w west |
3rd (and so on) |
.s south |
last |
.nw northwest |
2nd last |
.sw southwest |
3rd last (and so on) |
pic also understands compass points. Figure 25.2 shows the parts of a pic element to which you can refer.
Figure 25.2. pic reference points.
The position notation words and the compass points enable you to specify positions like these:
line from upper right of 2nd last box to upper left of last box arrow from 1st circle.e to 2nd circle.w box at end of last line move left 1i from start of last box line from Box.c to Box.s move down 1i from bottom of 2nd last ellipse
Now you have several ways of specifying the two boxes shown in Figure 25.1. You could write
.PS box "Box 1" move to last box.s down .5 box "Box 2" .PE
or you could write
.PS box "Box 1" move to bottom of last box down .5 box "Box 2" .PE
If you want to avoid the wordiness of bottom of last box, you can label your construct
B1: box "Box 1"
Labels must begin with a capital letter.
Using labels enables you to specify the two boxes as follows:
.PS B1:box "Box 1" B2:box with .c down 1i from B1.c "Box 2" .PE
These notationsleft, right, .ne, .sw, and so onassume that you can tell left from right and east from west. If you are directionally challenged like me, you should allow extra debugging time for your pics. I've tried sticking scraps of paper
labelled left/west and right/east on the sides of my monitor. It helps a little.
pic comes to your rescue with a solution. It understands Cartesian coordinates, as shown in Figure 25.3.
Figure 25.3. x,y coordinates.
Again, the unit is inches. The important thing to remember is that your first object starts at 0,0. In other words, the coordinates are relative. There is no specific location on a page or in a drawing that is always 0,0. It depends on where you start.
Cartesian coordinates enable you to specify the two boxes shown in Figure 25.1 as
.PS box at 0,0 "Box 1" box at 0,-1 "Box 2" .PE
You'll probably find this easier.
pic also has an invis command. At first glance, it doesn't seem very useful. How often do you expect to draw a page full of invisible boxes? The real advantage of invis is in placing text. Consider Figure 25.4.
Figure 25.4. Using invisible lines.
Placing those pesky dots could be a problem. Using invis, though, makes it easy. The code that produces Figure 25.4 is
.PS box; move; box line invis .75 "\s12 . . . \s0" box .PE
There are other uses for invis. You can use it, for example, to define a large area in which you will be drawing several smaller objects and to provide compass points outside a smaller object.
pic includes two more shapes in addition to the ones you've already seen. They are the arc and the spline.
To pic, an arc is a quarter of a circle. You can use the arc command to draw a circle, as in
.PS arc; arc; arc; arc .PE
A more sensible use of arc is to draw a rectangle with rounded corners. For example,
.PS line left; arc; line down; arc line right; arc; line up; arc .PE
To make a spiral like the one shown in Figure 25.5, combine a series of arcs. For example,
.PS arc rad .04 arc rad .08 arc rad .12 arc rad .16 arc rad .20 arc rad .24 arc rad .28 arc rad .32 arc rad .36 arc rad .40 arc rad .44 arc rad .48 .PE
produces the following:
Figure 25.5. A spiral made of arcs.
pic also recognizes trigonometric and other mathematical functions:
atan2 |
(e1, e2) |
the arctangent of e1, e2 |
cos |
|
cosine of e (e must be in radians) |
exp |
|
10e |
int |
|
integer part (by truncation) |
log |
|
logarithm base 10 of e |
max |
(e1, e2) |
maximum of e1 and e2 |
min |
(e1, e2) |
minimum of e1 and e2 |
rand |
(n) |
random number between 1 and n |
sin |
|
sine of e (e must be in radians) |
sqrt |
|
square root of e |
These functions must be followed by an expression in parentheses. In the case of atan2, max, and min, two expressions must follow. rand is followed by empty parentheses and produces a random number between 0 and 1.
Lines and shapes don't have to be solid. You can draw dotted and dashed objects. Consider the following code.
.PS B1: box move to B1.n up .05 right .05 B2: box dashed move to B2.n up .05 right .05 B3: box dotted .PE
pic variables include several that specify the default size of pic objects. Table 25.1 lists these variables and their default values.
Variable |
Default Value |
Variable |
Default Value |
arcrad |
.25i |
ellipsewid |
.75i |
arrowhead |
2i |
lineht |
.5i |
arrowht |
.1i |
linewid |
.75i |
arrowwid |
.05i |
moveht |
.5i |
boxht |
.5i |
movewid |
.75i |
boxwid |
.75i |
scale |
1i |
circlerad |
.25i |
textht |
0i |
dashwid |
.5i |
textwid |
0i |
ellipseht |
.5i |
|
|
arrowwid and arriowht refer to the arrowhead. The arrowhead variable specifies the fill style of the arrowhead.
It's easy to change the value of a variable. For example,
boxht = .75; boxwid = .5
Remember: The default unit for pic is inches.
There are other ways of controlling the size of a picture. You can specify a height or a widthor bothon the .PS line. Usually it's better to specify only the width. If you specify both dimensions, your picture may be distorted.
You can also set the variable scale. By default, scale is set at 100 or 1, depending on your version of pic. (You can test this by scaling a drawing to 1.5. If you get an error message or a garbled result, use 150.) All the dimensions in a pic drawing
are divided by the scaling factor. Therefore, if the scale is normally 1 and you set it to 4, your 1-inch lines will be a quarter-inch long. For example,
.PS scale = 2 box ht 2i wid 2i .PE
This code produces a box scaled down to half the size of its specifications, that is, a 1- inch square.
You can define any sequence of objects or moves as a block, which you can manipulate almost as if it were a simple box. You need to name the block. The name must begin with an uppercase letter. Although pic places no specific restrictions on the length
of the name, shorter is better.
Object blocks are useful when you are placing text.
You can also position an object block easily, as in
.PS C1: circle rad .125 Spiral [ arc rad .04 arc rad .08 arc rad .12 arc rad .16 arc rad .20 arc rad .24 arc rad .28 arc rad .32 arc rad .36 arc rad .40 arc rad .44 arc rad .48 ] with .s at C1.n .PE
If you want to reuse an object, you can put it in a file by itself and use the copy function:
.PS <pic code> copy filename <pic code> .PE
You can also define a pic macro. Don't confuse pic macros with troff macros. In the broadest sense, a macro is a short way of referring to a complex process. In other words, a pic macro is just a collection of pic commands that have been given a name.
Unlike object blocks, which merely give you a convenient way of referring to positions in and around the object, macros can be used to draw objects. The first three lines of the following code sequence enable you to draw the defined object by invoking
its name, as shown in the last line.
.PS define SQ % box ht .5 wid .5 % SQ; move; SQ .PE
This code produces
To create a macro, use the word define followed by a name for your macro and a delimeter. Next come all your pic instructions and finally, another delimeter. In the first example, I used % for delimeters. In the second example, I used curly braces.
There is no default. The choice is yours.
Macros can have up to nine arguments, specified $1 through $9. For example, you can define a square and supply the dimensions as arguments when you invoke the macro, as shown in the first three lines of the following code. The last line produces the 1/2
inches square shown in Figure 25.6.
.PS define SQ } box ht $1 wid $1 "$2" { SQ(.5, square) .PE
produces
Figure 25.6. Squares Created with a Macro
Macro definitions require delimiters. As you can see, though, the choice is up to you. Percent signs (%) are usual choices. When you invoke the macro, the arguments go in parentheses.
Macro definitions persist throughout a file. If you ever have to get rid of a macro, use undef SQor whatever you've named your macro.
When you're dealing with pic, you aren't troubleshootingyou're debugging. It's much easier to do this as you code. Draw the first element of your picture. Before you print it, send the file through pic to see whether any error messages are
generated. If your file contains only pic, you can do this:
pic filename
If your file contains text, just use your normal troff command line. However, instead of sending the file to a printer, redirect your output to /dev/null. See Chapter 28, "Tools for Writers," for more information on directing output to
/dev/null.
pic tries to help you pinpoint your errors with messages similar to the following:
pic: syntax error near line 26 context is >>> linr <<< left 1i
Occasionally, pic tells you that it has reduced the size of your picture. This is almost always because you've made a mistake. Most often, you've left out a decimal point, and pic is trying to fit a line 1625 inches longyou meant 1.625
incheson an 8.5-inch page. When this happens, your picture naturally is mangled out of all recognition.
Usually, your debugging involves the placement of objects and the placement or size of text.
If you can't get an object placed correctly by moving down and left (or up and right) from an object, try referring to both objects by their centers, as in box.c.
If your drawing involves a number of objects and placement is crucial, use x,y coordinates.
If you're having trouble placing text, remember over and under.
Using a box invis or a line invis to place your text usually works well.
Make yourself a library of pic drawings so that you don't have to keep reinventing the spiral.
pic is a troff preprocessor for drawing lines, arrows, boxes, circles, ellipses, arcs, and splines. Output tends to vary from system to system, so be prepared to spend some time debugging. pic is well worth the trouble if you frequently include simple
graphics in text files. It is especially useful for organization charts, flow charts, state diagrams, and the like.