%% BEGIN pst-3d.tex
%%
%% Tilting and other pseudo-3D tricks for PSTricks v0.93a.
%% This is experimental. See 3d-test.tex for a test file.
%% There is not yet any documentation.
%%
\def\fileversion{0.93a}
\def\filedate{93/08/26}
%%
%% COPYRIGHT 1993, by Timothy Van Zandt, tvz@Princeton.EDU
%% See pstricks.tex or pstricks.doc for copying restrictions.
%%

\message{ v\fileversion, \filedate}

\csname PSTthreeDLoaded\endcsname
\let\PSTthreeDLoaded\endinput

\ifx\PSTricksLoaded\endinput\else
  \def\next{\input pstricks.tex}
  \expandafter\next
\fi

\edef\TheAtCode{\the\catcode`\@}
\catcode`\@=11

% \begin{macro}{\tx@SetMatrixThreeD,\tx@ProjThreeD,\tx@SetMatrixEmbed}
% Viewpoint for 3D coordinates is given by three angles: $\alpha$, $\beta$ and
% $\gamma$. $\alpha$ and $\beta$ determine the direction from which one is
% looking. $\gamma$ then determines the orientation of the observing.
%
% When $\alpha$, $\beta$ and $\gamma$ are all zero, the observer is looking
% from the negative part of the $y$-axis, and sees the $xz$-plane the way in
% 2D one sees the $xy$ plan. Hence, to convert the 3D coordinates to their 2D
% project, $\la x, y, z\ra$ map to $\la x, z\ra$.
%
% When the orientation is different, we rotate the coordinates, and then
% perform the same projection.
%
% We move up to latitude $\beta$, over to longitude $\alpha$, and then rotate
% by $\gamma$. This means that we first rotate around $y$-axis by $\gamma$,
% then around $x$-axis by $\beta$, and the around $z$-axis by $\alpha$.
%
% Here are the matrices:
% \begin{eqnarray*}
%   R_z(\alpha) & = & \left[
%     \begin{array}{ccc}
%       \cos \alpha & -\sin \alpha & 0 \\
%       \sin \alpha & cos \alpha   & 0 \\
%       0           & 0            & 1
%     \end{array} \right] \\
%   R_x(\beta) & = & \left[
%     \begin{array}{ccc}
%       1           & 0            & 0 \\
%       0           & \cos \beta   & \sin \beta \\
%       0           & -\sin \beta  & \cos \beta
%     \end{array} \right] \\
%   R_y(\gamma) & = & \left[
%     \begin{array}{ccc}
%       \cos \gamma & 0            & -\sin \gamma \\
%       0           & 1            & 0 \\
%       \sin \gamma & 0            & \cos \gamma
%     \end{array} \right]
% \end{eqnarray*}
%
% The rotation of a coordinate is then performed by the matrix $R_z(\alpha)
% R_x(\beta) R_y(\gamma)$. The first and third columns of the matrix are the
% basis vectors of the plan upon which the 3D coordinates are project (the old
% basis vectors were $\la 1, 0, 0\ra$ and $\la 0, 0, 1$\ra; rotating these
% gives the first and third columns of the matrix).
%
% These new basis vectors are:
% \begin{eqnarray*}
%   \tilde{x} & = & \left[
%     \begin{array}{c}
%       \cos\alpha \cos\gamma - \sin\beta \sin\alpha \sin\gamma \\
%       \sin\alpha \cos\gamma + \sin\beta \cos\alpha \sin\gamma \\
%       \cos\beta \sin\gamma
%     \end{array} \right] \\
%   \tilde{z} & = & \left[
%     \begin{array}{c}
%       -\cos\alpha \sin\gamma - \sin\beta \sin\alpha \cos\gamma \\
%       -\sin\alpha \sin\gamma + \sin\beta \cos\alpha \cos\gamma \\
%       \cos\beta \cos\gamma
%     \end{array} \right]
% \end{eqnarray*}
%
% Rather than specifying the angles $\alpha$ and $\beta$, the user gives a
% vector indicating where the viewpoint is. This new viewpoint is the rotation
% o the old viewpoint. The old viewpoint is $\la 0, -1, 0\ra$, and so the new
% viewpoint is
% \[
%  R_z(\alpha) R_x(\beta) \left[ \begin{array}{c} 0\\-1\\0 \end{array} \right]
%  \, = \,
%  \left[ \begin{array}{c}
%    \cos\beta \sin\alpha \\
%    -\cos\beta \cos\alpha \\
%    \sin\beta
%  \end{array} \right]
%  \, = \,
%  \left[ \begin{array}{c} v_1 \\ v_2 \\ v_3 \end{array} \right]
% \]
% Therefore,
% \begin{eqnarray*}
%   \alpha & = & \arc\tan (v_1 / -v_2) \\
%   \beta & = & \arc\tan (v_3 \sin\alpha / v_1)
% \end{eqnarray*}
% Unless $p_1=p_2=0$, in which case $\alpha=0$ and $\beta=\sign(p_3)90$, or
% $p_1=p_3=0$, in which case $\beta=0$.
%
% The syntax of "SetMatrixThreeD" is
% \begin{Ex}
%   $v_1$ $v_2$ $v_3$ $\gamma$ "SetMatrixThreeD"
% \end{Ex}
% "SetMatrixThreeD" first computes
% \[
%   \begin{array}{ll}
%     a=\sin\alpha & b=\cos\alpha\\
%     c=\sin\beta  & d=\cos\beta\\
%     e=\sin\gamma & f=\cos\gamma
%   \end{array}
% \]
% and then sets "Matrix3D" to "["$\tilde{x}$ $\tilde{z}$"]".
%
%    \begin{macrocode}
\pst@def{SetMatrixThreeD}<%
  dup sin /e ED cos /f ED
  /p3 ED /p2 ED /p1 ED
  p1 0 eq
  { /a 0 def /b p2 0 le { 1 } { -1 } ifelse def
    p3 p2 abs
  }
  { p2 0 eq
    { /a p1 0 lt { -1 } { 1 } ifelse def /b 0 def
      p3 p1 abs
    }
    { p1 dup mul p2 dup mul add sqrt dup
      p1 exch div /a ED
      p2 exch div neg /b ED
      p3 p1 a div
    }
    ifelse
  }
  ifelse
  atan dup sin /c ED cos /d ED
  /Matrix3D
  [
    b f mul c a mul e mul sub
    a f mul c b mul e mul add
    d e mul
    b e mul neg c a mul f mul sub
    a e mul neg c b mul f mul add
    d f mul
  ] def>
%    \end{macrocode}
%
% The syntax of "ProjThreeD" is
% \begin{Ex}
%   $x$ $y$ $z$ ProjThreeD $x'$ $y'$
% \end{Ex}
% where $x'=\la x, y, z\ra \cdot \tilde{x}$ and $y'=\la x, y, z\ra \cdot
% \tilde{z}$.
%
%    \begin{macrocode}
\pst@def{ProjThreeD}<%
  /z ED /y ED /x ED
  Matrix3D aload pop
  z mul exch y mul add exch x mul add
  4 1 roll
  z mul exch y mul add exch x mul add
  exch>
%    \end{macrocode}
%
% To embed 2D $\la x, y\ra$ coordinates in 3D, the user specifies the normal
% vector and an angle. If we decompose this normal vector into an angle, as
% when converting 3D coordinates to 2D coordinates, and let $\hat\alpha$,
% $\hat\beta$ and $\hat\gamma$ be the three angles, then when these angles are
% all zero the coordinate $\la x, y\ra$ gets mapped to $\la x, 0, y\ra$, and
% otherwise $\la x, y\ra$ gets mapped to
% \[
%   R_z(\hat\alpha) R_x(\hat\beta) R_y(\hat\gamma)
%   \left[ \begin{array}{c} x \\ 0 \\ y \end{array} \right]
%  \, = \,
%   \left[ \begin{array}{c}
%    \hat{x}_1 x + \hat{z}_1 y\\
%    \hat{x}_2 x + \hat{z}_2 y\\
%    \hat{x}_3 x + \hat{z}_3 y
%   \end{array} \right]
% \]
% where $\hat{x}$ and $\hat{z}$ are the first and third columns of
% $R_z(\hat\alpha) R_x(\hat\beta) R_y(\hat\gamma)$.
%
% Now add on a 3D-origin:
% \[
%   \left[ \begin{array}{c}
%    \hat{x}_1 x + \hat{z}_1 y + x_0\\
%    \hat{x}_2 x + \hat{z}_2 y + y_0\\
%    \hat{x}_3 x + \hat{z}_3 y + z_0
%   \end{array} \right]
% \]
%
% Now when we project back onto 2D coordinates, we get
% \begin{eqnarray*}
%   x' & = & \tilde{x}_1(\hat{x}_1 x + \hat{z}_1 y + x_0) +
%            \tilde{x}_2(\hat{x}_2 x + \hat{z}_2 y + y_0) +
%            \tilde{x}_3(\hat{x}_3 x + \hat{z}_3 y + z_0)\\
%   & = &
%   (\tilde{x}_1\hat{x}_1 + \tilde{x}_2\hat{x}_2 + \tilde{x}_3\hat{x}_3) x\\
%   + (\tilde{x}_1\hat{z}_1 + \tilde{x}_2\hat{z}_2 + \tilde{x}_3\hat{z}_3) y\\
%   + \tilde{x}_1 x_0 + \tilde{x}_2 y_0 + \tilde{z}_3 z_0
%   y' & = & \tilde{z}_1(\hat{x}_1 x + \hat{z}_1 y + x_0) +
%            \tilde{z}_2(\hat{x}_2 x + \hat{z}_2 y + y_0) +
%            \tilde{z}_3(\hat{x}_3 x + \hat{z}_3 y + z_0)\\
%   & = &
%   (\tilde{z}_1\hat{x}_1 + \tilde{z}_2\hat{x}_2 + \tilde{z}_3\hat{x}_3) x\\
%   + (\tilde{z}_1\hat{z}_1 + \tilde{z}_2\hat{z}_2 + \tilde{z}_3\hat{z}_3) y\\
%   + \tilde{z}_1 x_0 + \tilde{z}_2 y_0 + \tilde{z}_3 z_0
% \end{eqnarray*}
% Hence, the transformation matrix is:
% \[
%   \left[ \begin{array}{c}
%   \tilde{x}_1\hat{x}_1 + \tilde{x}_2\hat{x}_2 + \tilde{x}_3\hat{x}_3) \\
%   \tilde{z}_1\hat{x}_1 + \tilde{z}_2\hat{x}_2 + \tilde{z}_3\hat{x}_3) \\
%   \tilde{x}_1\hat{z}_1 + \tilde{x}_2\hat{z}_2 + \tilde{x}_3\hat{z}_3) \\
%   \tilde{z}_1\hat{z}_1 + \tilde{z}_2\hat{z}_2 + \tilde{z}_3\hat{z}_3) \\
%   \tilde{x}_1 x_0 + \tilde{x}_2 y_0 + \tilde{z}_3 z_0 \\
%   \tilde{z}_1 x_0 + \tilde{z}_2 y_0 + \tilde{z}_3 z_0
%   \end{array} \right]
% \]
%
% The syntax of "SetMatrixEmbed" is
% \begin{Ex}
%   $x_0$ $y_0$ $z_0$ $\hat{v_1}$ $\hat{v_2}$ $\hat{v_3} $\hat{\gamma}$
%   $v_1$ $v_2$ $v_3$ $\gamma$ "SetMatrixEmbed"
% \end{Ex}
% "SetMatrixEmbed" first sets "<x1 x2 x3 y1 y2 y3>" to the basis vectors for
% the viewpoint projection (the tilde stuff above). Then it sets "Matrix3D" to
% the basis vectors for the embedded plane. Finally, it sets the
% transformation matrix to the matrix given above.
%
%    \begin{macrocode}
\pst@def{SetMatrixEmbed}<%
  \tx@SetMatrixThreeD
  Matrix3D aload pop
  /z3 ED /z2 ED /z1 ED /x3 ED /x2 ED /x1 ED
  \tx@SetMatrixThreeD
  [
  Matrix3D aload pop
  z3 mul exch z2 mul add exch z1 mul add 4 1 roll
  z3 mul exch z2 mul add exch z1 mul add
  Matrix3D aload pop
  x3 mul exch x2 mul add exch x1 mul add 4 1 roll
  x3 mul exch x2 mul add exch x1 mul add
  3 -1 roll 3 -1 roll 4 -1 roll 8 -3 roll 3 copy
  x3 mul exch x2 mul add exch x1 mul add 4 1 roll
  z3 mul exch z2 mul add exch z1 mul add
  ]
  concat>
%   \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@viewpoint,\psk@viewpoint}
%    \begin{macrocode}
\let\pssetzlength\pssetylength
\def\psset@viewpoint#1{%
  \pst@expandafter\psset@@viewpoint#1 {} {} {} \@nil
  \let\psk@viewpoint\pst@tempg}
\def\psset@@viewpoint#1 #2 #3 #4\@nil{%
  \begingroup
    \pssetxlength\pst@dima{#1}%
    \pssetylength\pst@dimb{#2}%
    \pssetzlength\pst@dimc{#3}%
    \xdef\pst@tempg{%
      \pst@number\pst@dima \pst@number\pst@dimb \pst@number\pst@dimc}%
  \endgroup}
\psset@viewpoint{1 -1 1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@viewangle,\psk@viewangle}
%    \begin{macrocode}
\def\psset@viewangle#1{\pst@getangle{#1}\psk@viewangle}
\psset@viewangle{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@normal,\psk@normal}
%    \begin{macrocode}
\def\psset@normal#1{%
  \pst@expandafter\psset@@viewpoint#1 {} {} {} \@nil
  \let\psk@normal\pst@tempg}
\psset@normal{0 0 1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@embedangle,\psk@embedangle}
%    \begin{macrocode}
\def\psset@embedangle#1{\pst@getangle{#1}\psk@embedangle}
\psset@embedangle{0}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\tx@TMSave,\tx@TMRestore}
% \begin{LVerbatim}
%   {<Proc for modifying tm>} TMChange
%    \begin{macrocode}
\pst@def{TMSave}<%
  tx@Dict /TMatrix known not { /TMatrix { } def /RAngle { 0 } def } if
  /TMatrix [ TMatrix CM ] cvx def>
\pst@def{TMRestore}<%
  CP /TMatrix [ TMatrix setmatrix ] cvx def moveto>
\pst@def{TMChange}<%
  \tx@TMSave
  /cp [ currentpoint ] cvx def % ??? Check this later.
  CM
% Set "standard" coor. system , with "pt" units and origin at currentpoint.
% This let's us rotate, or whatever, around \TeX's current point, without
% having to worry about strange coordinate systems that the dvi-to-ps
% driver might be using.
  CP T \tx@STV
% Let M = old matrix (on stack), and M' equal current matrix. Then
% go from M' to M by applying  M Inv(M').
  CM matrix invertmatrix    % Inv(M')
  matrix concatmatrix       % M Inv(M')
% Now modify transformation matrix:
  exch exec
% Now apply M Inv(M')
  concat cp moveto>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ThreeDput}
%    \begin{macrocode}
\def\ThreeDput{\def\pst@par{}\pst@object{ThreeDput}}
\def\ThreeDput@i{\@ifnextchar({\ThreeDput@ii}{\ThreeDput@ii(\z@,\z@,\z@)}}
\def\ThreeDput@ii(#1,#2,#3){%
  \pst@killglue\pst@makebox{\ThreeDput@iii(#1,#2,#3)}}
\def\ThreeDput@iii(#1,#2,#3){%
  \begingroup
    \use@par
    \if@star\pst@starbox\fi
    \pst@makesmall\pst@hbox
    \pssetxlength\pst@dima{#1}%
    \pssetylength\pst@dimb{#2}%
    \pssetzlength\pst@dimc{#3}%
    \leavevmode
    \hbox{%
      \pst@Verb{%
        { \pst@number\pst@dima
          \pst@number\pst@dimb
          \pst@number\pst@dimc
          \psk@normal
          \psk@embedangle
          \psk@viewpoint
          \psk@viewangle
          \tx@SetMatrixEmbed
        } \tx@TMChange}%
    \box\pst@hbox
    \pst@Verb{\tx@TMRestore}}%
  \endgroup
  \ignorespaces}
%    \end{macrocode}
% \end{macro}
%
%
% \section{Arithmetic\label{Arithmetic}}
%
%
% \begin{macro}{\pst@divide}
% This is adapted from Donald Arseneau's "shapepar.sty".
% Syntax:
% \begin{LVerbatim}
%   \pst@divide{<numerator>}{<denominator>}{<command>}
%   \pst@@divide{<numerator>}{<denominator>}
% \end{LVerbatim}
% <numerator> and <denominator> should be dimensions. "\pst@divide" sets
% <command> to <num>/<den> (in points). "\pst@@divide" sets "\pst@dimg" to
% <num>/<den>.
%    \begin{macrocode}
\def\pst@divide#1#2#3{%
  \pst@@divide{#1}{#2}%
  \pst@dimtonum\pst@dimg{#3}}
\def\pst@@divide#1#2{%
  \pst@dimg=#1\relax
  \pst@dimh=#2\relax
  \pst@cntg=\pst@dimh
  \pst@cnth=67108863
  \pst@@@divide\pst@@@divide\pst@@@divide\pst@@@divide
  \divide\pst@dimg\pst@cntg}
%    \end{macrocode}
% The number 16 is the level of uncertainty. Use a lower power of 2 for more
% accuracy (2 is most precise). But if you change it, you must change the
% repetions of "\pst@@@divide" in "\pst@@divide" above:
% \[
%   \mbox{precision}^\mbox{repetitions} = 65536
% \]
% (E.g., $16^4 = 65536$).
%    \begin{macrocode}
\def\pst@@@divide{%
  \ifnum
    \ifnum\pst@dimg<\z@-\fi\pst@dimg<\pst@cnth
    \multiply\pst@dimg\sixt@@n
  \else
    \divide\pst@cntg\sixt@@n
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pst@pyth}
% Syntax:
% \begin{LVerbatim}
%   \pst@pyth{<dim1>}{<dim2>}{<dimen register>}
% \end{LVerbatim}
% <dimen register> is set to $((dim1)^2+(dim2)^2)^{1/2}$.
%
% The algorithm is copied from \PiCTeX, by Michael Wichura (with permission).
% Here is his description:
% \begin{quote}
% Suppose $x>0$, $y>0$. Put $s = x+y$. Let $z = (x^2+y^2)^{1/2}$. Then $z =
% s\times f$, where
% \[
%   f = (t^2 + (1-t)^2)^{1/2} = ((1+\tau^2)/2)^{1/2}
% \]
% and $t = x/s$  and  $\tau = 2(t-1/2)$.
% \end{quote}
%    \begin{macrocode}
\def\pst@pyth#1#2#3{%
  \begingroup
    \pst@dima=#1\relax
    \ifnum\pst@dima<\z@\pst@dima=-\pst@dima\fi  % dima=abs(x)
    \pst@dimb=#2\relax
    \ifnum\pst@dimb<\z@\pst@dimb=-\pst@dimb\fi  % dimb=abs(y)
    \advance\pst@dimb\pst@dima         % dimb=s=abs(x)+abs(y)
    \ifnum\pst@dimb=\z@
      \global\pst@dimg=\z@             % dimg=z=sqrt(x^2+y^2)
    \else
      \multiply\pst@dima 8\relax              % dima= 8abs(x)
      \pst@@divide\pst@dima\pst@dimb     % dimg =8t=8abs(x)/s
      \advance\pst@dimg -4pt            % dimg = 4tau = (8t-4)
      \multiply\pst@dimg 2
      \pst@dimtonum\pst@dimg\pst@tempa
      \pst@dima=\pst@tempa\pst@dimg           % dima=(8tau)^2
      \advance\pst@dima 64pt         % dima=u=[64+(8tau)^2]/2
      \divide\pst@dima 2\relax                      % =(8f)^2
      \pst@dimd=7pt                % initial guess at sqrt(u)
      \pst@@pyth\pst@@pyth\pst@@pyth            % dimd=sqrt(u)
      \pst@dimtonum\pst@dimd\pst@tempa
      \pst@dimg=\pst@tempa\pst@dimb
      \global\divide\pst@dimg 8             % dimg=z=(8f)*s/8
    \fi
  \endgroup
  #3=\pst@dimg}
\def\pst@@pyth{%                      dimd = g <-- (g + u/g)/2
  \pst@@divide\pst@dima\pst@dimd
  \advance\pst@dimd\pst@dimg
  \divide\pst@dimd 2\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pst@sinandcos}
% Syntax:
% \begin{LVerbatim}
%   \pst@sinandcos{<dim>}{<int>}
% \end{LVerbatim}
% <dim>, in "sp" units, should equal 100,000 times the angle, in degrees
% between 0 and 90. <int> should equal the angle's quadrant (0, 1, 2 or 3).
% "\pst@dimg" is set to $\sin(\theta)$ and "\pst@dimh" is set to
% $\cos(\theta)$ (in pt's).
%
% The algorithms uses the usual McLaurin expansion.
%    \begin{macrocode}
\def\pst@sinandcos#1{%
  \begingroup
    \pst@dima=#1\relax
    \pst@dima=.366022\pst@dima     %Now 1pt=1/32rad
    \pst@dimb=\pst@dima   % dimb->32sin(angle) in pts
    \pst@dimc=32\p@       % dimc->32cos(angle) in pts
    \pst@dimtonum\pst@dima\pst@tempa
    \pst@cntb=\tw@
    \pst@cntc=-\@ne
    \pst@cntg=32
    \loop
    \ifnum\pst@dima>\@cclvi % 256
      \pst@dima=\pst@tempa\pst@dima
      \divide\pst@dima\pst@cntg
      \divide\pst@dima\pst@cntb
      \ifodd\pst@cntb
        \advance\pst@dimb \pst@cntc\pst@dima
        \pst@cntc=-\pst@cntc
      \else
        \advance\pst@dimc by \pst@cntc\pst@dima
      \fi
      \advance\pst@cntb\@ne
    \repeat
    \divide\pst@dimb\pst@cntg
    \divide\pst@dimc\pst@cntg
    \global\pst@dimg\pst@dimb
    \global\pst@dimh\pst@dimc
  \endgroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pst@getsinandcos}
% "\pst@getsinandcos" normalizes the angle to be in the first quadrant, sets
% "\pst@quadrant" to 0 for the first quadrant, 1 for the second, 2 for the
% third, and 3 for the fourth, invokes "\pst@sinandcos", and sets "\pst@sin"
% to the sine and "\pst@cos" to the cosine.
%    \begin{macrocode}
\def\pst@getsinandcos#1{%
  \pst@dimg=100000sp
  \pst@dimg=#1\pst@dimg
  \pst@dimh=36000000sp
  \pst@cntg=0
  \loop
  \ifnum\pst@dimg<\z@
    \advance\pst@dimg\pst@dimh
  \repeat
  \loop
  \ifnum\pst@dimg>\pst@dimh
    \advance\pst@dimg-\pst@dimh
  \repeat
  \pst@dimh=9000000sp
  \def\pst@tempg{%
    \ifnum\pst@dimg<\pst@dimh\else
      \advance\pst@dimg-\pst@dimh
      \advance\pst@cntg\@ne
      \ifnum\pst@cntg>\thr@@ \advance\pst@cntg-4 \fi
      \expandafter\pst@tempg
    \fi}%
  \pst@tempg
  \chardef\pst@quadrant\pst@cntg
  \ifdim\pst@dimg=\z@
    \def\pst@sin{0}%
    \def\pst@cos{1}%
  \else
    \pst@sinandcos\pst@dimg
    \pst@dimtonum\pst@dimg\pst@sin
    \pst@dimtonum\pst@dimh\pst@cos
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \section{Tilting}
%
% \begin{macro}{\pstilt}
%    \begin{macrocode}
\def\pstilt#1{\pst@makebox{\pstilt@{#1}}}
\def\pstilt@#1{%
  \begingroup
    \leavevmode
    \pst@getsinandcos{#1}%
    \hbox{%
      \ifcase\pst@quadrant
        \kern\pst@cos\dp\pst@hbox
        \pst@dima=\pst@cos\ht\pst@hbox
        \ht\pst@hbox=\pst@sin\ht\pst@hbox
        \dp\pst@hbox=\pst@sin\dp\pst@hbox
      \or
        \kern\pst@sin\ht\pst@hbox
        \pst@dima=\pst@sin\dp\pst@hbox
        \ht\pst@hbox=\pst@cos\ht\pst@hbox
        \dp\pst@hbox=\pst@cos\dp\pst@hbox
      \or
        \kern\pst@cos\ht\pst@hbox
        \pst@dima=\pst@sin\dp\pst@hbox
        \pst@dimg=\pst@sin\ht\pst@hbox
        \ht\pst@hbox=\pst@sin\dp\pst@hbox
        \dp\pst@hbox=\pst@dimg
      \or
        \kern\pst@sin\dp\pst@hbox
        \pst@dima=\pst@sin\ht\pst@hbox
        \pst@dimg=\pst@cos\ht\pst@hbox
        \ht\pst@hbox=\pst@cos\dp\pst@hbox
        \dp\pst@hbox=\pst@dimg
      \fi
      \pst@Verb{%
        { [ 1 0
            \pst@cos\space \ifnum\pst@quadrant>\@ne neg \fi
            \pst@sin\space
            \ifnum\pst@quadrant>\z@\ifnum\pst@quadrant<\thr@@ neg \fi\fi
            \ifodd\pst@quadrant exch \fi
            0 0
          ] concat
        } \tx@TMChange}%
      \box\pst@hbox
      \pst@Verb{\tx@TMRestore}%
      \kern\pst@dima}%
  \endgroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psTilt}
%    \begin{macrocode}
\def\psTilt#1{\pst@makebox{\psTilt@{#1}}}
\def\psTilt@#1{%
  \begingroup
    \leavevmode
    \pst@getsinandcos{#1}%
    \hbox{%
      \ifodd\pst@quadrant
        \pst@@divide{\dp\pst@hbox}{\pst@cos\p@}%
        \ifnum\pst@quadrant=\thr@@\kern\else\pst@dima=\fi\pst@sin\pst@dimg
        \pst@@divide{\ht\pst@hbox}{\pst@cos\p@}%
        \ifnum\pst@quadrant=\@ne\kern\else\pst@dima=\fi\pst@sin\pst@dimg
      \else
        \ifdim\pst@sin\p@=\z@
          \@pstrickserr{\string\psTilt\space angle cannot be 0 or 180}\@ehpa
          \def\pst@sin{.7071}%
          \def\pst@cos{.7071}%
        \fi
        \pst@@divide{\dp\pst@hbox}{\pst@sin\p@}%
        \ifnum\pst@quadrant=\z@\kern\else\pst@dima=\fi\pst@cos\pst@dimg
        \pst@@divide{\ht\pst@hbox}{\pst@sin\p@}%
        \ifnum\pst@quadrant=\tw@\kern\else\pst@dima=\fi\pst@cos\pst@dimg
      \fi
      \ifnum\pst@quadrant>\@ne
        \pst@dimg=\ht\pst@hbox
        \ht\pst@hbox=\dp\pst@hbox
        \dp\pst@hbox=\pst@dimg
      \fi
      \pst@Verb{%
        { [ 1 0
            \pst@cos\space \pst@sin\space
            \ifodd\pst@quadrant exch \fi
            \tx@Div
            \ifnum\pst@quadrant>\z@\ifnum\pst@quadrant<\thr@@ neg \fi\fi
            \ifnum\pst@quadrant>\@ne -1 \else 1 \fi
            0 0
          ] concat
        } \tx@TMChange}%
      \box\pst@hbox
      \pst@Verb{\tx@TMRestore}%
      \kern\pst@dima}%
  \endgroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@Tshadowsize,\psTshadowsize}
%    \begin{macrocode}
\def\psset@Tshadowsize#1{\pst@checknum{#1}\psTshadowsize}
\psset@Tshadowsize{1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@Tshadowangle,\psk@Tshadowangle}
%    \begin{macrocode}
\def\psset@Tshadowangle#1{\pst@getangle{#1}\psk@Tshadowangle}
\psset@Tshadowangle{60}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psset@Tshadowcolor,\psTshadowcolor}
%    \begin{macrocode}
\def\psset@Tshadowcolor#1{\pst@getcolor{#1}\psTshadowcolor}
\psset@Tshadowcolor{lightgray}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psshadow}
%    \begin{macrocode}
\def\psshadow{\def\pst@par{}\pst@object{psshadow}}
\def\psshadow@i{\pst@makebox{\psshadow@ii}}
\def\psshadow@ii{%
  \begingroup
    \use@par
    \leavevmode
    \pst@getsinandcos{\psk@Tshadowangle}%
    \hbox{%
      \lower\dp\pst@hbox\hbox{%
        \pst@Verb{%
          { [ 1 0
              \pst@cos\space \psTshadowsize mul
              \ifnum\pst@quadrant>\@ne neg \fi
              \pst@sin\space \psTshadowsize mul
              \ifnum\pst@quadrant>\z@\ifnum\pst@quadrant<\thr@@ neg \fi\fi
              \ifodd\pst@quadrant exch \fi
              0 0
            ] concat
          } \tx@TMChange}}%
      \hbox to\z@{{\@nameuse{\psTshadowcolor}\copy\pst@hbox\hss}}%
      \pst@Verb{\tx@TMRestore}%
      \box\pst@hbox}%
  \endgroup}
%    \end{macrocode}
% \end{macro}

\catcode`\@=\TheAtCode\relax

\endinput

%% END pst-3d.tex
