| [ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.2 Paths and guides
path-
a cubic spline resolved into a fixed path. The implicit initializer for paths is
nullpath.For example, the routine
circle(pair c, real r), which returns a Bezier curve approximating a circle of radiusrcentered onc, is based onunitcircle(see 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 the routine
Circledefined in the modulegraph.asy:import graph; path Circle(pair c, real r, int n=nCircle);
A circular arc consistent with
circlecentered oncwith radiusrfromangle1toangle2degrees, drawing counterclockwise ifangle2 >= angle1, can be constructed withpath arc(pair c, real r, real angle1, real angle2);
One may also specify the direction explicitly:
path arc(pair c, real r, real angle1, real angle2, bool direction);
Here the direction can be specified as CCW (counter-clockwise) or CW (clockwise). For convenience, an arc centered at
cfrom pairz1toz2(assuming|z2-c|=|z1-c|) in the may also be constructed withpath arc(pair c, explicit pair z1, explicit pair z2, bool direction=CCW)If high accuracy is needed, true arcs may be produced with routines in the module
graph.asythat produce Bezier curves withncontrol points:import graph; path Arc(pair c, real r, real angle1, real angle2, bool direction, int n=nCircle); path Arc(pair c, real r, real angle1, real angle2, int n=nCircle); path Arc(pair c, explicit pair z1, explicit pair z2, bool direction=CCW, int n=nCircle);An ellipse can be drawn with the routine
path ellipse(pair c, real a, real b) { return shift(c)*scale(a,b)*unitcircle; }A brace can be constructed between pairs
aandbwithpath brace(pair a, pair b, real amplitude=bracedefaultratio*length(b-a));
This example illustrates the use of all five guide connectors discussed in Tutorial and Bezier curves:
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);This is the number of (linear or cubic) segments in path
p. Ifpis cyclic, this is the same as the number of nodes inp.int size(path p);This is the number of nodes in the path
p. Ifpis cyclic, this is the same aslength(p).bool cyclic(path p);returns
trueiff pathpis cyclic.bool straight(path p, int i);returns
trueiff the segment of pathpbetween nodeiand nodei+1is straight.bool piecewisestraight(path p)returns
trueiff the pathpis piecewise straight.pair point(path p, int t);If
pis cyclic, return the coordinates of nodetmodlength(p). Otherwise, return the coordinates of nodet, unlesst< 0 (in which casepoint(0)is returned) ort>length(p)(in which casepoint(length(p))is returned).pair point(path p, real t);This returns the coordinates of the point between node
floor(t)andfloor(t)+1corresponding to the cubic spline parametert-floor(t)(see section Bezier curves). Iftlies outside the range [0,length(p)], it is first reduced modulolength(p)in the case wherepis cyclic or else converted to the corresponding endpoint ofp.pair dir(path p, int t, int sign=0, bool normalize=true);If
sign < 0, return the direction (as a pair) of the incoming tangent to pathpat nodet; ifsign > 0, return the direction of the outgoing tangent. Ifsign=0, the mean of these two directions is returned.pair dir(path p, real t, bool normalize=true);returns the direction of the tangent to path
pat the point between nodefloor(t)andfloor(t)+1corresponding to the cubic spline parametert-floor(t)(see section Bezier curves).pair dir(path p)returns dir(p,length(p)).
pair dir(path p, path q)returns unit(dir(p)+dir(q)).
pair accel(path p, int t, int sign=0);If
sign < 0, return the acceleration of the incoming pathpat nodet; ifsign > 0, return the acceleration of the outgoing path. Ifsign=0, the mean of these two accelerations is returned.pair accel(path p, real t);returns the acceleration of the path
pat the pointt.real radius(path p, real t);returns the radius of curvature of the path
pat the pointt.pair precontrol(path p, int t);returns the precontrol point of
pat nodet.pair precontrol(path p, real t);returns the effective precontrol point of
pat parametert.pair postcontrol(path p, int t);returns the postcontrol point of
pat nodet.pair postcontrol(path p, real t);returns the effective postcontrol point of
pat parametert.real arclength(path p);returns the length (in user coordinates) of the piecewise linear or cubic curve that path
prepresents.real arctime(path p, real L);returns the path "time", a real number between 0 and the length of the path in the sense of
point(path p, real t), at which the cumulative arclength (measured from the beginning of the path) equalsL.real arcpoint(path p, real L);returns
point(p,arctime(p,L)).real dirtime(path p, pair z);returns the first "time", a real number between 0 and the length of the path in the sense of
point(path, real), at which the tangent to the path has the direction of pairz, or -1 if this never happens.real reltime(path p, real l);returns the time on path
pat the relative fractionlof its arclength.pair relpoint(path p, real l);returns the point on path
pat the relative fractionlof its arclength.pair midpoint(path p);returns the point on path
pat half of its arclength.path reverse(path p);returns a path running backwards along
p.path subpath(path p, int a, int b);returns the subpath of
prunning from nodeato nodeb. Ifa<b, the direction of the subpath is reversed.path subpath(path p, real a, real b);returns the subpath of
prunning from path timeato path timeb, in the sense ofpoint(path, real). Ifa<b, the direction of the subpath is reversed.real[] intersect(path p, path q, real fuzz=-1);If
pandqhave at least one intersection point, return a real array of length 2 containing the times representing the respective path times alongpandq, in the sense ofpoint(path, real), for one such intersection point (as chosen by the algorithm described on page 137 ofThe MetaFontbook). The computations are performed to the absolute error specified byfuzz, or iffuzz < 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=-1);Return all (unless there are infinitely many) intersection times of paths
pandqas a sorted array of real arrays of length 2 (see sort). The computations are performed to the absolute error specified byfuzz, or iffuzz < 0, to machine precision.real[] intersections(path p, explicit pair a, explicit pair b, real fuzz=-1);Return all (unless there are infinitely many) intersection times of path
pwith the (infinite) line through pointsaandbas a sorted array. The intersections returned are guaranteed to be correct to within the absolute error specified byfuzz, or iffuzz < 0, to machine precision.real[] times(path p, real x)returns all intersection times of path
pwith the vertical line through(x,0).real[] times(path p, explicit pair z)returns all intersection times of path
pwith the horizontal line through(0,z.y).real[] mintimes(path p)returns an array of length 2 containing times at which path
preaches its minimal horizontal and vertical extents, respectively.real[] maxtimes(path p)returns an array of length 2 containing times at which path
preaches its maximal horizontal and vertical extents, respectively.pair intersectionpoint(path p, path q, real fuzz=-1);returns the intersection point
point(p,intersect(p,q,fuzz)[0]).pair[] intersectionpoints(path p, path q, real fuzz=-1);returns an array containing all intersection points of the paths
pandq.pair extension(pair P, pair Q, pair p, pair q);returns the intersection point of the extensions of the line segments
P--Qandp--q, or if the lines are parallel,(infinity,infinity).slice cut(path p, path knife, int n);returns the portions of path
pbefore and after thenth intersection ofpwith pathknifeas a structureslice(if no intersection exist is found, the entire path is considered to be ‘before’ the intersection):struct slice { path before,after; }The argument
nis treated as modulo the number of intersections.slice firstcut(path p, path knife);equivalent to
cut(p,knife,0);Note thatfirstcut.afterplays the role of theMetaPost cutbeforecommand.slice lastcut(path p, path knife);equivalent to
cut(p,knife,-1);Note thatlastcut.beforeplays the role of theMetaPost cutaftercommand.path buildcycle(... path[] p);This returns the path surrounding a region bounded by a list of two or more consecutively intersecting paths, following the behaviour of the
MetaPost buildcyclecommand.pair min(path p);returns the pair (left,bottom) for the path bounding box of path
p.pair max(path p);returns the pair (right,top) for the path bounding box of path
p.int windingnumber(path p, pair z);returns the winding number of the cyclic path
prelative to the pointz. The winding number is positive if the path encircleszin the counterclockwise direction. Ifzlies onpthe constantundefined(defined to be the largest odd integer) is returned.bool interior(int windingnumber, pen fillrule)returns true if
windingnumbercorresponds to an interior point according tofillrule.bool inside(path p, pair z, pen fillrule=currentpen);returns
trueiff the pointzlies inside or on the edge of the region bounded by the cyclic pathpaccording to the fill rulefillrule(see fillrule).int inside(path p, path q, pen fillrule=currentpen);returns
1if the cyclic pathpstrictly containsqaccording to the fill rulefillrule(see fillrule),-1if the cyclic pathqstrictly containsp, and0otherwise.pair inside(path p, pen fillrule=currentpen);returns an arbitrary point strictly inside a cyclic path
paccording to the fill rulefillrule(see fillrule).real orient(pair a, pair b, pair c);returns a positive (negative) value if
a--b--c--cycleis oriented counterclockwise (clockwise) or zero if all three points are colinear. Equivalently, a positive (negative) value is returned ifclies to the left (right) of the line throughaandbor zero ifclies on this line. The value returned is the determinant|a.x a.y 1| |b.x b.y 1| |c.x c.y 1|
real incircle(pair a, pair b, pair c, pair d);returns a positive (negative) value if
dlies inside (outside) the circle passing through the counterclockwise-oriented pointsa,b,cor zero ifdlies on the this circle. The value returned is the determinant|a.x a.y a.x^2+a.y^2 1| |b.x b.y b.x^2+b.y^2 1| |c.x c.y c.x^2+c.y^2 1| |d.x d.y d.x^2+d.y^2 1|
path[] strokepath(path g, pen p=currentpen);returns the path array that
PostScriptwould fill in drawing pathgwith penp.
guide-
an unresolved cubic spline (list of cubic-spline nodes and control points). The implicit initializer for a guide is
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);Analogous to
size(path p).int length(guide g);Analogous to
length(path p).bool cyclic(path p);Analogous to
cyclic(path p).pair point(guide g, int t);Analogous to
point(path p, int t).guide reverse(guide g);Analogous to
reverse(path p). Ifgis cyclic and also contains a secondary cycle, it is first solved to a path, then reversed. Ifgis 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);This returns a pair array of length 2 containing the outgoing (in element 0) and incoming (in element 1) direction specifiers (or
(0,0)if none specified) for the segment of guidegbetween nodesiandi+1.pair[] controlSpecifier(guide g, int i);If the segment of guide
gbetween nodesiandi+1has 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);This returns the tension specifier for the segment of guide
gbetween nodesiandi+1. The individual components of thetensionSpecifiertype can be accessed as the virtual membersin,out, andatLeast.real[] curlSpecifier(guide g);This returns an array containing the initial curl specifier (in element 0) and final curl specifier (in element 1) for guide
g.
As a technical detail we note that a direction specifier given to
nullpathmodifies the node on the other side: the guidesa..{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;
| [ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on May 24, 2014 using texi2html 5.0.
