asymptote: Bezier curves
5 Bezier curves
***************
Each interior node of a cubic spline may be given a direction prefix or
suffix '{dir}': the direction of the pair 'dir' specifies the direction
of the incoming or outgoing tangent, respectively, to the curve at that
node. Exterior nodes may be given direction specifiers only on their
interior side.
A cubic spline between the node z_0, with postcontrol point c_0, and
the node z_1, with precontrol point c_1, is computed as the Bezier curve
[(1-t)^3*z_0+3t(1-t)^2*c_0+3t^2(1-t)*c_1+t^3*z_1 for 0 <=t <= 1.]
As illustrated in the diagram below, the third-order midpoint (m_5)
constructed from two endpoints z_0 and z_1 and two control points c_0
and c_1, is the point corresponding to t=1/2 on the Bezier curve formed
by the quadruple (z_0, c_0, c_1, z_1). This allows one to recursively
construct the desired curve, by using the newly extracted third-order
midpoint as an endpoint and the respective second- and first-order
midpoints as control points:
[bezier2]
Here m_0, m_1 and m_2 are the first-order midpoints, m_3 and m_4 are
the second-order midpoints, and m_5 is the third-order midpoint. The
curve is then constructed by recursively applying the algorithm to (z_0,
m_0, m_3, m_5) and (m_5, m_4, m_2, z_1).
In fact, an analogous property holds for points located at any
fraction t in [0,1] of each segment, not just for midpoints (t=1/2).
The Bezier curve constructed in this manner has the following
properties:
* It is entirely contained in the convex hull of the given four
points.
* It starts heading from the first endpoint to the first control
point and finishes heading from the second control point to the
second endpoint.
The user can specify explicit control points between two nodes like
this:
draw((0,0)..controls (0,100) and (100,100)..(100,0));
However, it is usually more convenient to just use the '..' operator,
which tells 'Asymptote' to choose its own control points using the
algorithms described in Donald Knuth's monograph, The MetaFontbook,
Chapter 14. The user can still customize the guide (or path) by
specifying direction, tension, and curl values.
The higher the tension, the straighter the curve is, and the more it
approximates a straight line. One can change the spline tension from
its default value of 1 to any real value greater than or equal to 0.75
(cf. John D. Hobby, Discrete and Computational Geometry 1, 1986):
draw((100,0)..tension 2 ..(100,100)..(0,100));
draw((100,0)..tension 3 and 2 ..(100,100)..(0,100));
draw((100,0)..tension atleast 2 ..(100,100)..(0,100));
In these examples there is a space between '2' and '..'. This is
needed as '2.' is interpreted as a numerical constant.
The curl parameter specifies the curvature at the endpoints of a path
(0 means straight; the default value of 1 means approximately circular):
draw((100,0){curl 0}..(100,100)..{curl 0}(0,100));
The 'MetaPost ...' path connector, which requests, when possible, an
inflection-free curve confined to a triangle defined by the endpoints
and directions, is implemented in 'Asymptote' as the convenient
abbreviation '::' for '..tension atleast 1 ..' (the ellipsis '...' is
used in 'Asymptote' to indicate a variable number of arguments;
Rest arguments). For example, compare
draw((0,0){up}..(100,25){right}..(200,0){down});
[dots]
with
draw((0,0){up}::(100,25){right}::(200,0){down});
[colons]
The '---' connector is an abbreviation for '..tension atleast
infinity..' and the '&' connector concatenates two paths, after first
stripping off the last node of the first path (which normally should
coincide with the first node of the second path).