There are various ways of declaring and initializing Paths. The
simplest is to use the constructor taking two Point arguments:
Point A;
Point B(2, 2);
Path p(A, B);
p.draw();
Fig. 9.
Paths created in this way are important, because they are
guaranteed to be linear, as long as no operations are performed on them
that cause them to become non-linear.
Linear Paths can be used to find intersections.
See Path Intersections.
Paths can be declared and initialized using a single connector
and an arbitrary number of Points. The first argument is a
string specifying the connector. It is followed by a
bool, indicating whether the
Path is cyclical or not. Then, an arbitrary number of
pointers to Point follow. The last argument must be 0.1
Point p[3];
p[0].shift(1);
p[1].set(1, 2, 2);
p[2].set(1, 0, 2);
Path pa("--", true, &p[0], &p[1], &p[2], 0);
pa.draw();
Fig. 10.
Another constructor must be used for Paths with
more than one connector and an arbitrary number of Points.
The argument list starts with a pointer to Point, followed by
string for the first connector. Then,
pointer to Point arguments alternate with string arguments
for the connectors.
Again, the list of arguments ends in 0. There is no
need for a bool to indicate whether the Path is cyclical
or not; if it is, the last non-zero argument will be a connector,
otherwise, it will be a pointer to Point.
Point p[8];
p[0].set(-2);
p[1].set(2);
p[2].set(0, 0, -2);
p[3].set(0, 0, 2);
p[4] = p[0].mediate(p[2]);
p[5] = p[2].mediate(p[1]);
p[6] = p[1].mediate(p[3]);
p[7] = p[3].mediate(p[0]);
p[4] *= p[5] *= p[6] *= p[7].shift(0, 1);
Path pa(&p[0], "..", &p[4], "...", &p[2],
"..", &p[5], "...", &p[1], "..", &p[6],
"...", &p[3], "..", &p[7], "...", 0);
pa.draw();
Fig. 11.
As mentioned above (see Accuracy), specifying connectors is
problematic for three-dimensional Paths,
because MetaPost ultimately calculates the “most pleasing curve”
based on the two-dimensional points in the MetaPost code written by
3DLDF.2
For this reason, it's advisable to avoid specifying ‘curl’,
‘dir’, ‘tension’ or control points in connectors.
The more Points a (3DLDF) Path or other object contains,
the less freedom MetaPost has to determine the (MetaPost) path
through them.
So a three-dimensional Path or
other object in 3DLDF should have enough Points to ensure
satisfactory results. The Path in [the previous figure]
does not
really have enough Points. It may require some trial and error
to determine
what a sufficient number of Points is in a given case.
Paths are very flexible, but not always convenient. 3DLDF
provides a number of classes representing common geometric
Shapes, which will be described in subsequent sections, and I
intend to add more in the course of time.
[1] It's easy to forget to use Point* arguments, rather
than plain Point arguments, and to forget to end the list of
arguments with 0. If plain Point arguments are used, compilation
fails with GCC. With the DEC compiler, compilation succeeds, but a
memory fault error occurs at run-time. If the argument list doesn't end
in 0, neither compiler signals an error, but a memory fault error always
occurs at run-time.
[2] Knuth, The METAFONTbook, Chapter 14, p. 127.