Next: Pens, Previous: Data types, Up: Programming
path
nullpath
.
The routine circle(pair c, real r)
, which returns a Bezier curve
approximating a circle of radius r
centered on c
,
is based on unitcircle:
path circle(pair c, real r) { return shift(c)*scale(r)*unitcircle; }If high accuracy is needed, a true circle may be produced with this routine, defined in the module
graph.asy
:
path Circle(pair c, real r, int n=400);
A circular arc consistent with the above approximation centered on
c
with radius r
from angle1
to angle2
degrees, drawing counterclockwise if angle2 >= angle1
, can be
constructed with
path arc(pair c, real r, real angle1, real angle2);If
r
< 0, the complementary arc of radius |r|
is constructed.
For convenience, an arc centered at c
from pair z1
to
z2
(assuming |z2-c|=|z1-c|
) in the direction CCW
(counter-clockwise) or CW (clockwise) may also be constructed with
path arc(pair c, explicit pair z1, explicit pair z2, bool direction=CCW)
If high accuracy is needed, a true arc may be produced with this
routine, defined in the module graph.asy
:
path Arc(pair c, real r, real angle1, real angle2, int n=400);
An ellipse can be drawn with the routine
path ellipse(pair c, real a, real b) { return shift(c)*scale(a,b)*unitcircle; }
Here is an example of all five path connectors discussed in Tutorial:
size(300,0); pair[] z=new pair[10]; z[0]=(0,100); z[1]=(50,0); z[2]=(180,0); for(int n=3; n <= 9; ++n) z[n]=z[n-3]+(200,0); path p=z[0]..z[1]---z[2]::{up}z[3] &z[3]..z[4]--z[5]::{up}z[6] &z[6]::z[7]---z[8]..{up}z[9]; draw(p,grey+linewidth(4mm)); dot(z);
Here are some useful functions for paths:
int length(path p);
p
.
If p
is cyclic, this is the same as the number of nodes in p
.
int size(path p);
p
.
If p
is cyclic, this is the same as length(p)
.
bool cyclic(path p);
true
iff path p
is cyclic.
bool straight(path p, int i);
true
iff the segment of path p
between node
i
and node i+1
is straight.
pair point(path p, int t);
p
is cyclic, return the coordinates of node t
mod
length(p)
. Otherwise, return the coordinates of node t
,
unless t
< 0 (in which case point(0)
is returned) or
t
> length(p)
(in which case point(length(p))
is returned).
pair point(path p, real t);
floor(t)
and floor(t)+1
corresponding to the cubic spline parameter
t-floor(t)
(see Bezier). If t
lies outside the range
[0,length(p)
], it is first reduced modulo length(p)
in the case where p
is cyclic or else converted to the corresponding
endpoint of p
.
pair dir(path p, int t, int sign=0);
sign < 0
, the direction (as a pair) of the incoming tangent
to path p
at node t
is returned; if sign > 0
, the
direction of the outgoing tangent is returned. If sign=0
, the
mean of these two directions is returned. If p
contains only one
point, (0,0)
is returned.
pair dir(path p, real t);
p
at the point
between node floor(t)
and floor(t)+1
corresponding to the
cubic spline parameter t-floor(t)
(see Bezier).
If p
contains only one point, (0,0)
is returned.
pair precontrol(path p, int t);
p
at node t
.
pair precontrol(path p, real t);
p
at parameter t
.
pair postcontrol(path p, int t);
p
at node t
.
pair postcontrol(path p, real t);
p
at parameter t
.
real arclength(path p);
p
represents.
real arctime(path p, real L);
point(path p, real t)
, at which the
cumulative arclength (measured from the beginning of the path) equals L
.
real dirtime(path p, pair z);
point(path, real)
, at which the tangent
to the path has the direction of pair z
, or -1 if this never happens.
real reltime(path p, real l);
p
at the relative fraction l
of
its arclength.
pair relpoint(path p, real l);
p
at the relative fraction l
of its
arclength.
pair midpoint(path p);
p
at half of its arclength.
path reverse(path p);
p
.
path subpath(path p, int a, int b);
p
running from node a
to node b
.
If a
< b
, the direction of the subpath is reversed.
path subpath(path p, real a, real b);
p
running from path time a
to path
time b
, in the sense of point(path, real)
. If a
<
b
, the direction of the subpath is reversed.
real[] intersect(path p, path q, real fuzz=0);
p
and q
have at least one intersection point, return a
real array of length 2 containing the times representing the respective
path times along p
and q
, in the sense of
point(path, real)
, for one such intersection point (as chosen by
the algorithm described on page 137 of The MetaFontbook
).
The computations are performed to the absolute error specified by fuzz
,
or, if fuzz
is 0, to machine precision. If the paths do not
intersect, return a real array of length 0.
real[][] intersections(path p, path q, real fuzz=0);
p
and q
as a sorted array
of real arrays of length 2 (see sort).
The computations are performed to the absolute error specified by fuzz
,
or, if fuzz
is 0, to machine precision.
pair intersectionpoint(path p, path q, real fuzz=0);
point(p,intersect(p,q,fuzz)[0])
.
pair[] intersectionpoints(path p, path q);
p
and q
.
slice cut(path p, path knife, int n);
p
before and after the n
th
intersection of p
with path knife
as a structure
slice
(if no intersection exist is found, the entire path is
considered to be `before' the intersection):
struct slice { path before,after; }The argument
n
is treated as modulo the number of intersections.
slice firstcut(path p, path knife);
cut(p,knife,0);
Note that firstcut.after
plays the role of the MetaPost
cutbefore
command.
slice lastcut(path p, path knife);
cut(p,knife,-1);
Note that lastcut.before
plays the role of the
MetaPost cutafter
command.
path buildcycle(... path[] p);
MetaPost buildcycle
command.
pair min(path p);
p
.
pair max(path p);
p
.
int windingnumber(path p, pair z);
g
relative to the point
z
. The winding number is positive if the path encircles z
in the
counterclockwise direction.
bool inside(path p, pair z, pen fillrule=currentpen);
true
iff the point z
is inside the region bounded
by the cyclic path p
according to the fill rule fillrule
(see fillrule).
bool inside(path p, path q, pen fillrule=currentpen);
1
if the cyclic path p
strictly contains q
according to the fill rule fillrule
(see fillrule), -1
if the cyclic path q
strictly contains p
, and 0
otherwise.
guide
nullpath
; this is useful
for building up a guide within a loop.
A guide is similar to a path except that the computation of the cubic spline is deferred until drawing time (when it is resolved into a path); this allows two guides with free endpoint conditions to be joined together smoothly. The solid curve in the following example is built up incrementally as a guide, but only resolved at drawing time; the dashed curve is incrementally resolved at each iteration, before the entire set of nodes (shown in red) is known:
size(200); real mexican(real x) {return (1-8x^2)*exp(-(4x^2));} int n=30; real a=1.5; real width=2a/n; guide hat; path solved; for(int i=0; i < n; ++i) { real t=-a+i*width; pair z=(t,mexican(t)); hat=hat..z; solved=solved..z; } draw(hat); dot(hat,red); draw(solved,dashed);
We point out an efficiency distinction in the use of guides and paths:
guide g; for(int i=0; i < 10; ++i) g=g--(i,i); path p=g;
runs in linear time, whereas
path p; for(int i=0; i < 10; ++i) p=p--(i,i);
runs in quadratic time, as the entire path up to that point is copied at each step of the iteration.
The following routines can be used to examine the individual elements of a guide without actually resolving the guide to a fixed path (except for internal cycles, which are resolved):
int size(guide g);
size(path p)
.
int length(guide g);
length(path p)
.
bool cyclic(path p);
cyclic(path p)
.
pair point(guide g, int t);
point(path p, int t)
.
guide reverse(guide g);
reverse(path p)
. If g
is cyclic and
also contains a secondary cycle, it is first solved to a
path, then reversed. If g
is not cyclic but contains an internal
cycle, only the internal cycle is solved before reversal. If there are
no internal cycles, the guide is reversed but not solved to a path.
pair[] dirSpecifier(guide g, int i);
(0,0)
if none specified) for the segment of guide g
between nodes i
and i+1
.
pair[] controlSpecifier(guide g, int i);
g
between nodes i
and i+1
has explicit outgoing and incoming control points, they are returned as
elements 0 and 1, respectively, of a two-element array. Otherwise, an
empty array is returned.
tensionSpecifier tensionSpecifier(guide g, int i);
g
between
nodes i
and i+1
. The individual components of the
tensionSpecifier
type can be accessed as the virtual members
in
, out
, and atLeast
.
real[] curlSpecifier(guide g);
g
.
As a technical detail we note that a direction specifier given to
nullpath
modifies the node on the other side: the guides
a..{up}nullpath..b; c..nullpath{up}..d; e..{up}nullpath{down}..f;are respectively equivalent to
a..nullpath..{up}b; c{up}..nullpath..d; e{down}..nullpath..{up}f;