Three-Dimensional Graphics

Points in xyz space are expressed by vectors of homogeneous coordinates. These vectors are translated, rotated, scaled, and projected onto the two-dimensional drawing surface by multiplying them by transformation matrices. The geometrical transformations used by IDL, and many other graphics packages, are taken from Chapters 7 and 8 of Foley and Van Dam (1982). The reader is urged to consult this book for a detailed description of homogeneous coordinates and transformation matrices since this section presents only an overview.

Homogeneous Coordinates

A point in homogeneous coordinates is represented as a four-element column vector of three coordinates and a scale factor w ¹¹¹ 0. For example:

P(wx, wy, wz, w) º P(x/w, y/w, z/w, 1) º (x, y, z)

One advantage of this approach is that translation, which normally must be expressed as an addition, can be represented as a matrix multiplication. Another advantage is that homogeneous coordinate representations simplify perspective transformations. The notion of rows and columns used by IDL is opposite that of Foley and Van Dam (1982). In IDL, the column subscript is first, while in Foley and Van Dam (1982) the row subscript is first. This changes all row vectors to column vectors and transposes matrices.

Right-Handed Coordinate System

The coordinate system is right-handed so that when looking from a positive axis to the origin, a positive rotation is counterclockwise. As usual, the x-axis runs across the display, the y-axis is vertical, and the positive z-axis extends out from the display to the viewer. For example, a 90-degree positive rotation about the z-axis transforms the x-axis to the y-axis.

Transformation Matrices

 Note
For most applications, it is not necessary to create, manipulate, or to even understand transformation matrices. The procedure T3D, explained below, implements most of the common transformations.

Transformation matrices, which post-multiply a point vector to produce a new point vector, must be (4, 4). A series of transformation matrices can be concatenated into a single matrix by multiplication. If A1, A2, and A3 are transformation matrices to be applied in order, and the matrix A is the product of the three matrices, the following applies.

((P · A1) · A2) · A3 º P · ((A1 · A2) · A3) = P · A

IDL stores the concatenated transformation matrix in the system variable field !P.T.

Each of the operations of translation, scaling, rotation, and shearing can be represented by a transformation matrix.

Translation

The transformation matrix to translate a point by (Dx, Dy, Dz) is shown below.

Scaling

Scaling by factors of Sx, Sy, and Sz about the x-, y-, and z-axes respectively, is represented by the matrix below.

Rotation

Rotation about the x-, y-, and z-axes is represented respectively by the following three matrices:

T3D Procedure

The IDL procedure T3D creates and accumulates transformation matrices, storing them in the system variable field !P.T. The procedure can be used to create a transformation matrix composed of any combination of translation, scaling, rotation, perspective projection, oblique projection, and axis exchange. Transformations are applied in the order of the keyword descriptions below.

RESET

Set this keyword to reset the transformation matrix to the identity matrix to begin a new accumulation of transformations. If this keyword is not present, the current transformation matrix !P.T is post-multiplied by the new transformation. The final transformation matrix is always stored back in !P.T.

TRANSLATE

This keyword argument accepts a 3-element vector. The viewpoint is translated by the three-element vector [Tx, Ty, Tz].

SCALE

This keyword argument accepts a 3-element vector. The viewing area is scaled by factor [Sx, Sy, Sz].

ROTATE

This keyword accepts a 3-element vector. The viewing area is rotated about each axis by the amount [qx, qy, qz], in degrees.

PERSPECTIVE

A scalar (p) indicating the z distance of the center of the projection in the negative direction. Objects are projected into the xy plane, at z = 0, and the eye is at point (0, 0, -p).

OBLIQUE

A two-element vector, [d, a], specifying the parameters for an oblique projection. Points are projected onto the xy-plane at z = 0 as follows:

x0 = x + z(d cos a)

y0 = y + z(d sin a)

An oblique projection is a parallel projection in which the normal to the projection plane is the z-axis, and the unit vector (0, 0, 1) is projected to (d cos ad sin a) where a is expressed in degrees.

XYEXCH

If set, exchanges the x- and y-axes.

XZEXCH

If set, exchanges the x- and z-axes.

YZEXCH

If set, exchanges the y- and z-axes.

Example: The Transformation Created by SURFACE

The SURFACE procedure creates a transformation matrix from its keyword parameters AX and AZ as follows:

1. Starting with the identity transformation, SURFACE translates the center of the normalized cube to the origin.
2. SURFACE rotates 90 degrees about the x-axis to make the + z-axis of the data the +y axis of the display. The +y data axis extends from the front of the display to the rear.
3. SURFACE rotates AZ degrees about the y-axis. This rotates the result counter-clockwise, as seen from above the page.
4. SURFACE rotates AX degrees about the x-axis, tilting the data towards the viewer.
5. The procedure then removes the translation applied in the first step and scales the data so that the data are still contained within the normal coordinate unit cube after transformation.

These transformations can be created using T3D as shown below. The SCALE3 procedure, documented in the IDL Reference Guide, mimics the transformation matrix created by SURFACE using the following method:

```; Translate to move center of cube to origin.
T3D, /RESET, TRANSLATE = [-.5, -.5, -.5]
; Rotate 90 degrees about x-axis, so +z axis is now +y.
; Then rotate AZ degrees about y-axis.
T3D, ROTATE = [-90, AZ, 0]
; Rotate AX about x axis:
T3D, ROTATE = [AX, 0, 0]
; Restore origin.
T3D, TRANSLATE = [0.5, 0.5, 0.5]
```

The SCALE3 procedure, scales the unit cube by a fixed factor, 1/SQRT(3) to ensure that the corners of the rotated cube fit within the drawing area. If requested, it also will set the data scaling. Animations involving rotations or the SURFACE procedure should have their scaling and viewing transformation set by SCALE3 rather than the obsolete SURFR procedure, so that the scaling does not vary between frames.

Three-Dimensional Coordinate Conversion

To convert from a three-dimensional coordinate to a two-dimensional coordinate, IDL follows these steps:

• Data coordinates are converted to three-dimensional normalized coordinates. To convert the x coordinate from data to normalized coordinates, use the formula Nx = X0 + X1Dx. The same process is used to convert the y and z coordinates using !Y.S and !Z.S.
• The three-dimensional normalized coordinate, P = (Nx, Ny, Nz), whose homogeneous representation is (Nx, Ny, Nz, 1), is multiplied by the concatenated transformation matrix !P.T:

P¢ = P · `!P.T`

• The vector P¢ is scaled by dividing by w, and the normalized two-dimensional coordinates are extracted:

N¢x = P¢x/P¢w and N¢y = P¢y/P¢w

The CONVERT_COORD function performs the above process when converting to and from coordinate systems when the T3D keyword is specified. For example, if a three-dimensional coordinate system is established, then the device coordinates of the data point (0, 1, 2) can be computed as follows:

```D = CONVERT_COORD(0, 1, 2, /TO_DEVICE, /T3D, /DATA)
```

On completion, the three-element vector D will contain the desired device coordinates. The process of converting from three-dimensional to two-dimensional coordinates also can be written as an IDL function. This function accepts a three-dimensional data coordinate, returns a two-element vector containing the coordinate transformed to two-dimensional normalized coordinates using the current transformation matrix:

```FUNCTION CVT_TO_2D, X, Y, Z
; Make a homogeneous vector of normalized 3D coordinates:
P = [!X.S[0] + !X.S[1] * X, !Y.S[0] + !Y.S[1] * Y, \$
!Z.S[0] + !Z.S[1] * Z, 1]
; Transform by !P.T:
P = P # !P.T
; Return the scaled result as a two-element,
; two-dimensional, xy vector:
RETURN, [P[0] / P[3], P[1] / P[3]]
END
```

Establishing a Three-Dimensional Coordinate System

Usually, scaling parameters for coordinate conversion are set up by the higher-level procedures. To set up your own three-dimensional coordinate system with a given transformation matrix and x, y, z data range, follow these steps:

• Establish the scaling from your data coordinates to normalized coordinates-the (0, 1) cube. Assuming your data are contained in the range (Xmin, Ymin, Zmin) to (Xmax, Ymax, Zmax), set the data scaling system variables as follows:
• ```
!X.S = [ -Xmin, 1 ] / (Xmax - Xmin)

!Y.S = [ -Ymin, 1 ] / (Ymax - Ymin)

!Z.S = [ -Zmin, 1 ] / (Zmax - Zmin)
```
• Establish the transformation matrix that determines the view of the unit cube. This can be done by either calling T3D, as explained above or by directly manipulating !P.T yourself. If you wish to simply mimic the rotations provided by the SURFACE procedure, call the SCALE3 procedure (which can also be used to perform the previous step).

Example

This example draws four views of a simple house. The procedure HOUSE defines the coordinates of the front and back faces of the house. The data-to-normal coordinate scaling is set, as shown above, to a volume about 25 percent larger than that enclosing the house. The PLOTS procedure is called to draw lines describing and connecting the front and back faces. XYOUTS is called to label the front and back faces.

The commands shown after the definition of the HOUSE procedure contain four sequences of calls to T3D to establish the coordinate transformation, each followed by a call to HOUSE. If you prefer not to enter the IDL code by hand, run the batch file `showhaus` with the following command at the IDL prompt:

```@showhaus
```

See Running the Example Code if IDL does not find the batch file.

```PRO HOUSE
; X coordinates of 10 vertices. First 5 are front face,
; second 5 are back face. The range is 0 to 16.
house_x = [0, 16, 16, 8, 0, 0, 16, 16, 8, 0]
; The corresponding y values range from 0 to 16.
house_y = [0, 0, 10, 16, 10, 0, 0, 10, 16, 10]
;The z values range from 30 to 54.
house_z = [54, 54, 54, 54, 54, 30, 30, 30, 30, 30]
; Define max and min xy values to scale.
; Slightly larger than data range.
min_x = -4 & max_x = 20.
; Set x data scale to range from -4 to 20.
!X.S = [-(-4), 1.]/(20 - (-4))
; Same for y.
!Y.S = !X.S
; The z range is from 10 to 70.
!Z.S = [-10, 1.]/(70 - 10)
; Indices of front face.
face = [INDGEN(5), 0]
; Draw front face.
PLOTS, house_x[face], house_y[face], \$
house_z[face], /T3D, /DATA
; Draw back face.
PLOTS, house_x[face + 5], house_y[face + 5], \$
house_z[face + 5], /T3D, /DATA
; Connecting lines from front to back.
FOR I = 0, 4 DO PLOTS, [house_x[i], house_x[i + 5]], \$
[house_y[i], house_y[i + 5]], \$
[house_z[i], house_z[i + 5]], /T3D, /DATA
; Annotate front peak.
XYOUTS, house_x[3], house_y[3], Z = house_z[3], 'Front', \$
/T3D, /DATA, SIZE = 2
; Annotate back.
XYOUTS, house_x[8], house_y[8], Z = house_z[8], 'Back', \$
/T3D, /DATA, SIZE = 2
END
```

The HOUSE procedure could be called from the IDL command line to produce a number of different plots. For example:

```; Set up no rotation, scale, and draw house.
T3D, /RESET & HOUSE
; Create a handy constant.
H = [0.5, 0.5, 0.5]
; Straight projection after rotating 30 degrees about x and y axes.
T3D, /RESET, TRANS = -H, ROT = [30, 30, 0] & \$
T3D, TR = H & HOUSE
; No rotation, oblique projection, z factor = 0.5, angle = 45.
T3D, /RESET, TRANS = -H, ROT=[0, 0, 0], OBLIQUE=[.5, -45] & \$
T3D, TR = H & HOUSE
; Rotate 6 degrees about x and y, then apply perspective.
T3D, /RESET, TR=-H, ROT=[-6, 6, 0], PERS=4 & \$
T3D, TR=H & HOUSE
```
```
```

The figure illustrates the different transformations. The four rotations are:

• Upper left: no rotation, plain projection
• Upper right: oblique projection, factor = 0.5, angle = -45
• Bottom left: rotation of 30 degrees about both the x-and y-axes, plain projection
• Bottom right: rotation of -6 degrees about the x-axis and +6 degrees about the y-axis, and perspective projection with the eye at 4.

Rotating the House

A common procedure for visualizing three-dimensional data is to animate the data by rotating it about one or more axes. To make an animation of the house in the preceding example with the XINTERANIMATE procedure, use the following example.

```; Initialize animation: set frame size and number of frames.
sizx = 300
sizy = 300
nframes = 16
XINTERANIMATE, SET=[sizx, sizy, nframes]
; Rotate about the z axis. Draw the house.Save the window.
FOR i = 0, nframes - 1 DO BEGIN \$
SCALE3, AX = 75, AZ = i * 360. / nframes & \$
ERASE & \$
HOUSE & \$
SCALE3, AX = 75, AZ = i * 360. / nframes & \$
XINTERANIMATE, FRAME=i, WINDOW=!D.WINDOW & \$
ENDFOR
; Show the animation.
XINTERANIMATE
```

In the above example, SCALE3 rather than SCALE3D is used to maintain the same scaling in all rotations. If you prefer not to enter the IDL code by hand, run the batch file `animhaus` with the following command at the IDL prompt:

```@animhaus
```

See Running the Example Code if IDL does not find the batch file.