The package TDPACK contains the following routines:

- Initialization Routines:
- TDINIT - define eye position, line of sight, up direction, and stereo flag
- TDPARA - define the reference parallelogram
- TDCLRS - define colors for TDPACK

- Parameter-Access Routines:
- TDGETI - get the integer value of an internal parameter
- TDGETR - get the real value of an internal parameter
- TDGTRS - get the definition of a specified rendering style
- TDSETI - set the integer value of an internal parameter
- TDSETR - set the real value of an internal parameter
- TDSTRS - define a specified rendering style

- Point-Transforming Routines:
- TDPRPT - from 3-space to the projection plane
- TDPRPA - from the plane of the reference parallelogram to the projection plane
- TDPRPI - from the projection plane to the plane of the reference parallelogram

- Line-Drawing Routines:
- TDLINE - draw the projection of a line in 3-space
- TDLNPA - draw the projection of a line in the plane of the reference parallelogram

- Grid-Drawing Routines:
- TDGRDS - draw the grids on all the faces of a box in 3-space
- TDGRID - draw the grid on a particular face of a box in 3-space

- Label-Drawing Routines:
- TDLBLS - draw labels for all faces of a box in 3-space
- TDLBLA - draw labels for a particular face of a box in 3-space
- TDPLCH - draw characters in the plane of the reference parallelogram

- Surface-Drawing Routines:
- TDDTRI - draw triangles defined by a triangle list
- TDSTRI - add triangles defining a simple surface to a triangle list
- TDITRI - add triangles defining an isosurface to a triangle list
- TDMTRI - add triangles defining a 3D marker to a triangle list
- TDOTRI - order the triangles in a triangle list for proper rendering
- TDSORT - generic sorting routine

- Simplified-Interface Routines:
- TDEZ2D - simplified interface for drawing a surface
- TDEZ3D - simplified interface for drawing an isosurface

**SUBROUTINE TDINIT (UMID, VMID, WMID, UORI, VORI, WORI, UTHI, VTHI, WTHI,
OTEP)**

#include <ncarg/ncargC.h> void c_tdinit(float umid, float vmid, float wmid, float uori, float vori, float wori, float uthi, float vthi, float wthi, float otep)

This initialization routine is called to define the position of the eye, the position of the point looked at, which way is up, and whether or not a stereo view is to be done. TDINIT precomputes some quantities in TDPACK common blocks that will subsequently be used in projecting points from 3-space (U, V, and W coordinates) to 2-space (X and Y coordinates).

By default (that is to say, if the internal parameter 'SET' has its default value), TDINIT also calls the SPPS routine SET to define the mapping from the "user" coordinate system (the X/Y system) to the "fractional" coordinate system (in GKS terms, NDC space). This is done in such a way as to show in the projection plane a field of view of 'FOV' degrees. The viewport to be used in the fractional coordinate system is that defined by the values of the internal parameters 'VPL', 'VPR', 'VPB', and 'VPT'. In some situations, it may be desirable, after calling TDINIT, to call the SPPS routine GETSET to retrieve the arguments with which TDINIT called SET and then recall SET with a different set of arguments.

Normally, the creation of an image with TDPACK starts with a call to TDINIT (perhaps preceded by calls to TDSETI, TDSETR, and/or TDSTRS to reset internal parameters of the package) and continues with calls to draw objects. (Of course, if all of the arguments in a call to TDINIT have the same values as in the last call and the SET call that was done as a result is still in effect, then it's not necessary to repeat the call to TDINIT.)

For stereo views, one calls TDINIT with a negative OTEP, executes the object-drawing calls, calls TDINIT again with a positive OTEP, and then repeats all of the object-drawing calls. The exact way in which stereo views are drawn is also affected (slightly) by the value of the internal parameter 'STE'.

To understand how to specify the values of the TDPACK arguments, it may be helpful to examine this figure.

**UMID**, **VMID**, and **WMID** are input reals defining
the position of the eye, (if a single view is being drawn), or of a
point midway between the two eyes (if a stereo view is being drawn).

**UORI**, **VORI**, and **WORI** are input reals defining the
position of the point the eye is looking at. That point defines the origin
of the XY projection plane.

**UTHI**, **VTHI**, and **WTHI** are input reals defining the
position of the third point needed to completely specify the orientation
of the projection plane.

**OTEP** ("Offset To Eye Position") is an input real which is non-zero
if and only if a stereo view is to be drawn. Make the value negative to draw
a left-eye view, positive to draw a right-eye view. The magnitude of OTEP
is the distance from either eye to the point midway between the eyes; if R
represents the approximate distance from the eye to the objects being
drawn, then OTEP may be set using a statement like

OTEP = (+ or -) R * TAN(.017453292519943*ANGD/2.)

where the constant (.01745...) is just pi/180 and ANGD is the desired difference in the angle between the two views, in degrees; use a value of about 1 or 2 degrees for ANGD.

Note that, if the origin is approximately in the middle of the objects being viewed, then it's probably appropriate to use a value of R computed as follows:

R = SQRT((UMID-UORI)**2+(VMID-VORI)**2+(WMID-WORI)**2)

**SUBROUTINE TDPARA (UA00, VA00, WA00, UV10, VV10, WV10, UV01, VV01, WV01)**

#include <ncarg/ncargC.h> void c_tdpara(float ua00, float va00, float wa00, float uv10, float vv10, float wv10, float uv01, float vv01, float wv01)

This routine may be thought of as an initialization routine or as just a routine to access certain internal values; it simply transfers the values of its arguments into TDPACK labelled common blocks for later use by other TDPACK routines. These values define a "reference parallelogram". Each point in the plane in which the parallelogram lies can be identified by specifying its "parallelogram coordinates": a pair of reals, one of which may be thought of as an "X" coordinate and the other of which may be thought of as a "Y" coordinate.

Calls to TDPARA may be positioned without regard to calls to TDINIT because the two routines do not affect one another. Redefining the reference parallelogram affects the behavior of each of the routines TDPRPA, TDPRPI, TDGRID, TDLBLA, and TDPLCH, each of which makes use of parallelogram coordinates in some way. Be aware that each of the routines TDGRDS and TDLBLS calls TDPARA to redefine the reference parallelogram and neither of them restores the original definition when it is done.

If a point has "parallelogram coordinates" (XIPA,YIPA), then its actual 3-space coordinates are given by the following equations:

U = UA00+XIPA*UV10+YIPA*UV01 V = VA00+XIPA*VV10+YIPA*VV01 W = WA00+XIPA*WV10+YIPA*WV01

The point with parallelogram coordinates (0,0) is in what might be thought
of as the "lower left" corner of the parallelogram, while the point with
parallelogram coordinates (1,1) is in what might be thought of as the
"upper right" corner of the parallelogram. **Any** point of the plane
in which the reference parallelogram lies can be identified using its
parallelogram coordinates, not just the points inside the parallelogram
itself.

Note that, although the reference parallelogram doesn't have to be rectangular, a non-rectangular one is probably not very useful; in fact, a square one defined by unit vectors is probably best, particularly if one is drawing characters in the plane of the reference parallelogram. For example, suppose that you want to write the characters "THE U/V PLANE" in that part of the U/V plane with U values between 0 and 100 and V values between 0 and 200; it is probably best, in this case, to use a reference parallelogram with an origin at (0,0,0), an "X" side with components (1,0,0) and a "Y" side with components (0,1,0). Then, in the call to TDPLCH, one can place the character string at parallelogram coordinates (50,100) and use a character size of 1.5. If one used a reference parallelogram with an origin at (0,0,0), an "X" side with components (100,0,0) and a "Y" side with components (0,200,0), one could place the character string at parallelogram coordinates (.5,.5) and use a character size of .015, but the characters written would be twice as high as they are wide, which is undesirable.

**UA00**, **VA00**, and **WA00** are input reals defining the
position of the "origin" of the parallelogram: the point with parallelogram
coordinates (0,0).

**UV10**, **VV10**, and **WV10** are input reals defining the U, V,
and W components of the vector from the origin of the parallelogram to the
point with parallelogram coordinates (1,0).

**UV01**, **VV01**, and **WV01** are input reals defining the U, V,
and W components of the vector from the origin of the parallelogram to the
point with parallelogram coordinates (0,1).

**SUBROUTINE TDCLRS (IWID, IBOW, SHDE, SHDR, IOFC, IOLC, ILMT)**

#include <ncarg/ncargC.h> void c_tdclrs(int iwid, int ibow, float shde, float shdr, int iofc, int iolc, int ilmt)

This routine is called to do the GKS calls defining the following colors on a specified workstation (NSHD is equal to IOLC-IOFC+1, the number of elements in each block of color shades):

Color 0 = the background color (black or white, depending on IBOW) Color 1 = the foreground color (white or black, depending on IBOW) Color 2 = pure red (RGB values 1,0,0) Color 3 = pure green (RGB values 0,1,0) Color 4 = pure blue (RGB values 0,0,1) Color 5 = pure cyan (RGB values 0,1,1) Color 6 = pure magenta (RGB values 1,0,1) Color 7 = pure yellow (RGB values 1,1,0) Colors IOFC through IOLC = gray shades, from white to black Colors IOFC+NSHD through IOLC+NSHD = shades of gray Colors IOFC+2*NSHD through IOLC+2*NSHD = shades of red Colors IOFC+3*NSHD through IOLC+3*NSHD = shades of green Colors IOFC+4*NSHD through IOLC+4*NSHD = shades of blue Colors IOFC+5*NSHD through IOLC+5*NSHD = shades of cyan Colors IOFC+6*NSHD through IOLC+6*NSHD = shades of magenta Colors IOFC+7*NSHD through IOLC+7*NSHD = shades of yellow

The colors defined by calling TDCLRS may be used for any purpose, but they are particularly useful when calling TDPACK routines to render surfaces.

**IWID** is an input expression of type INTEGER specifying the
workstation identifier.

**IBOW** is an input expression of type INTEGER specifying the basic color
scheme (white on black or black on white). If IBOW is 0, the foreground color
is white and the background color is black; if IBOW is non-zero, the opposite
is true.

**SHDE** and **SHDR** are input expressions of type REAL, each between
0 and 1, inclusive, specifying how color shades are to be generated. Values
of SHDE near 0 call for more intense shades to be used, while values near 1
call for more nearly pastel shades to be used. Values of SHDR near 0 say
that a narrower range of shades is to be used, while values near 1 say that
a broader range of shades is to be used.

**IOFC** and **IOLC** are input expressions of type INTEGER specifying
the first and last integers in a block of color indices to be used for NSHD
shades of gray ranging from pure white to pure black (where NSHD=IOLC-IOFC+1).
The next NSHD indices (in numerical order) will be used for the shades of gray
selected by SHDE and SHDR; the next NSHD indices after that for selected shades
of red, the next NSHD indices after that for selected shades of green, and so
on.

**ILMT** is an input expression of type INTEGER. Using a value between
1 and 7, inclusive, says that only that many blocks of NSHD indices will be
defined. For example, if ILMT has the value 4, only the black-to-white scale
and the shades of gray, red, and green will be generated; shades of blue, cyan,
magenta, and yellow will not be. (This allows one to have more shades of each
color at the expense of using fewer colors.) Using a value of ILMT less than
1 or greater than 7 will result in all 8*NSHD sets of color shades being
defined.

**SUBROUTINE TDGETI (PNAM, IVAL)**

#include <ncarg/ncargC.h> void c_tdgeti(char *pnam, int *ival)

Retrieve the value of an internal parameter. (For names and descriptions of all the internal parameters, look here).

**PNAM** is an input character string, the first three characters of which
is the name of an internal parameter of TDPACK whose value is to be retrieved.
It is recommended that the other characters of PNAM be used to describe the
internal parameter; for example, use 'FOV - FIELD OF VIEW, IN DEGREES'
instead of just 'FOV'.

**IVAL** is an output variable of type INTEGER in which the value of the
internal parameter is to be returned. If the internal parameter is
intrinsically of type REAL and has the value RVAL, then INT(RVAL) is returned
in IVAL.

**SUBROUTINE TDGETR (PNAM, RVAL)**

#include <ncarg/ncargC.h> void c_tdgetr(char *pnam, float *rval)

Retrieve the value of an internal parameter. (For names and descriptions of all the internal parameters, look here).

**PNAM** is an input character string, the first three characters of which
is the name of an internal parameter of TDPACK whose value is to be retrieved.
It is recommended that the other characters of PNAM be used to describe the
internal parameter; for example, use 'FOV - FIELD OF VIEW, IN DEGREES'
instead of just 'FOV'.

**RVAL** is an output variable of type REAL in which the value of the
internal parameter is to be returned. If the internal parameter is
intrinsically of type INTEGER and has the value IVAL, then REAL(IVAL) is
returned.

**SUBROUTINE TDGTRS (IRST, IFC1, IFC2, IFC3, IFC4, ILC1, ILC2, ILTD, USTP,
VSTP, WSTP)**

#include <ncarg/ncargC.h> void c_tdgtrs(int irst, int *ifc1, int *ifc2, int *ifc3, int *ifc4, int *ilc1, int *ilc2, int *iltd, float *ustp, float *vstp, float *wstp)

Get the values defining a selected rendering style. (The "rendering styles" affect the appearance of the triangles drawn by a call to the routine TDDTRI.)

**IRST** is an input integer specifying the index of the particular rendering
style which is to be retrieved.

**IFC1**, **IFC2**, **IFC3**, **IFC4**, **ILC1**,
**ILC2**, **ILTD**, **USTP**, **VSTP**, and **WSTP** are
described here.

**SUBROUTINE TDSETI (PNAM, IVAL)**

#include <ncarg/ncargC.h> void c_tdseti(char *pnam, int ival)

Set the value of an internal parameter. (For names and descriptions of all the internal parameters, look here).

**PNAM** is an input character string, the first three characters of which
is the name of an internal parameter of TDPACK whose value is to be changed.
It is recommended that the other characters of PNAM be used to describe
the internal parameter; for example, use 'FOV - FIELD OF VIEW, IN DEGREES'
instead of just 'FOV'.

**IVAL** is an input expression of type INTEGER whose value is the desired
new value of the internal parameter. If the internal parameter is intrinsically
of type REAL, it will be given the value REAL(IVAL).

**SUBROUTINE TDSETR (PNAM, RVAL)**

#include <ncarg/ncargC.h> void c_tdsetr(char *pnam, float rval)

Set the value of an internal parameter. (For names and descriptions of all the internal parameters, look here).

**PNAM** is an input character string, the first three characters of which
is the name of an internal parameter of TDPACK whose value is to be changed.
It is recommended that the other characters of PNAM be used to describe
the internal parameter; for example, use 'FOV - FIELD OF VIEW, IN DEGREES'
instead of just 'FOV'.

**RVAL** is an input expression of type REAL whose value is the desired new
value of the internal parameter. If the internal parameter is intrinsically of
type INTEGER, it will be given the value INT(RVAL).

**SUBROUTINE TDSTRS (IRST, IFC1, IFC2, IFC3, IFC4, ILC1, ILC2, ILTD, USTP,
VSTP, WSTP)**

#include <ncarg/ncargC.h> void c_tdstrs(int irst, int ifc1, int ifc2, int ifc3, int ifc4, int ilc1, int ilc2, int iltd, float ustp, float vstp, float wstp)

Set the values defining a selected rendering style. (The "rendering styles" affect the appearance of the triangles drawn by a call to the routine TDDTRI.)

**IRST** is an input integer specifying the index of the particular rendering
style which is to be changed.

**IFC1**, **IFC2**, **IFC3**, **IFC4**, **ILC1**,
**ILC2**, **ILTD**, **USTP**, **VSTP**, and **WSTP** are
described here.

**SUBROUTINE TDPRPT (UI3D, VI3D, WI3D, XI2D, YI2D)**

#include <ncarg/ncargC.h> void c_tdprpt(float ui3d, float vi3d, float wi3d, float *xi2d, float *yi2d)

Given the coordinates of a point in 3-space, get the coordinates of its projection in the projection plane.

**UI3D**, **VI3D**, and **WI3D** are input reals specifying the
coordinates of a point in 3-space.

**XI2D** and **YI2D** are output reals specifying the coordinates of
the projection in 2-space.

**SUBROUTINE TDPRPA (XIPA, YIPA, XI2D, YI2D)**

#include <ncarg/ncargC.h> void c_tdprpa(float xipa, float yipa, float *xi2d, float *yi2d)

Given the parallelogram coordinates of a point, get the coordinates of its projection in the projection plane. This routine is essentially the inverse of the routine TDPRPI.

**XIPA** and **YIPA** are input reals specifying the parallelogram
coordinates of a point. (The parallelogram is as defined by a prior call
to TDPARA.)

**XI2D** and **YI2D** are output reals specifying the coordinates of
the projection of the point in the projection plane.

**SUBROUTINE TDPRPI (XI2D, YI2D, XIPA, YIPA)**

#include <ncarg/ncargC.h> void c_tdprpi(float xi2d, float yi2d, float *xipa, float *yipa)

Given a point in the projection plane, retrieve the parallelogram coordinates of that point in the reference parallelogram (as defined by the last call to TDPARA) that projects into it. This routine is essentially the inverse of the routine TDPRPA.

**XI2D** and **YI2D** are input reals specifying the coordinates of a
point in the projection plane.

**XIPA** and **YIPA** are output reals specifying the parallelogram
coordinates of that point in the reference parallelogram that projects into
(XI2D,YI2D).

**SUBROUTINE TDLINE (UCP1, VCP1, WCP1, UCP2, VCP2, WCP2)**

#include <ncarg/ncargC.h> void c_tdline(float ucp1, float vcp1, float wcp1, float ucp2, float vcp2, float wcp2)

Draw the projection of a line joining two points in 3-space.

**UCP1**, **VCP1**, and **WCP1** are input reals - the 3-space
coordinates of the first 3-space point.

**UCP2**, **VCP2**, and **WCP2** are input reals - the 3-space
coordinates of the second 3-space point.

**SUBROUTINE TDLNPA (XCP1, YCP1, XCP2, YCP2)**

#include <ncarg/ncargC.h> void c_tdlnpa(float xcp1, float ycp1, float xcp2, float ycp2)

Draw the projection of a line joining two points in the reference parallelogram (as defined by the last call to TDPARA).

**XCP1** and **YCP1** are input reals - the parallelogram coordinates
of the first point in the reference parallelogram.

**XCP2** and **YCP2** are input reals - the parallelogram coordinates
of the second point in the reference parallelogram.

**SUBROUTINE TDGRDS (UMIN, VMIN, WMIN, UMAX, VMAX, WMAX, USTP, VSTP, WSTP,
IGRT, IHID)**

#include <ncarg/ncargC.h> void c_tdgrds(float umin, float vmin, float wmin, float umax, float vmax, float wmax, float ustp, float vstp, float wstp, int igrt, int ihid)

Draw perimeters, optionally with ticks or grid lines, on the six sides of a box. This routine calls TDPARA and will therefore change the definition of the reference parallelogram.

**UMIN**, **VMIN**, **WMIN**, **UMAX**, **VMAX**, and
**WMAX** are real input values, each of
which specifies one of the coordinate values defining the box in 3-space.
The names of these should make it clear what they are.

**USTP**, **VSTP**, and **WSTP** are real input values specifying
step sizes between ticks or grid lines in the U direction, the V direction,
and the W direction, respectively. If one of these values is less than or
equal to zero, the ticks or grid lines in the associated direction are
omitted.

**IGRT** is an integer input value of the form 10*IGRN+IGRF, where IGRN is
a value specifying what to draw on the near sides of the box and IGRF is a
value specifying what to draw on the far sides of the box, where "near"
and "far" are as defined by the current line of sight. Each of IGRN and
IGRF can have one of the values 0 (draw nothing), 1 (draw just a perimeter),
2 (draw a perimeter with inward-pointing ticks), or 3 (draw a perimeter
with a grid). For example, to draw grids on the far side of the box and
just perimeters on the near sides of the box, use IGRT = 13.

**IHID** is an integer input value set to 0 to draw only those sides of the
box that cannot be hidden by something inside the box or to 1 to draw only those
sides of the box that can be hidden by something inside the box. Standard
operating procedure is to call TDGRDS before drawing surfaces inside a box,
with IHID set to 1, and then call it again after drawing surfaces inside a
box, with IHID set to 0.

**SUBROUTINE TDGRID (XBEG, XSTP, NOXS, YBEG, YSTP, NOYS, IGRD)**

#include <ncarg/ncargC.h> void c_tdgrid(float xbeg, float xstp, int noxs, float ybeg, float ystp, int noys, int igrd)

Draw a perimeter, optionally with ticks or grid lines, around the edges of the reference parallelogram defined by the last call to TDPARA. This routine is normally called indirectly (by virtue of a call to TDGRDS), but there is no reason why it should not be called directly.

**XBEG**, **XSTP**, and **NOXS** define where ticks or grid lines
are to be drawn along the "X" axis of the parallelogram (at XBEG, XBEG+XSTP,
XBEG+2*XSTP, ... XBEG+NOXS*XSTP). XBEG and XSTP are input reals and NOXS is
an input integer.

**YBEG**, **YSTP**, and **NOYS** define where ticks or grid lines
are to be drawn along the "Y" axis of the parallelogram (at YBEG, YBEG+YSTP,
YBEG+2*YSTP, ... YBEG+NOYS*YSTP). YBEG and YSTP are input reals and NOYS is
an input integer.

**IGRD** defines what is to be drawn and has one of the values 1 (draw
just a perimeter), 2 (draw a perimeter with inward-pointing ticks), or 3
(draw a perimeter with a grid).

**SUBROUTINE TDLBLS (UMIN, VMIN, WMIN, UMAX, VMAX, WMAX, UNLB, VNLB, WNLB,
UILB, VILB, WILB, IPCK)**

#include <ncarg/ncargC.h> void c_tdlbls(float umin, float vmin, float wmin, float umax, float vmax, float wmax, char* unlb, char* vnlb, char* wnlb, char* uilb, char* vilb, char* wilb, int ipck)

Draw labels on selected sides of a projected box. This routine calls TDPARA and will therefore change the definition of the reference parallelogram; it also changes the value of the internal parameter 'CS2'.

**UMIN**, **VMIN**, **WMIN**, **UMAX**, **VMAX**, and
**WMAX** are input expressions of type REAL, each of which
specifies one of the coordinate values defining the box in 3-space. The
names of these should make it clear what they are.

**UNLB**, **VNLB**, and **WNLB** are character strings containing
numeric labels to be
placed on a U axis, a V axis, or a W axis, respectively. The labels need
not be in any particular order, but they have to be separated by blanks and
each has to be readable using a FORTRAN format of the form "En.0", where
"n" is the length of the label.

**UILB**, **VILB**, and **WILB** are character strings containing
informational labels
for a U axis, a V axis, or a W axis, respectively.

**IPCK** is an input integer determining which edges of the box are labelled.
If IPCK is zero, all six outer edges are labelled, but if IPCK is non-zero,
only three edges are labelled, one set of three if IPCK is negative, a
different set if IPCK is positive.

**SUBROUTINE TDLBLA (IAXS, ILBL, NLBL, XAT0, XAT1, YAT0, YAT1, ANGD)**

#include <ncarg/ncargC.h> void c_tdlbla(int iaxs, char* ilbl, char* nlbl, float xat0, float xat1, float yat0, float yat1, float angd)

This routine is called to put labels on a particular edge of a box.

It is assumed that TDPARA has been called to define the reference parallelogram to be a rectangle in 3-space lying in one corner of one face of the box being labelled. The sides of this rectangle are assumed to be vectors of length 1 (that is to say, the rectangle defines a unit square within that face of the box). It is also assumed that the value of the internal parameter 'CS2' has been set in the same way that TDLBLS would reset it, using a code sequence like

CALL TDGETR ('CS1',CSM1) CSM2=CSM1*MIN(UMAX-UMIN,VMAX-VMIN,WMAX-WMIN) CALL TDSETR ('CS2',CSM2)

(where UMIN, UMAX, VMIN, VMAX, WMIN, and WMAX are as defined for a call to TDLBLS).

**IAXS** is an input integer saying which edge of the face is being labelled
(1 => left, 2 => right, 3 => bottom, and 4 => top, where the meanings of
"left", "right", "bottom", and "top" are defined by the orientation of the
reference parallelogram).

**ILBL** is an input character string to be used as an informational label. If
the string is blank, no informational label is written.

**NLBL** is an input character string containing numeric labels. The labels need
not be in any particular order, but they have to be separated by blanks and
each has to be readable using a FORTRAN format of the form "En.0", where "n"
is the length of the label. If the string is blank, no informational label
is written.

**XAT0** and **XAT1** are the real values of "X" associated with the
left and right edges of the face being labelled, where "left" and "right"
are defined in terms of the current reference parallelogram.

**YAT0** and **YAT1** are the real values of "Y" associated with the
bottom and top edges of the face being labelled, where "bottom" and "top"
are defined in terms of the current reference parallelogram.

**ANGD** is an input real specifying the angle, in degrees, at which the
labels are to be written. This angle is defined with reference to the current
reference parallelogram.

**SUBROUTINE TDPLCH (XPOS, YPOS, CHRS, SIZE, ANGD, CNTR)**

#include <ncarg/ncargC.h> void c_tdplch(float xpos, float ypos, char *chrs, float size, float angd, float cntr)

Draw a character string at a specified position in the plane of the reference parallelogram.

**XPOS** and **YPOS** are input reals specifying the parallelogram
coordinates of a point relative to which the character string is to be
positioned.

**CHRS** is an input character string, suitable for input to the PLOTCHAR
routine PLCHHQ.

**SIZE** is an input real, specifying the width of the characters to be
used as a multiple of the "X" dimension of the reference parallelogram. If
the reference parallelogram is not a square, distortion of the characters
is to be expected: for example, if the reference parallelogram is twice
as wide as it is high, then the same will be true of characters drawn by
TDPLCH.

**ANGD** is an input real specifying the angle, in degrees, at which the
character string is to be drawn relative to the reference parallelogram
(0 => in the direction of positive X, 90 => in the direction of
positive Y, 180 => in the direction of negative X, and so on).

**CNTR** is an input real specifying how the character string is to be
centered relative to the point (XPOS,YPOS) within the reference parallelogram.
If CNTR = -1, the leading edge of the character string will be placed at
(XPOS,YPOS); if CNTR = 0, the center of the character string will be placed
at (XPOS,YPOS); and if CNTR = +1, the trailing edge of the character string
will be placed at (XPOS,YPOS). Other values may be used, with the logical
results; for example, if CNTR = -.5, the point halfway between the leading
edge and the center of the character string will be placed at (XPOS,YPOS).

**SUBROUTINE TDDTRI (RTRI, MTRI, NTRI, ITWK)**

#include <ncarg/ncargC.h> void c_tddtri(float *rtri, int mtri, int *ntri, int *itwk)

Draw the triangles defined by a triangle list (arguments RTRI, MTRI, and NTRI). The triangles are drawn in the order specified by the contents of the permutation array ITWK.

The exact manner in which each triangle is drawn depends on the rendering style selected for it. Generally, it is first filled with a user-selected color; if a wire-frame image is desired and no lines are to be considered hidden, this step may be skipped. The fill color can be a specific one chosen by the user (sometimes, it is useful to pick the background color) or one selected from a range of user-specified colors according to the angle between a line from the light source to the center of the triangle and the normal to the plane of the triangle (which results in a shading of the surface). After the triangle is filled, line segments representing its boundary and/or its intersection with planes of constant U, V, and/or W may be drawn in a user-specified contrasting color.

**RTRI** is a real input array, dimensioned 10 by MTRI, in which a list of
triangles has been stored, probably by means of calls to
TDSTRI,
TDITRI, and/or
TDMTRI,
and sorted, probably by means of a call to
TDOTRI.

If you put triangles in the triangle list directly, keep in mind the
following: For each value of *i* from 1
to NTRI, RTRI(1,*i*), RTRI(2,*i*), and RTRI(3,*i*) are the U, V,
and W coordinates of the first vertex of the triangle, RTRI(4,*i*),
RTRI(5,*i*), and RTRI(6,*i*) are the U, V, and W coordinates of the
second vertex of the triangle, RTRI(7,*i*), RTRI(8,*i*), and
RTRI(9,*i*) are the U, V, and W coordinates of the third vertex of the
triangle, and RTRI(10,*i*)=REAL(*irst*), where *irst* is the
index of the desired rendering style array for the triangle. The order of
the vertices is meaningful: they must be given in counter-clockwise order
as viewed from the "top". It is better if all of the triangles in a triangle
list are about the same size.

**MTRI** is an input integer specifying the second dimension of RTRI and
thus the maximum number of triangles the triangle list will hold.

**NTRI** is an input integer specifying the number of triangles currently
in the triangle list. (It is the user's responsibility to zero this initially;
its value is increased by each call to a triangle-generating routine like
TDSTRI,
TDITRI, or
TDMTRI and may be increased by a call
to the triangle-ordering routine TDOTRI.)

**ITWK** is an integer input array, dimensioned at least NTRI, containing
a permutation of the integers from 1 to NTRI (probably generated by calling
the routine TDOTRI).

**SUBROUTINE TDSTRI (U, NU, V, NV, W, LW1D, RTRI, MTRI, NTRI, IRST)**

#include <ncarg/ncargC.h> void c_tdstri(float *u, int nu, float *v, int nv, float *w, int lw1d, float *rtri, int mtri, int *ntri, int irst)

Add triangles defining a simple surface to the triangles in a triangle list.

**U** is a real input array, dimensioned NU, in which are stored values of
an independent variable *u*. It must be the case that U(1) < U(2) < ...
U(NU-1) < U(NU).

**NU** is an input integer specifying the dimension of the array U.

**V** is a real input array, dimensioned NV, in which are stored values of
an independent variable *v*. It must be the case that V(1) < V(2) < ...
V(NV-1) < V(NV).

**NV** is an input integer specifying the dimension of the array V.

**W** is a real input array, dimensioned NU by NV and having FORTRAN first
dimension LW1D, in which are stored values of a dependent variable
*w(u,v)*. The points (((U(I),V(J),W(I,J)),I=1,NU),J=1,NV) define a
surface that one wishes to draw.

**LW1D** is an input integer specifying the FORTRAN first dimension of the
array W. It must be the case that LW1D is greater than or equal to NU.

**RTRI** is a real input/output array, dimensioned 10 by MTRI, in which a
list of triangles is stored.

**MTRI** is an input integer specifying the second dimension of RTRI and thus
the maximum number of triangles the triangle list will hold.

**NTRI** is an input/output integer specifying the number of triangles
currently in the triangle list. It is the user's responsibility to zero this
initially and its value is increased by each call to a triangle-generating
routine like TDSTRI. If NTRI becomes equal to MTRI, TDSTRI does not take an
error exit; instead, it just stops generating triangles. Therefore, it's a
good idea, after calling TDSTRI, to check the value of NTRI against the
dimension MTRI; if they're equal, it probably means that the triangle list
filled up and that the rendered surface will be incomplete.

**IRST** is an input integer specifying the index of the rendering style to
to be used for the triangles added to the triangle list by this call.
Look here for descriptions
of the internal parameters defining the rendering styles,
here for a description
of the routine used to get the values of these internal parameters, and
here for a description
of the routine used to set their values.

**SUBROUTINE TDITRI (U, NU, V, NV, W, NW, F, LF1D, LF2D, FISO, RTRI, MTRI,
NTRI, IRST)**

#include <ncarg/ncargC.h> void c_tditri(float *u, int nu, float *v, int nv, float *w, int nw, float *f, int lf1d, int lf2d, float fiso, float *rtri, int mtri, int *ntri, int irst)

Add triangles defining an isosurface to the triangles in a triangle list.

**U** is a real input array, dimensioned NU, in which are stored values of
an independent variable *u*. It must be the case that U(1) < U(2) < ...
U(NU-1) < U(NU).

**NU** is an input integer specifying the dimension of the array U.

**V** is a real input array, dimensioned NV, in which are stored values of
an independent variable *v*. It must be the case that V(1) < V(2) < ...
V(NV-1) < V(NV).

**NV** is an input integer specifying the dimension of the array V.

**W** is a real input array, dimensioned NW, in which are stored values of
an independent variable *w*. It must be the case that W(1) < W(2) < ...
W(NW-1) < W(NW).

**NW** is an input integer specifying the dimension of the array W.

**F** is a real input array having first and second FORTRAN dimensions LF1D
and LF2D, respectively, in which are stored the values of a dependent
variable *f(u,v,w)*. F(I,J,K) is the value of the function *f* at
the position (U(I),V(J),W(K)); the equation "*f(u,v,w)=FISO*" defines a
surface that one wishes to draw.

**LF1D** and **LF2D** are the first and second FORTRAN dimensions of the
array F. It must be the case that LF1D is greater than or equal to NU and that
LF2D is greater than or equal to NV.

**FISO** is that value of the function *f* defining the isosurface to
be drawn.

**RTRI** is a real input/output array, dimensioned 10 by MTRI, in which a
list of triangles is stored.

**MTRI** is an input integer specifying the second dimension of RTRI and thus
the maximum number of triangles the triangle list will hold.

**NTRI** is an input/output integer specifying the number of triangles
currently in the triangle list. It is the user's responsibility to zero this
initially and its value is increased by each call to a triangle-generating
routine like TDITRI. If NTRI becomes equal to MTRI, TDITRI does not take an
error exit; instead, it just stops generating triangles. Therefore, it's a
good idea, after calling TDITRI, to check the value of NTRI against the
dimension MTRI; if they're equal, it probably means that the triangle list
filled up and that the rendered surface will be incomplete.

**IRST** is an input integer specifying the index of the rendering style to
to be used for the triangles added to the triangle list by this call.
Look here for descriptions
of the internal parameters defining the rendering styles,
here for a description
of the routine used to get the values of these internal parameters, and
here for a description
of the routine used to set their values.

**SUBROUTINE TDMTRI (IMRK, UMRK, VMRK, WMRK, SMRK, RTRI, MTRI, NTRI, IRST,
UMIN, VMIN, WMIN, UMAX, VMAX, WMAX)**

#include <ncarg/ncargC.h> void c_tdmtri(int imrk, float umrk, float vmrk, float wmrk, float smrk, float *rtri, int mtri, int *ntri, int irst, float umin, float vmin, float wmin, float umax, float vmax, float wmax)

Add triangles defining a 3D marker to the triangles in a triangle list.

**IMRK** is an input expression of type INTEGER having an absolute value
between 1 and 5, inclusive, specifying the type of marker to be generated. If
the value of IMRK is less than zero, the triangles will not be clipped against
the sides of the data box, otherwise, they will.

**UMRK**, **VMRK**, and **WMRK** are input expressions of type REAL
specifying the 3-space coordinates of the center point of the marker.

**SMRK** is an input expression of type REAL specifying the radius of the
marker in 3-space.

**RTRI** is a real input/output array, dimensioned 10 by MTRI, in which a
list of triangles is stored.

**MTRI** is an input integer specifying the second dimension of RTRI and thus
the maximum number of triangles the triangle list will hold.

**NTRI** is an input/output integer specifying the number of triangles
currently in the triangle list. It is the user's responsibility to zero this
initially and its value is increased by each call to a triangle-generating
routine like TDMTRI. If NTRI becomes equal to MTRI, TDMTRI does not take an
error exit; instead, it just stops generating triangles. Therefore, it's a
good idea, after calling TDMTRI, to check the value of NTRI against the
dimension MTRI; if they're equal, it probably means that the triangle list
filled up and that the rendered marker will be incomplete.

**IRST** is an input integer specifying the index of the rendering style to
to be used for the triangles added to the triangle list by this call.
Look here for descriptions
of the internal parameters defining the rendering styles,
here for a description
of the routine used to get the values of these internal parameters, and
here for a description
of the routine used to set their values.

**UMIN**, **VMIN**, **WMIN**, **UMAX**, **VMAX**, and
**WMAX** are input expressions of type REAL, each of which
specifies one of the coordinate values defining the data box in 3-space. The
names of these should make it clear what they are.

**SUBROUTINE TDOTRI (RTRI, MTRI, NTRI, RTWK, ITWK, IORD)**

#include <ncarg/ncargC.h> void c_tdotri(float *rtri, int mtri, int *ntri, float *rtwk, int *itwk, int iord)

This routine, given a list of NTRI triangles in the array RTRI and a real scratch array RTWK of length at least MTRI x 2 , determines the order in which the triangles are to be rendered and returns a permutation of the integers from 1 to NTRI in the array ITWK, defining that permutation.

The caller may select any of three ways in which the triangles are to be ordered, the first two of which are essentially identical: When the argument IORD is given the value 0, the distances of the midpoints of the triangles from the viewpoint are computed and the triangles are sorted by decreasing order of these distances. When IORD is given the value -1, the result is the same, except that the distances of the farthest points of the triangles from the viewpoint are computed and the triangles are put in decreasing order of those distances. Both of these possibilities are appropriate for situations in which the triangles represent smooth surfaces that do not intersect each other or themselves; the occasional small errors in the resulting rendering order should be acceptable.

If any of the triangles in the list intersect each other or if the surfaces being depicted are too rough, then the third option should be used: When IORD is given the value +1, TDOTRI executes an algorithm taken from the reference "Computer Graphics Principles and Practice", by Foley and Van Dam. It starts by ordering the triangles as if IORD had the value -1 (using distances of the far points of the triangles from the viewpoint), but then it checks for situations in which this ordering is in error and fixes the errors. Executing this algorithm can be time-consuming, so it should not be done unless it is really necessary; one possible way to proceed might be to use IORD = -1 while checking out a code and then use IORD = +1 only when doing final plots.

Sometimes, when IORD = +1, triangles must be broken into smaller triangles, thereby increasing the total number of triangles in RTRI. If, as a result of this, NTRI becomes equal to MTRI, no error exit is taken; instead, TDOTRI just returns control to the caller. Therefore, it's a good idea, after calling TDOTRI, to check the value of NTRI against the dimension MTRI; if they're equal, it probably means that the triangle list filled up and that using the permutation returned in ITWK will result in an incorrect rendering of the triangles.

**RTRI** is a real input/output array, dimensioned 10 by MTRI, in which a
list of triangles has been stored, probably by means of calls to
TDSTRI and/or
TDITRI. As described above, the number
of triangles in the list may increase as a result of calling TDOTRI.

**MTRI** is an input integer specifying the second dimension of RTRI and
thus the maximum number of triangles the triangle list will hold.

**NTRI** is an input/output integer specifying the number of triangles
currently in the triangle list. It is the user's responsibility to zero
this initially; its value is increased by each call to a triangle-generating
routine like
TDSTRI or
TDITRI and
may be increased by a call to TDOTRI.

**RTWK** is a real scratch array, dimensioned at least MTRIx2.

**ITWK** is an integer output array, dimensioned at least MTRI, returned
containing a permutation of the integers from 1 to NTRI, specifying the
order in which the triangles ought to be rendered.

**IORD** is an integer input expression that says how the triangles are
to be ordered. The value 0 implies ordering by decreasing distance of the
triangle midpoints from the eye, -1 implies ordering by decreasing distance
of the triangle farpoints from the eye, and +1 implies ordering by decreasing
distance of the triangle farpoints from the eye, with adjustments made by
running an algorithm from the reference "Computer Graphics Principles and
Practice", by Foley and Van Dam.

**SUBROUTINE TDSORT (RWRK, NRWK, IORD, IWRK)**

#include <ncarg/ncargC.h> void c_tdsort(float *rwrk, int nwrk, int iord, int *iwrk)

This is an internal routine used for sorting. It is not intended that a user should call this routine directly, but doing so should do no harm. Given an array of NRWK reals in an array RWRK and an "ordering flag" IORD, TDSORT returns a permutation vector IWRK such that, for every I and J such that 1.LE.I.LE.J.LE.NWRK, if IORD is zero, then RWRK(IWRK(I)).LE.RWRK(IWRK(J)), else RWRK(IWRK(I)).GE.RWRK(IWRK(J)).

**SUBROUTINE TDEZ2D(NX,NY,X,Y,Z,RMULT,THETA,PHI,IST)**

#include <ncarg/ncargC.h> void c_tdez2d (int nx, int ny, float *x, float *y, float *z, float rmult, float theta, float phi, int ist)

This subroutine uses other entries in TDPACK to draw a surface plot. TDEZ2D is meant to be a simplified interface for the purpose of quickly drawing a plot. TDEZ2D sacrifices much of the flexibility and functionality of TDPACK in its attempt to be simple.

**NX**, **NY**, **X**, **Y**, and **Z**
define the input data for the surface. X is dimensioned for NX,
Y is dimensioned for NY, and Z(I,J) is the data value
at (X(I),Y(J)) for I=1,NX and J=1,NY.

**RMULT**, **THETA**, and **PHI** are real input values
specifying an eye position (the point from which the surface
will be viewed), and are defined as follows:

- RMULT is a multiplier of the diagonal length (DL) of the smallest box containing the surface to be drawn.
- THETA is an angle (in degrees) in the XY plane measured positive counter-clockwise from the X axis
- PHI is an angle (in degrees) measured from the positive Z axis toward the XY plane.

Thus, the coordinate (RMULT*DL,THETA,PHI) is the spherical coordinate for the eye position. If RMULT = THETA = PHI = 0., a default eye position ( 2.5,-55.,70.) is chosen.

TDEZ2D calculates the point looked at to be the midpoint of the surface.

**IST** is a style index defining the colors used to shade the
surface. The legal values for IST are as follows:

IST | Description |
---|---|

1 | produce a wire-frame surface |

2 | use gray shades underneath; gray shades on top |

3 | use gray shades underneath; red shades on top |

4 | use gray shades underneath; green shades on top |

5 | use gray shades underneath; blue shades on top |

6 | use gray shades underneath; cyan shades on top |

7 | use gray shades underneath; gray shades on top |

8 | use gray shades underneath; magenta shades on top |

If IST is positive, then black is used for the background color and white for the foreground color; if IST is the negative of any of the above values, then white is used for the background color and black for the foreground color. If IST falls outside of the legal range, it is defaulted to 6.

When TDEZ2D is called, a color table is defined for all open
workstations that implements IST as described above. *This
color table will supersede any color table that has been
previously defined.* The color table that is defined is:

Color index | Colors |
---|---|

0 | black if IST is positive; white if IST is negative |

1 | white if IST is positive; black if IST is negative |

2 | red |

3 | green |

4 | blue |

5 | cyan |

6 | magenta |

7 | yellow |

8-37 | grayscale from white to black |

38-67 | shades of gray |

68-97 | shades of red |

98-127 | shades of green |

128-157 | shades of blue |

158-187 | shades of cyan |

188-217 | shades of magenta |

218-247 | shades of yellow |

TDEZ2D does *not* call FRAME.

If the image is too small, decrease the size of RMULT; if the image is too large, increase the size of RMULT.

Example:

CALL TDEZ2D(NX,NY,X,Y,Z,0.,0.,0.,6)

will draw a surface in shades of cyan with a black background and with a default eye position selected.

**SUBROUTINE TDEZ3D(NX,NY,NZ,X,Y,Z,U,VALUE,RMULT,THETA,PHI,IST)**

#include <ncarg/ncargC.h> void c_tdez3d (int nx, int ny, int nz, float *x, float *y, float *z, float *u, float value, float rmult, float theta, float phi, int ist)

This subroutine uses other entries in TDPACK to draw an isosurface plot. TDEZ3D is meant to be a simplified interface for the purpose of quickly drawing a plot. TDEZ3D sacrifices much of the flexibility and functionality of TDPACK in its attempt to be simple.

**NX**, **NY**, **NZ**, **X**, **Y**, **Z**,
and **U**
define the input data for the isosurface where **VALUE** is the
isovalue. X is dimensioned for NX, Y is dimensioned for NY, Z is
dimensioned for NZ, and U(I,J,K) is the data value
at (X(I),Y(J),Z(K)) for I=1,NX, J=1,NY, and K=1,NZ.

**RMULT**, **THETA**, and **PHI** are real input values
specifying an eye position (the point from which the surface
will be viewed), and are defined as follows:

- RMULT is a multiplier of the diagonal length (DL) of the grid box specified ty X, Y, and Z.
- THETA is an angle (in degrees) in the XY plane measured positive counter-clockwise from the X axis
- PHI is an angle (in degrees) measured from the positive Z axis toward the XY plane.

Thus, the coordinate (RMULT*DL,THETA,PHI) is the spherical coordinate for the eye position. If RMULT = THETA = PHI = 0., a default eye position ( 2.5,-55.,70.) is chosen.

TDEZ3D calculates the point looked at to be the midpoint of the grid box specified by X, Y, and Z.

**IST** is a style index defining the colors used to shade the
surface. The legal values for IST are:

IST | Description |
---|---|

1 | produce a wire-frame surface |

2 | use gray shades underneath; gray shades on top |

3 | use gray shades underneath; red shades on top |

4 | use gray shades underneath; green shades on top |

5 | use gray shades underneath; blue shades on top |

6 | use gray shades underneath; cyan shades on top |

7 | use gray shades underneath; gray shades on top |

8 | use gray shades underneath; magenta shades on top |

If IST is positive, then black is used for the background color and white for the foreground color; if IST is the negative of any of the above values, then white is used for the background color and black for the foreground color. If IST falls outside of the legal range, it is defaulted to 6.

When TDEZ3D is called, a color table is defined for all open
workstations that implements IST as described above. *This
color table will supersede any color table that has been
previously defined.* The color table that is defined is:

Color index | Colors |
---|---|

0 | black if IST is positive; white if IST is negative |

1 | white if IST is positive; black if IST is negative |

2 | red |

3 | green |

4 | blue |

5 | cyan |

6 | magenta |

7 | yellow |

8-37 | grayscale from white to black |

38-67 | shades of gray |

68-97 | shades of red |

98-127 | shades of green |

128-157 | shades of blue |

158-187 | shades of cyan |

188-217 | shades of magenta |

218-247 | shades of yellow |

TDEZ3D does *not* call FRAME.

If the image is too small, decrease the size of RMULT; if the image is too large, increase the size of RMULT.

Example:

CALL TDEZ3D(NX,NY,NZ,X,Y,Z,U,1.,0.,0.,0.,6)

will draw an isosurface (using an isovalue of 1.) in shades of cyan with a black background and with a default eye position selected.