Next: , Previous: graph, Up: Import


4.13.4 three

This module fully extends the notion of guides and paths in Asymptote to three dimensions, introducing the new types guide3 and path3, along with a three-dimensional cycle specifier cycle3, tension operator tension3, and curl operator curl3. Just as in two dimensions, the nodes within a guide3 can be qualified with these operators and also with explicit directions and control points (using braces and controls, respectively). This generalization of John Hobby's spline algorithm is shape-invariant under three-dimensional rotation, scaling, and shifting, and reduces in the planar case to the two-dimensional algorithm used in Asymptote, MetaPost, and MetaFont.

For example, a unit circle in the XY plane may be filled and drawn like this:

import three;
size(100,0);
guide3 g=(1,0,0)..(0,1,0)..(-1,0,0)..(0,-1,0)..cycle3;
filldraw(g,lightgrey);
draw(O--Z,red+dashed,BeginBar,Arrow);
draw(((-1,-1,0)--(1,-1,0)--(1,1,0)--(-1,1,0)--cycle3));
dot(g,red);
unitcircle3.png and then distorted into a saddle:
import three;
size(100,0);
guide3 g=(1,0,0)..(0,1,1)..(-1,0,0)..(0,-1,1)..cycle3;
filldraw(g,lightgrey);
dot(g,red);
draw(((-1,-1,0)--(1,-1,0)--(1,1,0)--(-1,1,0)--cycle3));
saddle.png Here O is the triple (0,0,0) and X, Y, and Z are the triples (1,0,0), (0,1,0), and (0,0,1), respectively. A general 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 |v2-c|=|v1-c|) in the direction CCW (counter-clockwise) 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 surface for an example of a three-dimensional circular arc.

A representation of the plane passing through point O with normal cross(u,v) is given by

path3 plane(triple u, triple v, triple O=O);
A three-dimensional box with opposite vertices at triples v1 and v2 may be drawn with the function
guide3[] box(triple v1, triple v2);
For example, a unit cube is predefined as
guide3[] unitcube=box((0,0,0),(1,1,1));

These projections to two dimensions are predefined:

oblique
The point (x,y,z) is projected to (x-0.5z,y-0.5z). If an optional real argument is given to oblique, the negative z axis is drawn at this angle in degrees measured counterclockwise from the positive x axis.
orthographic(triple camera)
orthographic(real x, real y, real z)
This projects three dimensions onto two using the view seen at the location camera or (x,y,z), respectively. Parallel lines are projected to parallel lines.
perspective(triple camera)
perspective(real x, real y, real z)
These project three dimensions onto two taking account of perspective, as seen from the location camera or (x,y,z), respectively.

The default projection, currentprojection, is initially set to perspective(5,4,2).

Three-dimensional objects may be transformed with one of the following built-in transform3 types:

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;
rotate(real angle, triple v)
rotates by angle in degrees about an axis v through the origin;
rotate(real angle, triple u, triple v)
rotates by angle in degrees about the axis u--v;
reflect(triple u, triple v, triple w)
reflects about the plane through u, v, and w.

Three-dimensional versions of the path functions length, size, point, dir, precontrol, postcontrol, arclength, arctime, reverse, subpath, intersect, intersectionpoint, min, max, cyclic, and straight are also defined in the module three.

Planar hidden surface removal is implemented with a binary space partition and picture clipping. A planar path is first converted to a struct face derived from picture. A face may be given to a 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);
Here is an example showing three orthogonal intersecting planes:
size(6cm,0);
import math;
import three;

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),y,yellow);
filldraw(faces.push(l),l,lightgrey);
filldraw(faces.push(g),g,green);

add(faces);

planes.png

Here is an example showing all five three-dimensional path connectors:

import graph3;

size(0,175);

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[n-3]+(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));

bbox3 b=limits(O,(700,200,100));

xaxis(Label("$x$",1),b,red,Arrow);
yaxis(Label("$y$",1),b,red,Arrow);
zaxis(Label("$z$",1),b,red,Arrow);

dot(z);

join3.png

A three-dimensional bounding box structure is returned by calling bbox3(triple min, triple max) with the opposite corners min and max. This can be used to adjust the aspect ratio (see the example helix.asy):

void aspect(picture pic=currentpicture, bbox3 b,
            real x=0, real y=0, real z=0);

Further three-dimensional examples are provided in the files near_earth.asy, conicurv.asy, and (in the animations subdirectory) cube.asy.