Node:Declaring and Initializing Paths, Next:Drawing and Filling Paths Intro, Previous:Paths, Up:Paths
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.
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.
Knuth, The METAFONTbook, Chapter 14, p. 127.