Next: , Previous: light, Up: Base modules


7.20 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.

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,Spline);
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);

helix.png

The next example illustrates three-dimensional x, y, and z axes, with autoscaling of the upper z limit disabled:

import three;
import graph;
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);

axis3.png

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).x;
		},perpendicular(G,Z)));
generalaxis3.png

Surface plots of functions and matrices over the region box(a,b) in the XY plane are also implemented:

// draw the surface described by a matrix f, with lighting
picture surface(real[][] f, pair a, pair b,
                pen surfacepen=lightgray, pen meshpen=nullpen,
                light light=currentlight, projection P=currentprojection);

// draw the surface described by a function f, with lighting
picture surface(real f(pair z), pair a, pair b, int n=nmesh, int m=n,
                pen surfacepen=lightgray, pen meshpen=nullpen,
                light light=currentlight, projection P=currentprojection)

// draw the surface described by f, subsampling nsub times along cell edges
picture surface(real f(pair z), int nsub, pair a, pair b, int n=nmesh, 
                int m=n, pen surfacepen=lightgray, pen meshpen=currentpen,
                projection P=currentprojection);
Here is an 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)--cycle3);

draw(arc(0.12Z,0.2,90,60,90,15),ArcArrow);

picture surface=surface(f,4,(-1,-1),(1,1),10);
  
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);

surface.png Surface lighting is illustrated in the example file sinc.asy.