# MetaPost

Paradigm Imperative John D. Hobby 1994 1.902 / 23.04.2014 Implicit, Dynamic, Strict metapost

MetaPost is a programming language and the interpreter of the MetaPost programming language. Both are derived from Donald Knuth's Metafont language and interpreter. MetaPost excels at producing diagrams in the PostScript programming language from a geometric/algebraic description. The language shares Metafont's elegant declarative syntax for manipulating lines, points and others. The limitations of MetaPost derive from features of Metafont. For example, numbers have a low-precision fixed-point representation, sufficient for representing the coordinates of points in a glyph, but this can be restrictive when working with figures in a larger coordinate space. Moreover, MetaPost does not support all features of PostScript.

## Compilation

A typical METAPOST source file consists of one or more figures. Compilation of the source file generates an EPS graphic for each figure. These EPS graphics are not self-contained in that fonts used in labels are not embedded into the graphic. If foo.mp is a typical METAPOST source file, then its contents are of the following form:

 beginfig(1);
draw commands
endfig;
beginfig(2);
draw commands
endfig;
...
beginfig(n);
draw commands
endfig;
end;

Executing

 mpost foo.mp

yields the following output:

 This is MetaPost, Version hversioni
(foo.mp [1] [2] . . . [n] )
n output files written: foo.1 .. foo.n
Transcript written on foo.log.

For users who just want to “get started” using METAPOST, a METAPOST previewer is available at http://www.tlhiv.org/MetaPostPreviewer. This previewer is simply a graphical interface to METAPOST itself. It generates a single graphic with the option to save the output in both EPS and PDF formats. Users may also choose to save the source code and can view the compilation log to assist in debugging.

## Data types

### Standart data types

There are ten data types in METAPOST. These data types allow users to store fragments of the graphics for later use. We will briefly discuss each of these data types and elaborate on how they are used in a typical METAPOST program.

• numeric — numbers
• pair — ordered pairs of numerics
• path — Bézier curves (and lines)
• picture — pictures
• transform — transformations such as shifts, rotations, and slants
• rgbcolor or color — triplets with each component between 0 and 1 (red, green, and blue)
• cmykcolor — quadruplets with each component between 0 and 1 (cyan, magenta, yellow, and black)
• string — strings of characters
• boolean— “true” or “false” values
• pen — stroke properties

Virtually all programming languages provide a way of storing and retrieving numerical values. This is precisely the purpose of the numeric data type in METAPOST. Since graphics drawn with METAPOST are simply two dimensional pictures, it is clear that an ordered pair is needed to identify each point in the picture. The pair data type provides this functionality. Each point in the plane consists of an x (i.e., abscissa) part and a y (i.e., ordinate) part. METAPOST uses the standard syntax for defining points in the plane, e.g., (x, y) where both x and y are numeric data typed variables.

The following code declares a variable of type numeric, one of type pair, and two string variables:

 numeric idx;
pair v;
string s, name;

Note, variables of type numeric need not necessarily be declared. A formerly undeclared variable is automatically assumed to be numeric at first use.

### Arrays

Just like many other programming languages MetaPost provides a way to access variables by index. After the following variable declaration

 pair a[];

it is possible to store points in the “array” a with numeric values as index. The console output of

 a[1] := (0,1);
a[2] := (0,5);
a[3] := (10,20);
show a[1];
show a1;
j := 2;
show a[j] + a[j+1];

is

 >> (0,1)
>> (0,1)
>> (10,25)

Notice, the point stored at array index 1 can be referred to as a[1] as well as just a1, omitting the brackets. The latter convenient—and often practised—notation works as long as the index is a plain numeric value. If the index is a numeric variable or an expression, however, the brackets have to be present, since, e.g., aj would clearly refer to an unrelated variable of that name instead of index j of variable a.

Aside, MetaPost, as a macro language, doesn’t really provide true arrays. However, from a user’s perspective, the MetaPost way of indexing variables perfectly looks like an array.

## Common commands

### Draw command

The most common command in METAPOST is the draw command. This command is used to draw paths or pictures. In order to draw a path from z1:=(0,0) to z2:=(54,18) to z3:=(72,72), we should first decide how we want the path to look. For example, if we want these points to simply be connected by line segments, then we use

 draw z1--z2--z3;

However, if we want a smooth path between these points, we use

 draw z1..z2..z3;

In order to specify the direction of the path at the points, we use the dir operator. Constraints on the Bézier curve are imposed by

 draw z1{right}..z2{dir 45}..{up}z3;

Notice that z2{dir 45} forces the outgoing direction at z2 to be 45 degrees. This implies an incoming direction at z2 of 45 degrees. In order to require different incoming and outgoing directions, we would use

 draw z1{right}..{dir θi}z2{dir θo}..{up}z3;

### Fill command

Another common command in METAPOST is the fill command. This is used to fill closed paths (or cycles). In order to construct a cycle, cycle may be appended to the path declaration. For example,

 path p;
p := z1{right}..z2{dir 45}..{up}z3--cycle;
fill p withcolor red;
draw p;

Just as it is necessary to fill closed paths, it may also be necessary to unfill closed paths. For example, the annulus can be constructed by

 color bbblue;
bbblue := (3/5,4/5,1);
path p,q;
p := fullcircle scaled (2*54);
q := fullcircle scaled (2*27);
fill p withcolor bbblue;
unfill q;
draw p;
draw q;

The fullcircle path is a built-in path that closely approximates a circle in METAPOST with diameter 1 bp traversed counter-clockwise. This path is not exactly a circle since it is parameterized by a Bezier curve and not by trigonometric functions; however, visually it is essentially indistinguishable from an exact circle.

### Arrow commands

When drawing simple graphs and other illustrations, the use of arrows is often essential. There are two arrow commands in METAPOST for accommodating this need—drawarrow and drawdblarrow. Both of these commands require a path argument. For example,

 drawarrow (0,0)--(72,72);

draws an arrow beginning at (0,0) and ending at (72,72) along the line segment connecting these points.

### Label command

Almost all figures in technical documents are accompanied by labels which help clarify the situation for which the figure is assisting to illustrate. The label command requires two arguments — a string to typeset and the point for which label is placed. For example, the command

 label("A", (0,0));

will place the letter “A” at the coordinate (0,0) and the box around this label is centered vertically and horizontally at this point. Simple strings like "A" require no real typesetting to ensure that they appear properly in the figure.

## Graphics functions

Among the most common types of figures for TEX users are those which are the graphs of functions of a single variable. Hobby recognized this and constructed a package to accomplish this task. It is invoked by

 input graph;

METAPOST has the ability to construct data (i.e., ordered pairs) for graphing simple functions. However, for more complicated functions, the data should probably be constructed using external programs such as MATLAB (or Octave), Maple, Mathematica. A typical data file, say data.d, to be used with the graph package may have contents

 0.0 0.0
0.2 0.447214
0.4 0.632456
0.6 0.774597
0.8 0.894427
1.0 1.0

This data represents the graph of f(x) = ${\displaystyle {\sqrt {x}}}$ for six equally spaced points in [0, 1]. To graph this data, the size of the graph must first be decided. Choosing a width of 144 bp and a height of 89 bp, a minimally controlled plot of this data can be generated by

 draw begingraph(144bp,89bp);
gdraw "data.d";
endgraph;

The graph package provides many commands used to customize generated graphs, and these commands are fully documented in the manual for the graph package.