%% 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-97} \def\filedate{1997/03/25} %% %% 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 "" 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} % {} 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{}{}{} % \pst@@divide{}{} % \end{LVerbatim} % and should be dimensions. "\pst@divide" sets % to / (in points). "\pst@@divide" sets "\pst@dimg" to % /. % \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{}{}{} % \end{LVerbatim} % 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{}{} % \end{LVerbatim} % , in "sp" units, should equal 100,000 times the angle, in degrees % between 0 and 90. 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