Полезная информация

Previous Page TOC Next Page Home

25 — Drawing Pictures with pic

By Susan Peppard

pic is rarely your first choice as a drawing tool. With pic you can draw lines and a limited variety of shapes—no color, no shading—but 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 capabilities—except for color—of the sophisticated packages, and they don't require a knowledge of pic. xcip produces pic code, which—and here's the point—you 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.

The Basics

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 them—you're not required to—the 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.

Required Macros and Primitives

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 picture—where 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 height—or both—of the final picture


CAUTION: If you have a space after the .PS and no measurements, your figure will be enlarged proportionally so that its width is the current width (line length) of your pages.

To insert comments in pic code, begin a line with #.

Forbidden Macros and Primitives

Whatever you do, don't include any spacing requests—.sp, .ls, .vs, .SP, and .P—inside your pic code. pic does its own spacing, and it gets really annoyed if you interfere. Use the move command instead.

Adding Text

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


NOTE: To right or left justify text, use rjust or ljust.

The preceding examples are troff escape sequences and are discussed further in Chapter 21, "Basic Formatting with troff/nroff."

Default Placement of Objects

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.

Connecting Objects

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


NOTE: When you write pic code, you specify one command per line, or you can separate commands with semicolons. Long lines require the continuation symbol (\).

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.


TIP: To draw a line with an arrow at both ends, use line <-> or arrow <->. This might seem obvious, but for seven years I drew two-headed arrows using the arrow command twice—drawing a right-pointing arrow over a left-pointing arrow—because nobody told me about <->.

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.

More about Placement

To avoid having to think like pic—an exercise that can be dangerous to your mental health—you 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

NOTE: You can use terms like upper left and lower right, but not top left and lower bottom.

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

TIP: If you reference objects by their centers, you don't have to worry about where pic starts a new object or in which direction the new object is drawn.

These notations—left, right, .ne, .sw, and so on—assume 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.

Additional Shapes and Functions

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

Controlling Size

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 width—or both—on the .PS line. Usually it's better to specify only the width. If you specify both dimensions, your picture may be distorted.


NOTE: For some reason, you must specify the width first. For example, .PS 2 4 produces a picture 2 inches wide and 4 inches long. This is the opposite of the order in which you specify the dimensions of a box or ellipse. The width and height you specify refer to the whole picture.

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.


CAUTION: Text is not scaled. If your text needs resizing, you must do it with \s, and it's usually a matter of trial and error to find out what will fit in your scaled figure.

Object Blocks

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

Macros and Variables

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 SQ—or whatever you've named your macro.

Debugging

When you're dealing with pic, you aren't troubleshooting—you'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 long—you meant 1.625 inches—on 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.

pic Tips and Tricks

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.

Summary

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.

Previous Page TOC Next Page Home