Next: grid3, Previous: light, Up: Base modules
graph3
This module implements three-dimensional versions of the
functions in graph.asy
. They work much like their
two-dimensional counterparts, except that the user has to keep track
of the three-dimensional axes limits (which in two dimension are stored in
the picture) in a bbox3
bounding box. The function
bbox3 autolimits(picture pic=currentpicture, triple min, triple max);can be used to determine “nice” values for the bounding box corners. A user-space bounding box that takes into account of the axes scalings for picture
pic
is returned by
bbox3 limits(picture pic=currentpicture, triple min, triple max);
To crop a bounding box to a given interval use:
void xlimits(bbox3 b, real min, real max); void ylimits(bbox3 b, real min, real max); void zlimits(bbox3 b, real min, real max); void limits(bbox3 b, triple min, triple max);
To draw an x axis in three dimensions from triple min
to
triple max
with ticks in the direction dir
, use the routine
void xaxis(picture pic=currentpicture, Label L="", triple min, triple max, pen p=currentpen, ticks ticks=NoTicks, triple dir=Y, arrowbar arrow=None, bool put=Above, projection P=currentprojection, bool opposite=false);To draw an x axis in three dimensions from triple
min
to
triple (max,min.y,min.z)
with ticks in the direction
dir
, use the routine
void xaxis(picture pic=currentpicture, Label L="", triple min, real max, pen p=currentpen, ticks ticks=NoTicks, triple dir=Y, arrowbar arrow=None, bool put=Above, projection P=currentprojection, bool opposite=false);To draw an x axis in three dimensions using
bbox3 b
with ticks in the direction dir
, use the routine
void xaxis(picture pic=currentpicture, Label L="", bool all=false, bbox3 b, pen p=currentpen, ticks ticks=NoTicks, triple dir=Y, arrowbar arrow=None, bool put=Above, projection P=currentprojection);If
all=true
, also draw opposing edges of the three-dimensional
bounding box.
Analogous routines yaxis
and zaxis
can be used to draw
y and z axes in three dimensions.
There are also some convenient routines for drawing all three axis:
void axes(picture pic=currentpicture, Label xlabel="", Label ylabel="", Label zlabel="", bbox3 b, pen p=currentpen, arrowbar arrow=None, bool put=Below, projection P=currentprojection); void axes(picture pic=currentpicture, Label xlabel="", Label ylabel="", Label zlabel="", triple min, triple max, pen p=currentpen, arrowbar arrow=None, bool put=Below, projection P=currentprojection);
Here is an example of a helix and bounding box axes with rotated tick and axis labels, using orthographic projection:
import graph3; size(0,200); currentprojection=orthographic(4,6,3); real x(real t) {return cos(2pi*t);} real y(real t) {return sin(2pi*t);} real z(real t) {return t;} defaultpen(overwrite(SuppressQuiet)); path3 p=graph(x,y,z,0,2.7,operator ..); bbox3 b=autolimits(min(p),max(p)); aspect(b,1,1,1); xaxis(rotate(X)*"$x$",all=true,b,red,RightTicks(rotate(X)*Label,2,2)); yaxis(rotate(Y)*"$y$",all=true,b,red,RightTicks(rotate(Y)*Label,2,2)); zaxis("$z$",all=true,b,red,RightTicks); draw(p,Arrow);
The next example illustrates three-dimensional x, y, and z axes, with autoscaling of the upper z limit disabled:
import graph3; size(0,200,IgnoreAspect); currentprojection=perspective(5,2,2); defaultpen(overwrite(SuppressQuiet)); scale(Linear,Linear,Log(automax=false)); bbox3 b=autolimits(Z,X+Y+30Z); xaxis("$x$",b,red,RightTicks(2,2)); yaxis("$y$",b,red,RightTicks(2,2)); zaxis("$z$",b,red,RightTicks);
One can also place ticks along a general three-dimensional axis:
import graph3; size(0,100); path3 G=xscale3(1)*(yscale3(2)*unitcircle3); axis(Label("C",align=Relative(5E)),G, LeftTicks(endlabel=false,8,end=false), ticklocate(0,360,new real(real v) { path g=G; path h=O--max(abs(max(G)),abs(min(G)))*dir(90,v); return intersect(g,h)[0]; },new pair(real t) { t /= ninterpolate; return dir(point(G,t),cross(dir(G,t),Z));}));
Surface plots of matrices and functions over the region
box(a,b)
in the XY plane are also implemented:
picture surface(real[][] f, pair a, pair b, bool[][] cond={}, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection); picture surface(triple[][] f, bool[][] cond={}, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection); picture surface(real f(pair z), pair a, pair b, int nx=nmesh, int ny=nx, bool cond(pair z)=null, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection); picture surface(real f(pair z), int nsub, pair a, pair b, int nx=nmesh, int ny=nx, bool cond(pair z)=null, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection);The boolean array or function
cond
can be used to control which
surface mesh cells are actually drawn (by default all mesh cells over
box(a,b)
are drawn).
A parametric surface for a function f(u,v) over the parameter
space box(a,b)
may be drawn with
picture surface(triple f(pair z), pair a, pair b, int nu=nmesh, int nv=nu, bool cond(pair z)=null, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection); picture surface(triple f(pair z), int nsub, pair a, pair b, int nu=nmesh, int nv=nu, bool cond(pair z)=null, bool outward=false, pen surfacepen=lightgray, pen meshpen=nullpen, light light=currentlight, projection P=currentprojection);as illustrated in the example
parametricsurface.asy
.
The optional argument nsub
allows one to subsample the function
nsub
times along the cell edges. However, smoother Gouraud shading
is used for lighting effects when this parameter is omitted. Lighting can be
disabled by setting light=O
, as in this example of a Gaussian
surface subsampled 4 times:
import graph3; size(200,0); currentprojection=perspective(5,4,2); real f(pair z) {return 0.5+exp(-abs(z)^2);} draw((-1,-1,0)--(1,-1,0)--(1,1,0)--(-1,1,0)--cycle); draw(arc(0.12Z,0.2,90,60,90,15),ArcArrow); picture surface=surface(f,nsub=4,(-1,-1),(1,1),nx=10,light=O); bbox3 b=limits(O,1.75(1,1,1)); xaxis(Label("$x$",1),b,red,Arrow); yaxis(Label("$y$",1),b,red,Arrow); zaxis(Label("$z$",1),b,red,Arrow); label("$O$",(0,0,0),S,red); add(surface);
parametricsurface.asy
and sinc.asy
.
A mesh can be drawn without solid fills by specifying nullpen
for the surfacepen. A mesh is always drawn in the absence of lighting, unless
meshpen=invisible
. For closed orientable surfaces parametrized
such that df/du \times df/dv points in the direction of the
outward normal, low-mesh-resolution lighting artifacts near the
projected edges can be avoided by specifying outward=true
,
as this forces only the outer surface to be drawn.