[ << ]  [ < ]  [ Up ]  [ > ]  [ >> ]  [Top]  [Contents]  [Index]  [ ? ] 
8.29 three
This module fully extends the notion of guides and paths in Asymptote
to three dimensions. It introduces the new types guide3, path3, and surface.
Guides in three dimensions are specified with the same syntax as in two
dimensions except that triples (x,y,z)
are used in place of pairs
(x,y)
for the nodes and direction specifiers. This
generalization of John Hobby’s spline algorithm is shapeinvariant under
threedimensional rotation, scaling, and shifting, and reduces in the
planar case to the twodimensional algorithm used in Asymptote
,
MetaPost
, and MetaFont
[cf. J. C. Bowman, Proceedings in
Applied Mathematics and Mechanics, 7:1, 20100212010022 (2007)].
For example, a unit circle in the XY plane may be filled and drawn like this:
import three; size(100); path3 g=(1,0,0)..(0,1,0)..(1,0,0)..(0,1,0)..cycle; draw(g); draw(OZ,red+dashed,Arrow3); draw(((1,1,0)(1,1,0)(1,1,0)(1,1,0)cycle)); dot(g,red);
and then distorted into a saddle:
import three; size(100,0); path3 g=(1,0,0)..(0,1,1)..(1,0,0)..(0,1,1)..cycle; draw(g); draw(((1,1,0)(1,1,0)(1,1,0)(1,1,0)cycle)); dot(g,red);
Module three
provides constructors for converting twodimensional
paths to threedimensional ones, and viceversa:
path3 path3(path p, triple plane(pair)=XYplane); path path(path3 p, pair P(triple)=xypart);
A Bezier surface, the natural twodimensional generalization of Bezier
curves, is defined in three_surface.asy
as a structure
containing an array of Bezier patches. Surfaces may drawn with one of
the routines
void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1, material surfacepen=currentpen, pen meshpen=nullpen, light light=currentlight, light meshlight=light, string name="", render render=defaultrender); void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1, material[] surfacepen, pen meshpen, light light=currentlight, light meshlight=light, string name="", render render=defaultrender); void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1, material[] surfacepen, pen[] meshpen=nullpens, light light=currentlight, light meshlight=light, string name="", render render=defaultrender);
The parameters nu
and nv
specify the number of subdivisions
for drawing optional mesh lines for each Bezier patch. The optional
name
parameter is used as a prefix for naming the surface
patches in the PRC model tree.
Here material is a structure defined in three_light.asy
:
struct material { pen[] p; // diffusepen,ambientpen,emissivepen,specularpen real opacity; real shininess; ... }
These material properties are used to implement OpenGL
style lighting,
based on the PhongBlinn specular model. Sample Bezier surfaces are
contained in the example files BezierSurface.asy
, teapot.asy
,
and parametricsurface.asy
. The structure render
contains
specialized rendering options documented at the beginning of module
three.asy
.
The examples
elevation.asy
and sphericalharmonic.asy
illustrate how to draw a surface with patchdependent colors.
The examples vertexshading
and smoothelevation
illustrate
vertexdependent colors, which is supported for both
Asymptote
’s native OpenGL
renderer and twodimensional
projections. Since the PRC output format does not currently support
vertex shading of Bezier surfaces, PRC patches are shaded
with the mean of the four vertex colors.
A surface can be constructed from a cyclic path3
with the constructor
surface surface(path3 external, triple[] internal=new triple[], triple[] normals=new triple[], pen[] colors=new pen[], bool3 planar=default);
and then filled:
draw(surface(path3(polygon(5))),red,nolight); draw(surface(unitcircle3),red,nolight); draw(surface(unitcircle3,new pen[] {red,green,blue,black}),nolight);
The last example constructs a patch with vertexspecific colors.
A threedimensional planar surface in the plane plane
can be
constructed from a twodimensional cyclic path g
with the constructor
surface surface(path p, triple plane(pair)=XYplane);
and then filled:
draw(surface((0,0)E+2N2EE+N..0.2E..cycle),red);
Planar Bezier surfaces patches are constructed using Orest Shardt’s
bezulate
routine, which decomposes (possibly nonsimply
connected) regions bounded (according to the zerowinding
fill rule)
by simple cyclic paths (intersecting only at the endpoints)
into subregions bounded by cyclic paths of length 4
or less.
A more efficient routine also exists for drawing tessellations composed of many 3D triangles, with specified vertices, and optional normals or vertex colors:
void draw(picture pic=currentpicture, triple[] v, int[][] vi, triple[] n={}, int[][] ni={}, material m=currentpen, pen[] p={}, int[][] pi={}, light light=currentlight);
Here, the triple array v
lists the distinct vertices, while
the array vi
lists integer arrays of length 3 containing
the indices of v
corresponding to the vertices of each
triangle. Similarly, the arguments n
and ni
contain
optional normal data and p
and pi
contain optional pen vertex data.
An example of this tessellation facility is given in triangles.asy
.
Arbitrary thick threedimensional curves and line caps (which the
OpenGL
standard does not require implementations to provide) are
constructed with
tube tube(path3 p, real width, render render=defaultrender);
this returns a tube structure representing a tube of diameter width
centered approximately on g
. The tube structure consists of a
surface s
and the actual tube center, path3 center
.
Drawing thick lines as tubes can be slow to render,
especially with the Adobe Reader
renderer. The setting
thick=false
can be used to disable this feature and force all
lines to be drawn with linewidth(0)
(one pixel wide, regardless
of the resolution). By default, mesh and contour lines in threedimensions
are always drawn thin, unless an explicit line width is given in the pen
parameter or the setting thin
is set to false
. The pens
thin()
and thick()
defined in plain_pens.asy can also be used
to override these defaults for specific draw commands.
There are four choices for viewing 3D Asymptote
output:
 Use the native
Asymptote
adaptiveOpenGL
based renderer (with the commandline optionV
and the default settingsoutformat=""
andrender=1
). If you encounter warnings from your graphics card driver, try specifyingglOptions=indirect
on the command line. OnUNIX
systems with graphics support for multisampling, the sample width can be controlled with the settingmultisample
. An initial screen position can be specified with the pair settingposition
, where negative values are interpreted as relative to the corresponding maximum screen dimension. The default settingsimport settings; leftbutton=new string[] {"rotate","zoom","shift","pan"}; middlebutton=new string[] {"menu"}; rightbutton=new string[] {"zoom/menu","rotateX","rotateY","rotateZ"}; wheelup=new string[] {"zoomin"}; wheeldown=new string[] {"zoomout"};
bind the mouse buttons as follows:
 Left: rotate
 Shift Left: zoom
 Ctrl Left: shift viewport
 Alt Left: pan
 Middle: menu (must be unmodified; ignores Shift, Ctrl, and Alt)
 Wheel Up: zoom in
 Wheel Down: zoom out
 Right: zoom/menu (must be unmodified)
 Right double click: menu
 Shift Right: rotate about the X axis
 Ctrl Right: rotate about the Y axis
 Alt Right: rotate about the Z axis
 h: home
 f: toggle fitscreen
 x: spin about the X axis
 y: spin about the Y axis
 z: spin about the Z axis
 s: stop spinning
 m: rendering mode (solid/mesh/patch)
 e: export
 c: show camera parameters
 p: play animation
 r: reverse animation
 : step animation
 +: expand
 =: expand
 >: expand
 : shrink
 _: shrink
 <: shrink
 q: exit
 Ctrlq: exit
 Render the scene to a specified rasterized format
outformat
at the resolution ofn
pixels perbp
, as specified by the settingrender=n
. A negative value ofn
is interpreted as2n
for EPS and PDF formats andn
for other formats. The default value ofrender
is 1. By default, the scene is internally rendered at twice the specified resolution; this can be disabled by settingantialias=1
. High resolution rendering is done by tiling the image. If your graphics card allows it, the rendering can be made more efficient by increasing the maximum tile sizemaxtile
to your screen dimensions (indicated bymaxtile=(0,0)
. If your video card generates unwanted black stripes in the output, try setting the horizontal and vertical components ofmaxtiles
to something less than your screen dimensions. The tile size is also limited by the settingmaxviewport
, which restricts the maximum width and height of the viewport. OnUNIX
systems some graphics drivers support batch mode (noV
) rendering in an iconified window; this can be enabled with the settingiconify=true
. Some (broken)UNIX
graphics drivers may require the command line settingglOptions=indirect
, which requests (slower) indirect rendering.  Embed the 3D PRC format in a PDF file
and view the resulting PDF file with
version
9.0
or later ofAdobe Reader
. In addition to the defaultsettings.prc=true
, this requiressettings.outformat="pdf"
, which can be specified by the command line optionf pdf
, put in theAsymptote
configuration file (see configuration file), or specified in the script beforethree.asy
(orgraph3.asy
) is imported. Themedia9
LaTeX package is also required (see sectionembed
). The examplepdb.asy
illustrates how one can generate a list of predefined views (see100d.views
). A stationary preview image with a resolution ofn
pixels perbp
can be embedded with the settingrender=n
; this allows the file to be viewed with otherPDF
viewers. Alternatively, the fileexternalprc.tex
illustrates how the resulting PRC and rendered image files can be extracted and processed in a separateLaTeX
file. However, seeLaTeX
usage for an easier way to embed threedimensionalAsymptote
pictures withinLaTeX
. For specialized applications where only the raw PRC file is required, specifysettings.outformat="prc"
. The opensource PRC specification is available from http://livedocs.adobe.com/acrobat_sdk/9/Acrobat9_HTMLHelp/API_References/PRCReference/PRC_Format_Specification/.  Project the scene to a twodimensional vector (EPS or
PDF) format with
render=0
. Only limited hidden surface removal facilities are currently available with this approach (see PostScript3D).
Automatic picture sizing in three dimensions is accomplished with double deferred drawing. The maximal desired dimensions of the scene in each of the three dimensions can optionally be specified with the routine
void size3(picture pic=currentpicture, real x, real y=x, real z=y, bool keepAspect=pic.keepAspect);
The resulting simplex linear programming problem is then solved to
produce a 3D version of a frame (actually implemented as a 3D picture).
The result is then fit with another application of deferred drawing
to the viewport dimensions corresponding to the usual twodimensional
picture size
parameters. The global pair viewportmargin
may be used to add horizontal and vertical margins to the viewport
dimensions. Alternatively, a minimum viewportsize
may be specified.
A 3D picture pic
can be explicitly fit to a 3D frame by calling
frame pic.fit3(projection P=currentprojection);
and then added to picture dest
about position
with
void add(picture dest=currentpicture, frame src, triple position=(0,0,0));
For convenience, the three
module defines O=(0,0,0)
,
X=(1,0,0)
, Y=(0,1,0)
, and Z=(0,0,1)
, along with a
unitcircle in the XY plane:
path3 unitcircle3=X..Y..X..Y..cycle;
A general (approximate) circle can be drawn perpendicular to the direction
normal
with the routine
path3 circle(triple c, real r, triple normal=Z);
A circular arc centered at c
with radius r
from
c+r*dir(theta1,phi1)
to c+r*dir(theta2,phi2)
,
drawing counterclockwise relative to the normal vector
cross(dir(theta1,phi1),dir(theta2,phi2))
if theta2 > theta1
or if theta2 == theta1
and phi2 >= phi1
, can be constructed with
path3 arc(triple c, real r, real theta1, real phi1, real theta2, real phi2, triple normal=O);
The normal must be explicitly specified if c
and the endpoints
are colinear. If r
< 0, the complementary arc of radius
r
is constructed.
For convenience, an arc centered at c
from triple v1
to
v2
(assuming v2c=v1c
) in the direction CCW
(counterclockwise) or CW (clockwise) may also be constructed with
path3 arc(triple c, triple v1, triple v2, triple normal=O, bool direction=CCW);
When high accuracy is needed, the routines Circle
and
Arc
defined in graph3
may be used instead.
See GaussianSurface for an example of a threedimensional circular arc.
The representation OO+uO+u+vO+vcycle
of the plane passing through point O
with normal
cross(u,v)
is returned by
path3 plane(triple u, triple v, triple O=O);
A threedimensional box with opposite vertices at triples v1
and v2
may be drawn with the function
path3[] box(triple v1, triple v2);
For example, a unit box is predefined as
path3[] unitbox=box(O,(1,1,1));
Asymptote
also provides optimized definitions for the
threedimensional paths unitsquare3
and unitcircle3
,
along with the surfaces unitdisk
, unitplane
, unitcube
,
unitcylinder
, unitcone
, unitsolidcone
,
unitfrustum(real t1, real t2)
, unitsphere
, and
unithemisphere
.
These projections to two dimensions are predefined:
oblique
oblique(real angle)

The point
(x,y,z)
is projected to(x0.5z,y0.5z)
. If an optional real argument is given, the negative z axis is drawn at this angle in degrees. The projectionobliqueZ
is a synonym foroblique
. obliqueX
obliqueX(real angle)

The point
(x,y,z)
is projected to(y0.5x,z0.5x)
. If an optional real argument is given, the negative x axis is drawn at this angle in degrees. obliqueY
obliqueY(real angle)

The point
(x,y,z)
is projected to(x+0.5y,z+0.5y)
. If an optional real argument is given, the positive y axis is drawn at this angle in degrees. orthographic(triple camera, triple up=Z, triple target=O,
real zoom=1, pair viewportshift=0, bool showtarget=true,
bool center=false)This projects from three to two dimensions using the view as seen at a point infinitely far away in the direction
unit(camera)
, orienting the camera so that, if possible, the vectorup
points upwards. Parallel lines are projected to parallel lines. The bounding volume is expanded to includetarget
ifshowtarget=true
. Ifcenter=true
, the target will be adjusted to the center of the bounding volume.orthographic(real x, real y, real z, triple up=Z, triple target=O,
real zoom=1, pair viewportshift=0, bool showtarget=true,
bool center=false)This is equivalent to
orthographic((x,y,z),up,target,zoom,viewportshift,showtarget,center)
triple camera(real alpha, real beta);
can be used to compute the camera position with the x axis below the horizontal at angle
alpha
, the y axis below the horizontal at anglebeta
, and the z axis up.perspective(triple camera, triple up=Z, triple target=O,
real zoom=1, real angle=0, pair viewportshift=0,
bool showtarget=true, bool autoadjust=true,
bool center=autoadjust)
This projects from three to two dimensions, taking account of perspective, as seen from the location
camera
looking attarget
, orienting the camera so that, if possible, the vectorup
points upwards. Ifrender=0
, projection of threedimensional cubic Bezier splines is implemented by approximating a twodimensional nonuniform rational Bspline (NURBS) with a twodimensional Bezier curve containing additional nodes and control points. Ifautoadjust=true
, the camera will automatically be adjusted to lie outside the bounding volume for all possible interactive rotations abouttarget
. Ifcenter=true
, the target will be adjusted to the center of the bounding volume. perspective(real x, real y, real z, triple up=Z, triple target=O,
real zoom=1, real angle=0, pair viewportshift=0,
bool showtarget=true, bool autoadjust=true,
bool center=autoadjust)This is equivalent to
perspective((x,y,z),up,target,zoom,angle,viewportshift,showtarget, autoadjust,center)
The default projection, currentprojection
, is initially set to
perspective(5,4,2)
.
We also define standard orthographic views used in technical drawing:
projection LeftView=orthographic(X,showtarget=true); projection RightView=orthographic(X,showtarget=true); projection FrontView=orthographic(Y,showtarget=true); projection BackView=orthographic(Y,showtarget=true); projection BottomView=orthographic(Z,showtarget=true); projection TopView=orthographic(Z,showtarget=true);
void addViews(picture dest=currentpicture, picture src, projection[][] views=SixViewsUS, bool group=true, filltype filltype=NoFill);
adds to picture dest
an array of views of picture src
using the layout projection[][] views
. The default layout
SixViewsUS
aligns the projection FrontView
below
TopView
and above BottomView
, to the right of
LeftView
and left of RightView
and BackView
.
The predefined layouts are:
projection[][] ThreeViewsUS={{TopView}, {FrontView,RightView}}; projection[][] SixViewsUS={{null,TopView}, {LeftView,FrontView,RightView,BackView}, {null,BottomView}}; projection[][] ThreeViewsFR={{RightView,FrontView}, {null,TopView}}; projection[][] SixViewsFR={{null,BottomView}, {RightView,FrontView,LeftView,BackView}, {null,TopView}}; projection[][] ThreeViews={{FrontView,TopView,RightView}}; projection[][] SixViews={{FrontView,TopView,RightView}, {BackView,BottomView,LeftView}};
A triple or path3 can be projected to a pair or path,
with project(triple, projection P=currentprojection)
or
project(path3, projection P=currentprojection)
.
It is occasionally useful to be able to invert a projection, sending
a pair z
onto the plane perpendicular to normal
and passing
through point
:
triple invert(pair z, triple normal, triple point, projection P=currentprojection);
A pair z
on the projection plane can be inverted to a triple
with the routine
triple invert(pair z, projection P=currentprojection);
A pair direction dir
on the projection plane can be inverted to
a triple direction relative to a point v
with the routine
triple invert(pair dir, triple v, projection P=currentprojection).
Threedimensional objects may be transformed with one of the following
builtin transform3 types (the identity transformation is identity4
):
shift(triple v)

translates by the triple
v
; xscale3(real x)

scales by
x
in the x direction; yscale3(real y)

scales by
y
in the y direction; zscale3(real z)

scales by
z
in the z direction; scale3(real s)

scales by
s
in the x, y, and z directions; scale(real x, real y, real z)

scales by
x
in the x direction, byy
in the y direction, and byz
in the z direction; rotate(real angle, triple v)
rotates by
angle
in degrees about an axisv
through the origin;rotate(real angle, triple u, triple v)
rotates by
angle
in degrees about the axisuv
;reflect(triple u, triple v, triple w)
When not multiplied on the left by a transform3, threedimensional TeX Labels are drawn as Bezier surfaces directly on the projection plane:
void label(picture pic=currentpicture, Label L, triple position, align align=NoAlign, pen p=currentpen, light light=nolight, string name="", render render=defaultrender, interaction interaction= settings.autobillboard ? Billboard : Embedded)
The optional name
parameter is used as a prefix for naming the label
patches in the PRC model tree.
The default interaction is Billboard
, which means that labels
are rotated interactively so that they always face the camera.
The interaction Embedded
means that the label interacts as a
normal 3D
surface, as illustrated in the example billboard.asy
.
Alternatively, a label can be transformed from the XY
plane by an
explicit transform3 or mapped to a specified twodimensional plane with
the predefined transform3 types XY
, YZ
, ZX
, YX
,
ZY
, ZX
. There are also modified versions of these
transforms that take an optional argument projection
P=currentprojection
that rotate and/or flip the label so that it is
more readable from the initial viewpoint.
A transform3 that projects in the direction dir
onto the plane
with normal n
through point O
is returned by
transform3 planeproject(triple n, triple O=O, triple dir=n);
triple normal(path3 p);
to find the unit normal vector to a planar threedimensional path p
.
As illustrated in the example planeproject.asy
, a transform3
that projects in the direction dir
onto the plane defined by a
planar path p
is returned by
transform3 planeproject(path3 p, triple dir=normal(p));
surface extrude(path p, triple axis=Z); surface extrude(Label L, triple axis=Z);
return the surface obtained by extruding path p
or
Label L
along axis
.
Threedimensional versions of the path functions length
,
size
, point
, dir
, accel
, radius
,
precontrol
, postcontrol
,
arclength
, arctime
, reverse
, subpath
,
intersect
, intersections
, intersectionpoint
,
intersectionpoints
, min
, max
, cyclic
, and
straight
are also defined.
real[][] intersections(path3 p, surface s, real fuzz=1);
returns the intersection times of a path p
with a surface
s
as a sorted array of real arrays of length 3, and
triple[] intersectionpoints(path3 p, surface s, real fuzz=1);
returns the corresponding intersection points.
Here, the computations are performed to the absolute error specified by
fuzz
, or if fuzz < 0
, to machine precision.
real orient(triple a, triple b, triple c, triple d);
returns a negative (positive) value if abccycle
is oriented
counterclockwise (clockwise) when viewed from d
or zero if all four
points are coplanar.
The value returned is the determinant
a.x a.y a.z 1 b.x b.y b.z 1 c.x c.y c.z 1 d.x d.y d.z 1
real insphere(triple a, triple b, triple c, triple d, triple e);
returns a positive (negative) value if e
lies inside (outside)
the sphere passing through the points a,b,c,d
oriented so that
abccycle
appears in clockwise order when viewed from d
or zero if all five points are cospherical.
The value returned is the determinant
a.x a.y a.z a.x^2+a.y^2+a.z^2 1 b.x b.y b.z b.x^2+b.y^2+b.z^2 1 c.x c.y c.z c.x^2+c.y^2+c.z^2 1 d.x d.y d.z d.x^2+d.y^2+d.z^2 1 e.x e.y e.z e.x^2+e.y^2+e.z^2 1
Here is an example showing all five guide3 connectors:
import graph3; size(200); currentprojection=orthographic(500,500,500); triple[] z=new triple[10]; z[0]=(0,100,0); z[1]=(50,0,0); z[2]=(180,0,0); for(int n=3; n <= 9; ++n) z[n]=z[n3]+(200,0,0); path3 p=z[0]..z[1]z[2]::{Y}z[3] &z[3]..z[4]z[5]::{Y}z[6] &z[6]::z[7]z[8]..{Y}z[9]; draw(p,grey+linewidth(4mm),currentlight); xaxis3(Label(XY()*"$x$",align=3Y),red,above=true); yaxis3(Label(XY()*"$y$",align=3X),red,above=true);
Threedimensional versions of bars or arrows can be drawn with one of
the specifiers None
, Blank
,
BeginBar3
, EndBar3
(or equivalently Bar3
), Bars3
,
BeginArrow3
, MidArrow3
,
EndArrow3
(or equivalently Arrow3
), Arrows3
,
BeginArcArrow3
, EndArcArrow3
(or equivalently
ArcArrow3
), MidArcArrow3
, and ArcArrows3
.
Threedimensional bars accept the optional arguments (real size=0,
triple dir=O)
. If size=O
, the default bar length is used; if
dir=O
, the bar is drawn perpendicular to the path
and the initial viewing direction. The predefined threedimensional
arrowhead styles are DefaultHead3
, HookHead3
, TeXHead3
.
Versions of the twodimensional arrowheads lifted to threedimensional
space and aligned according to the initial viewpoint (or an optionally
specified normal
vector) are also defined:
DefaultHead2(triple normal=O)
, HookHead2(triple normal=O)
,
TeXHead2(triple normal=O)
. These are illustrated in the example
arrows3.asy
.
Module three
also defines the threedimensional margins
NoMargin3
, BeginMargin3
, EndMargin3
,
Margin3
, Margins3
,
BeginPenMargin2
, EndPenMargin2
, PenMargin2
,
PenMargins2
,
BeginPenMargin3
, EndPenMargin3
, PenMargin3
,
PenMargins3
,
BeginDotMargin3
, EndDotMargin3
, DotMargin3
,
DotMargins3
, Margin3
, and TrueMargin3
.
The routine
void pixel(picture pic=currentpicture, triple v, pen p=currentpen, real width=1);
can be used to draw on picture pic
a pixel of width width
at
position v
using pen p
.
Further threedimensional examples are provided in the files
near_earth.asy
, conicurv.asy
, and (in the animations
subdirectory) cube.asy
.
Limited support for projected vector graphics (effectively threedimensional
nonrendered PostScript
) is available with the setting
render=0
. This currently only works for piecewise planar
surfaces, such as those produced by the parametric surface
routines in the graph3
module. Surfaces produced by the
solids
package will also be properly rendered if the parameter
nslices
is sufficiently large.
In the module bsp
, hidden surface removal of planar pictures is
implemented using a binary space partition and picture clipping.
A planar path is first converted to a structure face
derived from
picture
. A face
may be given to a twodimensional drawing
routine in place of any picture
argument. An array of such faces
may then be drawn, removing hidden surfaces:
void add(picture pic=currentpicture, face[] faces, projection P=currentprojection);
Labels may be projected to two dimensions, using projection P
,
onto the plane passing through point O
with normal
cross(u,v)
by multiplying it on the left by the transform
transform transform(triple u, triple v, triple O=O, projection P=currentprojection);
Here is an example that shows how a binary space partition may be used to draw a twodimensional vector graphics projection of three orthogonal intersecting planes:
size(6cm,0); import bsp; real u=2.5; real v=1; currentprojection=oblique; path3 y=plane((2u,0,0),(0,2v,0),(u,v,0)); path3 l=rotate(90,Z)*rotate(90,Y)*y; path3 g=rotate(90,X)*rotate(90,Y)*y; face[] faces; filldraw(faces.push(y),project(y),yellow); filldraw(faces.push(l),project(l),lightgrey); filldraw(faces.push(g),project(g),green); add(faces);
[ << ]  [ < ]  [ Up ]  [ > ]  [ >> ]  [Top]  [Contents]  [Index]  [ ? ] 
This document was generated on May 24, 2014 using texi2html 5.0.