MetaPost Curves
A draw
statement with the points separated by .. draws a smooth curve through the points. For example consider the result of
z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); draw z0..z1..z2..z3..z4
There are many other ways to draw a curved path through the same five points. To make a smooth closed curve, connect z4 back to the beginning by appending ..cycle
to the draw statement.
MetaPost already provides a small selection of basic path shapes that can be used to derive custom paths from. The predefined variable fullcircle
refers to a closed path describing a circle of unit diameter centered on the origin. There are also halfcircle
and quartercircle
, the former being the part of a full circle covering the first and second quadrant and the latter covering just the first quadrant. Because of the mathematical model that is used to describe paths in MetaPost, all these are not exactly circular paths, but very good approximations.
Rectangularly shaped paths can be derived from unitsquare
, a closed path describing a square of unit side length whose lower left corner is located at the origin.
Bézier Cubic Curves
This is how a closed line made from cubic Bézier curves looks:
The curve has been made to run through six points, and the angle at those points as well as the tension or taughtness (as in a rope) is shown through tangent lines between control points.
And this is an open line made from cubic Bézier curves through the same six on-line points:
This is the model that MetaPost follows and that will be discussed next.
When MetaPost is requested to draw a (smooth) curve through a sequence of points, it constructs a piecewise cubic curve with continuous slope and approximately continuous curvature. This means that a path specification such as
z0..z1..z2..z3..z4..z5
MetaPost allows the control points to be specified directly in the following format:
draw (0,0)..controls (26.8,-1.8) and (51.4,14.6) ..(60,40)..controls (67.1,61.0) and (59.8,84.6) ..(40,90)..controls (25.4,94.0) and (10.5,84.5) ..(10,70)..controls ( 9.6,58.8) and (18.8,49.6) ..(30,50);
Specifying Direction, Tension, and Curl
MetaPost provides many ways of controlling the behavior of a curved path without actually specifying the control points. For instance, some points on the path may be selected as vertical or horizontal extrema. If z1 is to be a horizontal extreme and z2 is to be a vertical extreme, you can specify that (X(t), Y (t)) should go upward at z1 and to the left at z2:
draw z0..z1{up}..z2{left}..z3..z4;
Curves used in MetaPost come from a family where a path is determined by its endpoints and the directions there.
beginfig(7) for a=0 upto 9: draw (0,0){dir 45}..{dir -10a}(6cm,0); endfor endfig;
or
beginfig(8) for a=0 upto 7: draw (0,0){dir 45}..{dir 10a}(6cm,0); endfor endfig;
The dir operator takes an angle in degrees and generates a unit vector in that direction. Thus dir 0
is equivalent to right
and dir 90
is equivalent to up
. There are also predefined direction vectors left
and down
for dir 180
and dir 270
.
The direction vectors given in {}
can be of any length, and they can come before a point as well as after one. It is even possible for a path specification to have directions given before and after a point. For example a path specification containing
..{dir 60}(10,0){up}..
produces a curve with a corner at (10, 0).
Note that some of the curves have points of inflection. This is necessary in order to produce smooth curves, but it is probably not desirable when dealing with vertical and horizontal extreme points.
draw z0{up}..z1{right}..z2{down}
If, say, z1 is supposed to be the topmost point on the curve, this can be achieved by using ...
instead of ..
in the path specification. The meaning of ... is choose an inflection-free path between these points unless the endpoint directions make this impossible.
As in
draw z0{up}...z1{right}...z2{down}
Another way to control a misbehaving path is to increase the tension parameter. Using ..
in a path specification sets the tension parameter to the default value 1. If this makes some part of a path a little too wild, we can selectively increase the tension. If Figure 11a is considered too wild,
a draw statement of the following form increases the tension between z1 and z2:
draw z0..z1..tension 1.3..z2..z3
For an asymmetrical effect, the draw statement becomes
draw z0..z1..tension 1.5 and 1..z2..z3
MetaPost paths also have a parameter called curl that affects the ends of a path. In the absence of any direction specifications, the first and last segments of a non-cyclic path are approximately circular arcs. To use a different value for the curl parameter, specify {curl c}
for some other value of c. Thus
draw z0{curl c}..z1..{curl c}z2
sets the curl parameter for z0 and z2. Small values of the curl parameter reduce the curvature at the indicated path endpoints, while large values increase the curvature. In particular, a curl value of zero makes the curvature approach zero.