\chapter{3D-Display Implementation}
\label{XGUI3DImplem}
\index{3D Display Implementation}
\thispagestyle{empty}

This chapter gives a short overview of the implementation of the 3D
visualization component.
The modules for 3D-viewing can be divided into four groups:
\index{3D viewing Module}

\begin{itemize}
\item Modules for the data structures
\item Modules for the panels
\item Modules for visualisation
\item Modules for drawing
\end{itemize}

Each program file has a corresponding header file declaring the
exported functions. Exceptions are the files {\tt d3\_global.c} and
{\tt d3\_global.h}, where the global variables are defined. All
modules carry the prefix {\tt d3\_ } for better distinction from the
2D XGUI functions (prefix {\tt ui\_ }) and the kernel functions (prefix
{\tt krui\_ }).

The functions that are visible from outside a module also carry the
prefix {\tt 3d\_ } of the 3D user interface.


\section{Contents of the Modules}

The following files contain data structures and variables of the 3D
user interface:
\index{3D viewing Module!3D User Interface}
\begin{tabbing}
\vspace{0.5cm} \= \hspace{3cm} \= \kill
\>{\tt d3\_global.h}   \> Global data structures and constants \\
\>{\tt d3\_global.c}   \> Global variables                \\
\>{\tt d3\_font5x7.c}  \> Array for the 5 $\times$ 7 character set\\
\>{\tt d3\_font5x8.c}  \> Array for the 5 $\times$ 8 character set\\
\>{\tt d3\_font8x14.c} \> Array for the 8 $\times$ 14 character set
\end{tabbing}

The following files contain panels of the 3D user interface:
\begin{tabbing}
\vspace{0.5cm} \= \hspace{3cm} \= \kill
\> {\tt d3\_pannels.c}  \> Control panel \\
\> {\tt d3\_move.c}   \> Panel for stepwise rotation, scaling and translation\\
\> {\tt d3\_zvalue.c}   \> Panel for input of the z-value \\
\> {\tt d3\_setup.c}    \> Panel for the step sizes and initial values\\
\> {\tt d3\_model.c}    \> Panel for the kind of display \\
\> {\tt d3\_project.c}  \> Panel for the projection    \\
\> {\tt d3\_light.c}    \> Panel for the illumination \\
\> {\tt d3\_units.c}    \> Panel for displaying values in the units \\
\> {\tt d3\_links.c}    \> Panel for displaying values in the links \\
\> {\tt d3\_disp.c}     \> Handling of the display window and the event loop\\
\> {\tt d3\_xUtils.c}   \> X Window assistance routine
\end{tabbing}

The following files contain 3D visualization functions:
\index{3D viewing Module!3D Visualization Function}
\begin{tabbing}
\vspace{0.5cm} \= \hspace{3cm} \= \kill
\>{\tt d3\_main.c}      \> Interface and controls of the visualisation \\
\>{\tt d3\_shade.c}     \> Illumination algorithm             \\
\>{\tt d3\_draw.c}      \> High level drawing routines for units and links \\
\>{\tt d3\_anageo.c}    \> Matrix transformations and basic operations \\
\>{\tt d3\_lists.c}     \> Administration of lists
\end{tabbing}

The following files contain low level drawing routines:
\index{3D viewing Module!3D Drawing Routine}
\begin{tabbing}
\vspace{0.5cm} \= \hspace{3cm} \= \kill
\>{\tt d3\_graph.c}     \> Low level drawing routines and color control \\
\>{\tt d3\_zgraph.c}    \> z-buffer functions \\
\>{\tt d3\_point.c}     \> Pixel oriented output \\
\>{\tt d3\_fonts.c}     \> Control of text output \\
\>{\tt d3\_dither.c}    \> dithering of the color values
\end{tabbing}


\section{Global Data Types and Variables}
\label{GlobalDataTypes}
\index{3D Global Data Type}

All global data types and constants are declared in the module {\tt
d3\_global.h}. The basic data types are

\begin{tabbing}
\hspace{6cm} \= \kill
{\tt typedef float vector[4]} 
                        \> the definition of a vector \\
{\tt typedef float matrix[4][4]} 
                        \> the definition of a matrix \\
{\tt typedef vector cube[9]} 
                        \> the corner points of a cube (unit), \\
                        \> as well as the center
\end{tabbing}
\vspace{1cm}

The following data type is used for the z-buffer algorithm of the unit
surfaces:

\begin{verbatim}
typedef struct {
    int n;
    int mask;
    vector vert[4];
} d3_polygon_type;
\end{verbatim}

\begin{tabular}{ll}
{\tt vert} & contains the vectors of the polygon edges \\
{\tt mask} & contains the interpolation mask for the x-, y-
                and z-coordinates \\
{\tt n}    & used as a counter of polygon edges \\
\end{tabular}
\vspace{1cm}

The following data type is used for the values that can be represented
by a unit:

\begin{verbatim}
typedef struct {
     int size;
     int color;
     int top_label;
     int bottom_label;
} d3_unit_mode_type;
\end{verbatim}

\begin{tabular}{ll}
{\tt size}   & a value is displayed by the size of the unit \\
{\tt color}  & a value is displayed by the color of the unit \\
{\tt top\_label}  & a value is written to the upper right
                corner of the unit \\
{\tt bottom\_label}  & a value is written to the lower right
                corner of the unit \\
\end{tabular}

The fields may each contain one of the constants:~~{\tt
acti\-vation\_\-on}, {\tt init\_\-act\_\-on}, {\tt out\-put\_\-on},
{\tt bias\_\-on}, {\tt name\_\-on}, {\tt number\_\-on}, {\tt
zvalue\_\-on} or {\tt nothing\_\-on}. 
\vspace{1cm}

The light source is described by the following declaration:

\begin{verbatim}
typedef struct {
    int    shade_mode;
    vector position;
    float  Ia, Ka, Ip, Kd;
} d3_light_type;
\end{verbatim}

\begin{tabular}{ll}
{\tt shade\_mode}       & specifies, whether the units are to be illuminated \\
{\tt position}          & is the position of the light source \\
{\tt Ia, Ka, Ip, Kd} &  are the illumination constants \\
\end{tabular}
\vspace{1cm}

The whole status of the network display is contained in:

\begin{verbatim}
typedef struct {
    vector trans_vec, rot_vec, scale_vec;
    vector trans_step, rot_step, scale_step;
    vector viewpoint;
    float unit_aspect;
    float link_scale;
    float pos_link_trigger;  
    float neg_link_trigger;  
    int font;
    int projection_mode;
    int color_mode;
    int link_mode;
    d3_unit_mode_type unit_mode;
    d3_light_type light;
} d3_state_type;
\end{verbatim}

\begin{tabular}{lp{10cm}}
{\tt trans\_vec} & current translation \\
{\tt rot\_vec} & current rotation \\
{\tt scale\_vec} &  current scaling  \\
{\tt trans\_step} & step size for the
           translation in the transformation panel \\
{\tt rot\_step} & step size for the
           rotation in the transformation panel \\
{\tt scale\_step} & step size for the
         scaling in the transformation panel \\
{\tt viewpoint} & viewpoint for the central projection\\
{\tt unit\_aspect} & ratio between the edge length of
         the units and the distance between them \\
{\tt link\_scale} & specifies a factor for a region in which the links
         are to be drawn\\
{\tt font} & specifies the character set for labeling the units and
         links\\
{\tt projection\_mode} & contains the constant {\tt parallel}
        or {\tt central} \\
{\tt model\_mode} & specifies the display mode for the network. The field
         contains the constant {\tt wire\_frame} or {\tt solid}\\
{\tt color\_mode} & specifies whether a monochrome or color terminal
         is used\\
{\tt link\_mode} & contains the display mode of the links. Values may be
       {\tt links\_on, links\_off, links\_color}
       or {\tt links\_label} \\
{\tt unit\_mode} & see {\tt d3\_unit\_mode\_type} \\
{\tt light} & see {\tt d3\_light\_type} \\
\end{tabular}

\index{3D Global Variable}
The global variables are located in the module {\tt d3\_global.c}.
Most of them are initialized with default values.

The variables

\begin{verbatim}
Display *d3_display;
Window  d3_window;
GC      d3_gc;
int     d3_screen;
\end{verbatim}

address the display window of Xlib (the data types {\tt Display,
Window} and {\tt GC} are declared in Xlib).

\begin{verbatim}
int d3_displayXsize;
int d3_displayYsize;
\end{verbatim}

contain the current size of the display window.

\begin{verbatim}
bool d3_displayIsReady;
bool d3_controlIsReady;
\end{verbatim}

specify, whether the display window and the control panel are created.

\begin{verbatim}
bool d3_freeze;
\end{verbatim}

specifies, whether updates are possible in the display window.

\begin{verbatim}
int d3_fontXsize;
int d3_fontYsize;
\end{verbatim}

specify the size of the current character set used to label the units
and links.

\begin{verbatim}
int d3_numberWidth;
int d3_shortNumberWidth;
\end{verbatim}

specify the width of float and short int in the X Window
dialogue widgets.

\begin{verbatim}
struct TransTable *d3_xyTransTable;
\end{verbatim}

is a pointer to the 2D $\rightarrow$ 3D translation table. The table
itself is declared in the kernel.

\begin{verbatim}
int d3_transOffset;
\end{verbatim}

specifies the offset for zero in the table. This is necessary, since C
does not allow negative indices.

\begin{verbatim}
d3_state_type d3_state;
\end{verbatim}

contains the status of the network display (see {\tt d3\_state\_type})

\begin{verbatim}
cube d3_e_cube;
\end{verbatim}

contains the corner points of the standard cube. The cube is moved by
the vector (-0.5, -0.5, -0.5) to be centered in the coordinate system.

\begin{verbatim}
int d3_cube_lines[12][2];
\end{verbatim}

contains the twelve edges of a cube. The numbers are used
as indices to {\tt d3\_e\_cube}.

\begin{verbatim}
int d3_vertex_index[6][4];
\end{verbatim}

contains the six planes of a cube. The numbers are also used 
as indices to {\tt d3\_e\_cube}


\section{Drawing the Network in 3D}
\index{3D Network!Drawing Function}
\index{Drawing Function}

This section describes the functions that are called to draw the
network. Most of the routines are located in the module {\tt main.c}.
In other cases, the name of the module is given in parentheses without
the prefix  d3\_$\;$. The functions are explained  "top-down".
Figure \ref{calls} shows the hierarchy of the calls.

\begin{figure}[p]
\begin{center}
  \begin{minipage}{\textwidth}
    \screendump{0.8}{xgui_3D_figs/3D_functions.ps}
  \end{minipage}
  \caption{\label{calls}Function calls of drawNet}
\end{center}
\end{figure}



\index{3D Network!Drawing Function!d3\_drawNet}
{\bf d3\_drawNet}:The routine is called by the function {\tt
ui\_net\_updateWhole} in the module {\tt ui\_netUpdate.c} as well as
by all routines which make a redraw of the network necessary.(e.g.\
upon changing from wire to solid model). When the display is frozen or
not opened, the routine is left immediately. In the case of solid
representation, the z-buffer is cleared. Then the units are drawn by
{\tt draw\_units}. If links are to be displayed, {\tt draw\_links}
calls the appropriate functions.

\index{3D Network!Drawing Function!draw\_units}
{\bf draw\_units}: This function draws all units in a network. First,
the maximal dimensions of the net are calculated by {\tt
get\_net\_extrema}, then the center of rotation is computed from
there. Afterwards the matrices for the global translation, scaling,
and rotation are determined. The corners for labeling are determined
next by {\tt get\_label\_vert\_indices}. Now the net is traversed unit
by unit.  For each unit its location in space (in {\tt
get\_unit\_pos\_\-vector}) and the corresponding matrix is computed.
If a value is to be displayed by the size of the unit, the value is
first changed to a vector in {\tt get\_size\_vector} and then to a
matrix. The matrices are multiplied with each other by {\tt
calc\_transformed\_cube}. With this new matrix, the vectors of the
standard cube are transformed to picture space. The center of the
transformed unit is stored by {\tt insert\_center\_vector}, to speed
up the subsequent drawing of links.  Depending upon the representation
mode the unit is drawn with {\tt d3\_drawWireframeCube} or {\tt
d3\_drawSolidCube} in the module {\tt draw.c}. If the units are to be
labeled, {\tt d3\_labelUnit} puts the value at the appropriate place.

\index{3D Network!Drawing Function!get\_net\_extrema}
{\bf get\_net\_extrema}: This routine determines the extension of the
network in x-, y-, and z-direction. For each unit position it is
checked whether one of its components is a maximum. The results are
two vectors enclosing the net.

\index{3D Network!Drawing Function!get\_label\_vert\_indices}
{\bf get\_label\_vert\_indices}: The indices to the unit vectors for
labeling are computed in this function. This can be done at a single
unit, since all units are rotated by the same angle and the alignment
doesn't change. The routine calls the actual computing function {\tt
get\_vert\_index} once for the upper and once for the lower label.

\index{3D Network!Drawing Function!get\_unit\_pos\_vector}
{\bf get\_unit\_pos\_vector}: This function contains the 2D
$\rightarrow$ 3D transformation. Input parameter is the unit number,
output value the 3D--vector.  All functions which require
3D--coordinates have to call this routine.

The position of the unit is read by {\tt krui\_getUnitPosition}. This
value contains the x and y coordinate in the 2D--display as well as
the z-value assigned to the unit. The displacement of the unit against
the 2d--display in x and y direction is computed by the 2D
$\rightarrow$ 3D translation table {\tt d3\_xyTransTable}. The
z-coordinate is used to index the table.

\index{3D Network!Drawing Function!get\_size\_vector}
{\bf get\_size\_vector}: In this routine the activation, the initial
activation, the output, or the threshold is translated into a vector
for the unit size. All components of the vector contain the same
value. Values bigger than 1 are clipped. This guarantees that the unit
can not grow arbitrarily and cover other units. For negative values
and values around zero, a flag is returned that keeps the unit from
being drawn. This is necessary, since the unit would otherwise be
drawn as a point.

\index{3D Network!Drawing Function!calc\_transformed\_cube}
{\bf calc\_transformed\_cube}: This subprogram has to calculate the
transformed unit coordinates.  Therefore the following matrices have
to be multiplied: matrix for 3D--position, for centering the unit in
space, for the base values of the unit, for the size of the unit
representing a value, for the scaling of the net, for a displacement
of the net, and the matrix for rotation of the net. The resulting
matrix transforms the vectors of the standard cube by {\tt
unit\_transformation}. Finally a central projection is performed by
{\tt d3\_projection} if that option was selected.

\index{3D Network!Drawing Function!unit\_transformation}
{\bf unit\_transformation}: In this routine, the vectors of the
standard cube are multiplied by the transformation matrix.

\index{3D Network!Drawing Function!insert\_center\_vector}
{\bf insert\_center\_vector}: The transformed center of the unit is
written to the unit structure of the kernel by {\tt
krui\_setUnitCenters}.

\index{3D Network!Drawing Function!d3\_drawWireframeCube}
{\bf d3\_drawWireframeCube}: This function draws a ``transparent''
unit. The eight transformed vectors of the unit corners are connected
with each other according to the entries in the {\tt d3\_cube\_lines}
array. The drawing is performed by the low level routine {\tt
d3\_drawLine} ({\tt graph.c})

\index{3D Network!Drawing Function!d3\_drawSolidCube} 
{\bf d3\_drawSolidCube}: This subprogram draws a ``massive`` unit. The
corner points of the planes are defined by the array {\tt
d3\_vertex\_index} in {\tt global.c}. If no value is to be displayed
by the color of the unit, the brightness is computed for all six
planes of the cube. For this purpose, {\tt d3\_normalVector} ({\tt
anageo.c}) computes a vector perpendicular to the plane. {\tt
d3\_shadeIntens} in module {\tt shade.c} takes the position of the
light source, the normal vector of the plane, and a vector on the
plane and computes the intensity value for the plane. This is
converted to a palette index by {\tt d3\_intens\_to\_grayval} and
activated by {\tt d3\_setColor} ({\tt draw.c}). If a value is to be
displayed by the color, {\tt d3\_getColorValue} determines the
appropriate color value and {\tt d3\_value\_to\_color} the palette
index. Then {\tt d3\_drawPoly} ({\tt graph.c}) draws the plane.

\index{3D Network!Drawing Function!d3\_shadeIntens}
{\bf d3\_shadeIntens}: Here the intensity of the light source is
computed. The value varies between -1 and 1.

\index{3D Network!Drawing Function!d3\_getColorValue} 
{\bf d3\_getColorValue}: This function returns a value in the range
$[-1,1]$. The value may represent the activation, initial activation,
output, or threshold of the unit.

\index{3D Network!Drawing Function!d3\_labelUnit}
{\bf d3\_labelUnit}: To label a unit, the appropriate value is
converted to a string. Then, the position for the string is computed.
The function {\tt get\_label\_vert\_indices} did already compute the
index of the corner.  If the label is to be put at the upper corner,
the y-coordinate has to be adjusted by the font height. The string is
drawn by a call to {\tt d3\_draw\_string} in module {\tt fonts.c}.

\index{3D Network!Drawing Function!draw\_links}
{\bf draw\_links}: This function draws the links in a network. For
each unit the numbers of all units connected with the current one are
obtained by {\tt krui\_getFirstPredUnit} and {\tt
krui\_getNextPredUnit}. Additionally the weight of the connection is
stored. The coordinates of the units to be connected are determined by
{\tt krui\_getUnitCenters}. A link is either black, or gets a color
assigned by {\tt d3\_setLinkColor} which corresponds to its weight.
The drawing is performed by the functions {\tt d3\_drawWireframeLine}
or {\tt d3\_drawSolidLine} in module {\tt draw.c}. An optional
labeling with the weight is performed by a call to {\tt
d3\_labelLink}.

\index{3D Network!Drawing Function!d3\_setLinkColor} 
{\bf d3\_setLinkColor}: The color of a link is determined by its
weight. For this purpose the weight is converted to the interval
$[-1,1]$ with the scale factor {\tt d3\_state.link\_scale}. Bigger
weights get the value 1, smaller ones -1.  The implementation is
analogous to the 2D--display.

\index{3D Network!Drawing Function!d3\_drawWireframeLine}
{\bf d3\_drawWireframeLine}: To draw a link in the wire frame model,
the vector is rounded and drawn by the function {\tt d3\_drawLine}
({\tt graph.c}).

\index{3D Network!Drawing Function!d3\_drawSolidLine}
{\bf d3\_drawSolidLine}: The points of a link in solid model display
are computed from the line equation and drawn with {\tt d3\_putPixel}.

\index{3D Network!Drawing Function!d3\_labelLink}
{\bf d3\_labelLink}: This routine writes the weight of a link at the
center of the link.  The center between head and tail is given by the
line equation with $\mu$ = 0.5.  The value is put at this position
with {\tt d3\_draw\_string}.



\section{Low Level Drawing Routines}
\label{XlibCalls}
\index{3D Drawing Routine}
\index{Drawing Function}

The low level drawing routines are located in the modules {\tt d3\_graph.c,
d3\_fonts.c d3\_point.c,} and {\tt d3\_dither.c}.

The following functions only call the corresponding Xlib routines.
The justification for these additional routines is, that they simplify
porting to other graphic systems, since they are the lowest level
of drawing calls.


\begin{center}
\begin{tabular}{|l|l|l|} \hline
function  & Xlib Call  & Task\\ \hline \hline
{\tt d3\_setColor} & {\tt XsetForegroand} & sets the foreground color\\
{\tt d3\_clearDisplay} & {\tt XClearWindow} & deletes the display
        window \\
{\tt d3\_drawLine} & {\tt XDrawLine}  & draws a line\\
{\tt d3\_putPixel} & {\tt XDrawPoint} & draws a pixel\\ \hline
\end{tabular}
\end{center}
\vspace{0.5cm}

\index{3D z-buffer Routine}
The z-buffer is controlled by the routines in module
{\tt d3\_zGraph.c}. The z-buffer is organized as a one dimensional
array of float. Thereby, clearing the buffer is very fast. The
necessary memory is dynamically allocated (and freed) by the operating
system. The position \mbox{$(x,y)$} is computed explicitly from the
size of the buffer.

\begin{tabular}{lll}
\hspace{0.5cm} & {\tt d3\_initZbuffer} & allocate the z-buffer on the heap\\
& {\tt d3\_clearZbuffer} & reset the z-buffer to the maximum distance\\
& {\tt d3\_readZbuffer} & get distance $z$ at position $(x,y)$\\
& {\tt d3\_writeZbuffer} & set distance $z$ at position $(x,y)$\\
& {\tt d3\_freeZbuffer} & free the z-buffer on the heap\\
\end{tabular}

A polygon is drawn by the function {\tt d3\_drawPoly}. The
corresponding Xlib call cannot be used, since the visibility of each
polygon point has to be checked. The implementation is derived from
the article "Generic Convex Polygon Scan Conversion and Clipping" by
Paul Heckbert.

Several routines for labeling the links and units had to be created.
This was necessary because the characters must be addressed point by
point because of the z-buffering. The routines are listed in the
module {\tt d3\_fonts.c}.
\index{3D Font Routine}

\begin{tabular}{lll}
\hspace{0.5cm} & {\tt d3\_select\_font} & selects a font\\
& {\tt d3\_get\_font\_sizes} & returns the width and height of the
        current font\\
& {\tt d3\_draw\_string} & writes the string to the 
                   position $(x,y,z)$\\
\end{tabular}

The local functions {\tt draw\_char} and {\tt draw\_zbuffered\_char} are
used by {\tt d3\_draw\_string} to generate a pixel sequence from the
ASCII code of a character and the font array. 

The creation of grey values is performed with the function {\tt dither} in
module {\tt d3\_dither.c}.


\section{Matrix Calculations}
\index{3D Matrix Calculation}

The module {\tt d3\_anageo.c} contains the routines for vector and
matrix calculations.


\begin{tabular}{lll}
\hspace{0.5cm} & {\tt e\_matrix} & creates an identity matrix\\
& {\tt d3\_transMatrix}   & creates the translation matrix\\
& {\tt d3\_scaleMatrix}   & creates the scaling matrix\\
& {\tt d3\_rotateXmatrix} & creates matrix for rotation around the x-axis\\
& {\tt d3\_rotateYmatrix} & creates matrix for rotation around the y-axis\\
& {\tt d3\_rotateZmatrix} & creates matrix for rotation around the z-axis\\
& {\tt d3\_rotateMatrix}  & creates matrix for rotation around all axes \\
& {\tt d3\_multMatrix}    & multiplies two matrices                     \\
& {\tt d3\_multMatrixVector} & multiplies a vector and a matrix \\
& {\tt d3\_normalVector}  & calculates the normal vector for a plane\\
& {\tt d3\_projection}    & performs a central projection\\
\end{tabular}


\section{The 3D Display Window}
\index{3D Display Window!Implementation}

The 3D display window is opened by the callback function {\tt
d3\_create\-Display\-Window}, linked to the \fbox{\tt DISPLAY} button
in the control panel.

The display window has its own event handler. It reacts to
ConfigureNotify and Expose events. When an Expose event occurs, the
net is redrawn. Since a series of Expose events is created in some
cases, all but the last one are ignored. If the size of the display
window is changed, a ConfigureNotify event causes the net to be
centered in the new window and redrawn. All Expose events are blocked
in this case.

The display window is created by {\tt XtCreatePopupShell}. It contains
an inner frame (see \ref{Panels}). After the window becomes visible
the Xlib variables  {\tt d3\_display, d3\_window} and
{\tt d3\_screen} are created as well as the graphic context {\tt
d3\_gc}. Each subsequent reference to the display window is performed by
Xlib functions (see \ref{XlibCalls}).


\section{Panels}
\label{Panels}
\index{3D Panel Implementation}

The panels were implemented with the Intrinsics -- and Athena Toolkit for
X11 Release 4. The structure of the panels is similar to those of the
2D--interface, to make the display as homogeneous as possible.
Therefore, the routines in module {\tt ui\_xWigets.c} have been used.

The module {\tt d3\_xUtils.c} contains the two functions {\tt
d3\_xCreate\-Button\-Item} and {\tt d3\_x\-Create\-Toggle\-Item}. They create
the buttons and import the ''xbm'' bitmaps for labeling the buttons.

Most of the panels are programmed in a similar fashion. Therefore,
the implementation of the panel for the projection is described as an
example. The panel looks like this:

\begin{figure}[htb]
\begin{center}
  \begin{minipage}{\textwidth}
    \screendump{0.75}{xgui_3D_figs/3D_ProjectPanel.ps}
  \end{minipage}
  \caption{Project panel}
\end{center}
\end{figure}

In module {\tt d3\_panels.c} five functions handle the project panel.

\index{3D Project Panel Implementation!d3\_createProjectpanel}
{\bf d3\_createProjectpanel}: This routine is a callback function of
the button \fbox{PROJECT} in the control panel. As a parameter, the
button itself is passed. From there, {\tt Xt\-Trans\-late\-Coords}
computes the position at which the project panel is to be opened with
{\tt Xt\-Create\-Popup\-Shell}.  Since the panel is supposed to have
an inner frame, a window of {\tt box\-Widget\-Class} is created with
{\tt Xt\-Create\-Managed\-Widget}.  There the actual window of class
{\tt formWidgetClass} is located. Now the two radio buttons
\fbox{PARALLEL} and \fbox{CENTRAL} are created with {\tt
d3\_xCreate\-Toggle\-Item}. Then the labeling \mbox{\bf Viewpoint X}
with {\tt ui\_xCreate\-Label\-Item} and the dialogue window follow.
The next two lines are created similarly. Then the \fbox{DONE} button
is created with {\tt d3\_xCreateButtonItem}. In the next step the
three callbacks for the three buttons are created by {\tt
Xt\-Add\-Call\-back}.  {\tt set\-Parallel\-Projec\-tion} and {\tt
set\-Central\-Projec\-tion} are linked to the two radio buttons, {\tt
d3\_closeProjectpanel} to the \fbox{DONE} button. Now a temporary
variable {\tt temp\_state} of type {\tt d3\_state\_type} for the
status of the display is generated. All changes to the status are
stored there as long as the panel exists.  Now one of the two radio
buttons gets inverted by {\tt setProjectToggleState}, corresponding
with the current status. At last, the panel is made visible by {\tt
XtPopup} with {\tt XtGrabExclusive}.

\index{3D Project Panel Implementation!setParallelProjection}
{\bf setParallelProjection}: If the \fbox{PARALLEL} button is clicked,
this function sets the field {\tt temp\_state.projection\_mode} to
{\tt parallel}. A call to {\tt setProjectToggleState} updates the
panel.

\index{3D Project Panel Implementation!setCentralProjection}
{\bf setCentralProjection}: like {\tt setParallelProjection}

\index{3D Project Panel Implementation!setProjectToggleState}
{\bf setProjectToggleState}: With this function, the status of the two
radio buttons is updated.  The variable {\tt
temp\_state.projection\_mode} is read, one of the buttons is set, the
other reset.

\index{3D Project Panel Implementation!d3\_closeProjectpanel}
{\bf d3\_closeProjectpanel}: When the panel is closed, the values of
the dialogue windows have to be written to the variable {\tt
temp\_state.viewpoint}. Now {\tt temp\_state} is compared with the
initial status variable {\tt d3\_state}. If they differ, a parameter
has changed and the net has to be redrawn. This is done by copying
{\tt temp\_state} to {\tt d3\_state} and calling {\tt d3\_drawNet}
afterwards. The indirection with the temporary variable is necessary,
since the panel may have been opened by mistake or for control
reasons. In this case the net doesn't have to be redrawn.




