Node: Declaring and Initializing Paths, Next: , Previous: Paths, Up: Paths

Declaring and Initializing 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.

Footnotes

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.