grunwald@uiucdcsm.cs.uiuc.edu (01/18/88)
This is part 3 of 3 of the PicTeX macros
----------------------------------------------------------------------
\!yshift=-\!dp
\else
\if B\!orientation
\!yshift=\!zpt
\else
\if t\!orientation
\!yshift=\!ht
\fi
\fi
\fi
\fi
\fi}
% ** \!dimenput{OBJECT} <XDIMEN,YDIMEN> [XY] (XLOC,YLOC)
% ** This is an internal put routine, similar to \put, except that
% ** XLOC=distance right from reference point, YLOC=distance up from
% ** reference point. XLOC and YLOC are dimensions, so this routine
% ** is completely independent of the current coordinate system.
% ** This routine does NOT do ROTATIONS.
\long\def\!dimenput#1#2(#3,#4){%
\!setputobject{#1}{#2}%
\!xpos=#3\advance\!xpos by -\!xshift
\!ypos=#4\advance\!ypos by -\!yshift
\kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
\!doaccounting\ignorespaces}
% ** The following macros permit the picture drawing routines to be used
% ** either in the default "coordinate mode", or in "dimension mode".
% ** In coordinate mode \!M(1.5,\!xunit) expands to 1.5\!xunit
% ** In dimension mode \!M(1.5pt,\!xunit) expands to 1.5pt
% ** Dimension mode is useful in coding macros.
% ** Any special purpose picture macro that sets dimension mode should
% ** reset coordinate mode before completion.
% ** See Subsection 9.2 of the manual.
\def\!setdimenmode{%
\let\!M=\!M!!\ignorespaces}
\def\!setcoordmode{%
\let\!M=\!M!\ignorespaces}
\def\!ifcoordmode{%
\ifx \!M \!M!}
\def\!ifdimenmode{%
\ifx \!M \!M!!}
\def\!M!#1#2{#1#2}
\def\!M!!#1#2{#1}
\!setcoordmode
\let\setdimensionmode=\!setdimenmode
\let\setcoordinatemode=\!setcoordmode
% ** \Xdistance{XCOORD}, \Ydistance{YCOORD} are the horizontal and
% ** vertical distances from the origin (0,0) to the point
% ** (XCOORD,YCOORD) in the current coordinate system.
% ** See Subsection 9.2 of the manual.
\def\Xdistance#1{%
\!M{#1}\!xunit
\ignorespaces}
\def\Ydistance#1{%
\!M{#1}\!yunit
\ignorespaces}
% ** The following macros -- \stack, \line, and \Lines -- are useful for
% ** annotating PiCtures. They can be used outside the \beginpicture ...
% ** \endpicture environment.
% ** \stack [POSITIONING] <LEADING> {VALUESLIST}
% ** Builds a vertical stack of the values in VALUESLIST. Values in
% ** VALUESLIST are separated by commas. In the resulting stack, values are
% ** centered by default, and positioned flush left (right) if
% ** POSITIONING = l (r). Values are separated vertically by LEADING,
% ** which defaults to \stackleading.
% ** See Subsection 2.3 of the manual.
\def\stack{%
\!ifnextchar[{\!stack}{\!stack[c]}}
\def\!stack[#1]{%
\let\!lglue=\hfill \let\!rglue=\hfill
\expandafter\let\csname !#1glue\endcsname=\relax
\!ifnextchar<{\!!stack}{\!!stack<\stackleading>}}
\def\!!stack<#1>#2{%
\vbox{\def\!valueslist{}\!ecfor\!value:=#2\do{%
\expandafter\!rightappend\!value\withCS{\\}\to\!valueslist}%
\!lop\!valueslist\to\!value
\let\\=\cr\lineskiplimit=\maxdimen\lineskip=#1%
\baselineskip=-1000pt\halign{\!lglue##\!rglue\cr \!value\!valueslist\cr}}%
\ignorespaces}
% ** \lines [POSITIONING] {LINES}
% ** Builds a vertical array of the lines in LINES. Each line in LINES
% ** is terminated by a \cr. In the resulting array, lines are
% ** centered by default, and positioned flush left (right) if
% ** POSITIONING = l (r). The lines in the array are subject to TeX's
% ** usual spacing rules: in particular the baselines are ordinarily an equal
% ** distance apart. The baseline of the array is the baseline of the
% ** the bottom line.
% ** See Subsection 2.3 of the manual.
\def\lines{%
\!ifnextchar[{\!lines}{\!lines[c]}}
\def\!lines[#1]#2{%
\let\!lglue=\hfill \let\!rglue=\hfill
\expandafter\let\csname !#1glue\endcsname=\relax
\vbox{\halign{\!lglue##\!rglue\cr #2\crcr}}%
\ignorespaces}
% ** \Lines [POSITIONING] {LINES}
% ** Like \lines, but the baseline of the array is the baseline of the
% ** top line. See Subsection 2.3 of the manual.
\def\Lines{%
\!ifnextchar[{\!Lines}{\!Lines[c]}}
\def\!Lines[#1]#2{%
\let\!lglue=\hfill \let\!rglue=\hfill
\expandafter\let\csname !#1glue\endcsname=\relax
\vtop{\halign{\!lglue##\!rglue\cr #2\crcr}}%
\ignorespaces}
% *********************************************
% *** PLOTTING (Things to do with plotting) ***
% *********************************************
% ** User commands
% ** \setplotsymbol ({PLOTSYMBOL} [ORIENTATION] <XSHIFT,YSHIFT>)
% ** \savelinesandcurves on "FILE_NAME"
% ** \dontsavelinesandcurves
% ** \writesavefile {MESSAGE}
% ** \replot {FILE_NAME}
% ** Internal command
% ** \!plot(XDIMEN,YDIMEN)
% ** \setplotsymbol ({PLOTSYMBOL} [ ] < , >)
% ** Save PLOTSYMBOL away in an hbox for use with curve plotting routines
% ** See Subsection 5.2 of the manual.
\def\setplotsymbol(#1#2){%
\!setputobject{#1}{#2}
\setbox\!plotsymbol=\box\!putobject%
\!plotsymbolxshift=\!xshift
\!plotsymbolyshift=\!yshift
\ignorespaces}
\setplotsymbol({\fiverm .})% ** initialize plotsymbol
% ** \!plot is either \!!plot (when no lines and curves are being saved) or
% ** \!!!plot (when lines and curves are being saved)
% ** \!!plot(XDIMEN,YDIMEN)
% ** Places the current plotsymbol a horizontal distance=XDIMEN-xorigin
% ** and a vertical distance=YDIMEN-yorigin from the current
% ** reference point.
\def\!!plot(#1,#2){%
\!dimenA=-\!plotxorigin \advance \!dimenA by #1% ** over
\!dimenB=-\!plotyorigin \advance \!dimenB by #2% ** up
\kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
\ignorespaces}
% ** \!!!plot(XDIMEN,YDIMEN)
% ** Like \!!plot, but also saves the plot location in units of
% ** scaled point, on file `replotfile'
\def\!!!plot(#1,#2){%
\!dimenA=-\!plotxorigin \advance \!dimenA by #1% ** over
\!dimenB=-\!plotyorigin \advance \!dimenB by #2% ** up
\kern\!dimenA\raise\!dimenB\copy\!plotsymbol\kern-\!dimenA%
\!countE=\!dimenA
\!countF=\!dimenB
\immediate\write\!replotfile{\the\!countE,\the\!countF.}%
\ignorespaces}
% ** \savelinesandcurves on "FILE_NAME"
% ** Switch to save locations used for plotting lines and curves
% ** (No advantage in saving locations for solid lines; however
% ** replotting curve locations speeds things up by a factor of about 4.
% ** \dontsavelinesandcurves
% ** Terminates \savelinesandcurves. The default.
% ** See Subsection 5.6 of the manual.
\def\savelinesandcurves on "#1" {%
\immediate\closeout\!replotfile
\immediate\openout\!replotfile=#1%
\let\!plot=\!!!plot}
\def\dontsavelinesandcurves {%
\let\!plot=\!!plot}
\dontsavelinesandcurves
% ** \writesavefile {MESSAGE}
% ** The message is preceded by a "%", so that it won't interfere
% ** with replotting.
% ** See Subsection 5.6 of the manual.
{\catcode`\%=11\xdef\!Commentsignal{%}}
\def\writesavefile#1 {%
\immediate\write\!replotfile{\!Commentsignal #1}%
\ignorespaces}
% ** \replot "FILE_NAME"
% ** Replots the locations saved earlier under \savelinesandcurves
% ** on "FILE_NAME"
% ** See Subsection 5.6 of the manual.
\def\replot"#1" {%
\expandafter\!replot\input #1 /}
\def\!replot#1,#2. {%
\!dimenA=#1sp
\kern\!dimenA\raise#2sp\copy\!plotsymbol\kern-\!dimenA
\futurelet\!nextchar\!!replot}
\def\!!replot{%
\if /\!nextchar
\def\!next{\!finish}%
\else
\def\!next{\!replot}%
\fi
\!next}
% **************************************************
% *** PYTHAGORAS (Euclidean distance function) ***
% **************************************************
% ** User command:
% ** \placehypotenuse for <dimension1> and <dimension2> in <register>
% ** Internal command:
% ** \!Pythag{X}{Y}{Z}
% ** Input X,Y are dimensions, or dimension registers.
% ** Output Z == sqrt(X**2+Y**2) must be a dimension register.
% ** Assumes that |X|+|Y| < 2048pt (about 28in).
% ** Without loss of generality, suppose x>0, y>0. Put s = x+y,
% ** z = sqrt(x**2+y**2). Then z = s*f, where f = sqrt(t**2 + (1-t)**2)
% ** = sqrt((1+tau**2)/2), where t = x/s and tau = 2(t-1/2) .
% ** Uses the \!divide macro (which uses registers \!dimenA--\!dimenD.
% ** Uses the \!removept macro (e.g., 123.45pt --> 123.45)
% ** Uses registers \!dimenE--\!dimenI.
\def\!Pythag#1#2#3{%
\!dimenE=#1\relax
\ifdim\!dimenE<\!zpt
\!dimenE=-\!dimenE
\fi% ** dimE = |x|
\!dimenF=#2\relax
\ifdim\!dimenF<\!zpt
\!dimenF=-\!dimenF
\fi% ** dimF = |y|
\advance \!dimenF by \!dimenE% ** dimF = s = |x|+|y|
\ifdim\!dimenF=\!zpt
\!dimenG=\!zpt% ** dimG = z = sqrt(x**2+y**2)
\else
\!divide{8\!dimenE}\!dimenF\!dimenE% ** now dimE = 8t = (8|x|)/s
\advance\!dimenE by -4pt% ** 8tau = (8t-4)*2
\!dimenE=2\!dimenE% ** (tau = 2*t - 1)
\!removept\!dimenE\!!t% ** 8tau, without "pt"
\!dimenE=\!!t\!dimenE% ** (8tau)**2, in pts
\advance\!dimenE by 64pt% ** u = [64 + (8tau)**2]/2
\divide \!dimenE by 2% ** [u = (8f)**2]
\!dimenH=7pt% ** initial guess g at sqrt(u)
\!!Pythag\!!Pythag\!!Pythag% ** 3 iterations give sqrt(u)
\!removept\!dimenH\!!t% ** 8f=sqrt(u), without "pt"
\!dimenG=\!!t\!dimenF% ** z = (8f)*s/8
\divide\!dimenG by 8
\fi
#3=\!dimenG
\ignorespaces}
\def\!!Pythag{% ** Newton-Raphson for sqrt
\!divide\!dimenE\!dimenH\!dimenI% ** v = u/g
\advance\!dimenH by \!dimenI% ** g <-- (g + u/g)/2
\divide\!dimenH by 2}
% ** \placehypotenuse for <XI> and <ETA> in <ZETA>
% ** See Subsection 9.3 of the manual.
\def\placehypotenuse for <#1> and <#2> in <#3> {%
\!Pythag{#1}{#2}{#3}}
% **********************************************
% *** QUADRATIC ARC (Draws a quadratic arc) ***
% **********************************************
% ** Internal command
% ** \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
% ** \!qjoin (XCOORD1,YCOORD1) (XCOORD2,YCOORD2)
% ** Draws an arc starting at the (last) point specified by the most recent
% ** \!qjoin, or \!ljoin, or \!start and passing through (X_1,Y_1), (X_2,Y_2).
% ** Uses quadratic interpolation in both x and y:
% ** x(t), 0 <= t <= 1, interpolates x_0, x_1, x_2 at t=0, .5, 1
% ** y(t), 0 <= t <= 1, interpolates y_0, y_1, y_2 at t=0, .5, 1
\def\!qjoin (#1,#2) (#3,#4){%
\advance\!intervalno by 1
\!ifcoordmode
\edef\!xmidpt{#1}\edef\!ymidpt{#2}%
\else
\!dimenA=#1\relax \edef\!xmidpt{\the\!dimenA}%
\!dimenA=#2\relax \edef\!xmidpt{\the\!dimenA}%
\fi
\!xM=\!M{#1}\!xunit \!yM=\!M{#2}\!yunit \!rotateaboutpivot\!xM\!yM
\!xE=\!M{#3}\!xunit \!yE=\!M{#4}\!yunit \!rotateaboutpivot\!xE\!yE
%
% ** Find coefficients for x(t)=a_x + b_x*t + c_x*t**2
\!dimenA=\!xM \advance \!dimenA by -\!xS% ** dimA = I = xM - xS
\!dimenB=\!xE \advance \!dimenB by -\!xM% ** dimB = II = xE-xM
\!xB=3\!dimenA \advance \!xB by -\!dimenB% ** b=3I-II
\!xC=2\!dimenB \advance \!xC by -2\!dimenA% ** c=2(II-I)
%
% ** Find coefficients for y(t)=y_x + b_y*t + c_y*t**2
\!dimenA=\!yM \advance \!dimenA by -\!yS%
\!dimenB=\!yE \advance \!dimenB by -\!yM%
\!yB=3\!dimenA \advance \!yB by -\!dimenB%
\!yC=2\!dimenB \advance \!yC by -2\!dimenA%
%
% ** Use Simpson's rule to calculate arc length over [0,1/2]:
% ** arc length = 1/2[1/6 f(0) + 4/6 f(1/4) + 1/6 f(1/2)]
% ** with f(t) = sqrt(x'(t)**2 + y'(t)**2).
\!xprime=\!xB \!yprime=\!yB% ** x'(t) = b + 2ct
\!dxprime=.5\!xC \!dyprime=.5\!yC% ** dt=1/4 ==> dx'(t) = c/2
\!getf \!midarclength=\!dimenA
\!getf \advance \!midarclength by 4\!dimenA
\!getf \advance \!midarclength by \!dimenA
\divide \!midarclength by 12
%
% ** Get arc length over [0,1].
\!arclength=\!dimenA
\!getf \advance \!arclength by 4\!dimenA
\!getf \advance \!arclength by \!dimenA
\divide \!arclength by 12% ** Now have arc length over [1/2,1]
\advance \!arclength by \!midarclength
\global\advance \totalarclength by \!arclength
%
%
% ** Check to see if there's anything to plot in this interval
\ifdim\!distacross>\!arclength
\advance \!distacross by -\!arclength% ** nothing
%
\else
\!initinverseinterp% ** initialize for inverse interpolation on arc length
\loop\ifdim\!distacross<\!arclength% ** loop over points on arc
\!inverseinterp% ** find t such that arc length[0,t] = distacross,
% ** using inverse quadratic interpolation
% ** now evaluate x(t)=(c*t + b)*t + a
\!xpos=\!t\!xC \advance\!xpos by \!xB
\!xpos=\!t\!xpos \advance \!xpos by \!xS
% ** evaluate y(t)
\!ypos=\!t\!yC \advance\!ypos by \!yB
\!ypos=\!t\!ypos \advance \!ypos by \!yS
\!plotifinbounds% ** plot point if in bounds
\advance\!distacross \plotsymbolspacing%** advance arc length for next pt
\!advancedashing% ** see "linear"
\repeat
%
\advance \!distacross by -\!arclength% ** prepare for next interval
\fi
%
\!xS=\!xE% ** shift ending points to starting points
\!yS=\!yE
\ignorespaces}
% ** \!getf -- Calculates sqrt(x'(t)**2 + y'(t)**2) and advances
% ** x'(t) and y'(t)
\def\!getf{\!Pythag\!xprime\!yprime\!dimenA%
\advance\!xprime by \!dxprime
\advance\!yprime by \!dyprime}
% ** \!initinverseinterp -- initializes for inverse quadratic interpolation
% ** of arc length provided 1/3 < midarclength/arclength < 2/3; otherwise
% ** initializes for inverse linear interpolation.
\def\!initinverseinterp{%
\ifdim\!arclength>\!zpt
\!divide{8\!midarclength}\!arclength\!dimenE% ** dimE=8w=8r/s, where r
% ** = midarclength, s=arclength
% ** Test for w out of range: w<1/3 or w>2/3
\ifdim\!dimenE<\!wmin \!setinverselinear
\else
\ifdim\!dimenE>\!wmax \!setinverselinear
\else% ** w in range: initialize
\def\!inverseinterp{\!inversequad}\ignorespaces
%
% ** Calculate the coefficients \!beta and \!gamma of the quadratic
% ** t = \!beta*v + \!gamma*v**2
% ** taking the values t=0, 1/2, 1 at v=0, w==r/s, 1 respectively:
% ** \!beta = (1/2 - w**2)/[w(1-w)]
% ** \!gamma = 1 - beta.
%
\!removept\!dimenE\!Ew% ** 8w, without "pt"
\!dimenF=-\!Ew\!dimenE% ** -(8w)**2
\advance\!dimenF by 32pt% ** 32 - (8w)**2
\!dimenG=8pt
\advance\!dimenG by -\!dimenE% ** 8 - 8w
\!dimenG=\!Ew\!dimenG% ** (8w)*(8-8w)
\!divide\!dimenF\!dimenG\!beta% ** beta = (32-(8w)**2)/(8w(8-8w))
% ** = (1/2 - w**2)/(w(1-w))
\!gamma=1pt
\advance \!gamma by -\!beta% ** gamma = 1-beta
\fi% ** end of the \ifdim\!dimenE>\!wmax
\fi% ** end of the \ifdim\!dimenE<\!wmin
\fi% ** end of the \ifdim\!arclength>\!zpt
\ignorespaces}
% ** For 0 <= t <= 1, let AL(t) = arclength[0,t]/arclength[0,1]; note
% ** AL(0)=0, AL(1/2)=midarclength/arclength, AL(1)=1. This routine
% ** calculates an approximation to AL^{-1}(distance across/arclength),
% ** using the assumption that AL^{-1} is quadratic. Specifically,
% ** it finds t such that
% ** AL^{-1}(v) =. t = v*(\!beta + \!gamma*v)
% ** where \!beta and \!gamma are set by \!initinv, and where
% ** v=distance across/arclength
\def\!inversequad{%
\!divide\!distacross\!arclength\!dimenG% ** dimG = v = distacross/arclength
\!removept\!dimenG\!v% ** v, without "pt"
\!dimenG=\!v\!gamma% ** gamma*v
\advance\!dimenG by \!beta% ** beta + gamma*v
\!dimenG=\!v\!dimenG% ** t = v*(beta + gamma*v)
\!removept\!dimenG\!t}% ** t, without "pt"
% ** When w <= 1/3 or w >= 2/3, the following routine writes (using
% ** plain TEK's \wlog command) a warning message on the user's log file,
% ** and initializes for inverse linear interpolation on arc length.
\def\!setinverselinear{%
\def\!inverseinterp{\!inverselinear}%
\divide\!dimenE by 8 \!removept\!dimenE\!t
\!countC=\!intervalno \multiply \!countC 2
\!countB=\!countC \advance \!countB -1
\!countA=\!countB \advance \!countA -1
\wlog{\the\!countB th point (\!xmidpt,\!ymidpt) being plotted
doesn't lie in the}%
\wlog{ middle third of the arc between the \the\!countA th
and \the\!countC th points:}%
\wlog{ [arc length \the\!countA\space to \the\!countB]/[arc length
\the \!countA\space to \the\!countC]=\!t.}%
\ignorespaces}
% ** Inverse linear interpolation
\def\!inverselinear{%
\!divide\!distacross\!arclength\!dimenG
\!removept\!dimenG\!t}
% **************************************
% ** ROTATIONS (Handles rotations) ***
% **************************************
% ** User commands
% ** \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
% ** \stoprotation
% ** \startrotation [by COS_OF_ANGLE SIN_OF_ANGLE] [about XPIVOT YPIVOT]
% ** Future (XCOORD,YCOORD)'s will be rotated about (XPIVOT,YPIVOT)
% ** by the angle with the give COS and SIN. Both fields are optional.
% ** [COS,SIN] defaults to previous value, or (1,0).
% ** (XPIVOT,YPIVOT) defaults to previous value, or (0,0)
% ** You can't change the coordinate system in the scope of a rotation.
% ** See Subsection 9.1 of the manual.
\def\startrotation{%
\let\!rotateaboutpivot=\!!rotateaboutpivot
\let\!rotateonly=\!!rotateonly
\!ifnextchar{b}{\!getsincos }%
{\!getsincos by {\!cosrotationangle} {\!sinrotationangle} }}
\def\!getsincos by #1 #2 {%
\edef\!cosrotationangle{#1}%
\edef\!sinrotationangle{#2}%
\!ifcoordmode
\let\!ROnext=\!ccheckforpivot
\else
\let\!ROnext=\!dcheckforpivot
\fi
\!ROnext}
\def\!ccheckforpivot{%
\!ifnextchar{a}{\!cgetpivot}%
{\!cgetpivot about {\!xpivotcoord} {\!ypivotcoord} }}
\def\!cgetpivot about #1 #2 {%
\edef\!xpivotcoord{#1}%
\edef\!ypivotcoord{#2}%
\!xpivot=#1\!xunit \!ypivot=#2\!yunit
\ignorespaces}
\def\!dcheckforpivot{%
\!ifnextchar{a}{\!dgetpivot}{\ignorespaces}}
\def\!dgetpivot about #1 #2 {%
\!xpivot=#1\relax \!ypivot=#2\relax
\ignorespaces}
% ** Following terminates rotation.
% ** See Subsection 9.1 of the manual.
\def\stoprotation{%
\let\!rotateaboutpivot=\!!!rotateaboutpivot
\let\!rotateonly=\!!!rotateonly
\ignorespaces}
% ** !!rotateaboutpivot{XREG}{YREG}
% ** XREG <-- xpvt + cos(angle)*(XREG-xpvt) - sin(angle)*(YREG-ypvt)
% ** YREG <-- ypvt + cos(angle)*(YREG-ypvt) + sin(angle)*(XREG-xpvt)
% ** XREG,YREG are dimension registers. Can't be \!dimenA to \!dimenD
\def\!!rotateaboutpivot#1#2{%
\!dimenA=#1\relax \advance\!dimenA -\!xpivot
\!dimenB=#2\relax \advance\!dimenB -\!ypivot
\!dimenC=\!cosrotationangle\!dimenA
\advance \!dimenC -\!sinrotationangle\!dimenB
\!dimenD=\!cosrotationangle\!dimenB
\advance \!dimenD \!sinrotationangle\!dimenA
\advance\!dimenC \!xpivot \advance\!dimenD \!ypivot
#1=\!dimenC #2=\!dimenD
\ignorespaces}
% ** \!!rotateonly{XREG}{YREG}
% ** Like \!!rotateaboutpivot, but with a pivot of (0,0)
\def\!!rotateonly#1#2{%
\!dimenA=#1\relax \!dimenB=#2\relax
\!dimenC=\!cosrotationangle\!dimenA
\advance \!dimenC -\!rotsign\!sinrotationangle\!dimenB
\!dimenD=\!cosrotationangle\!dimenB
\advance \!dimenD \!rotsign\!sinrotationangle\!dimenA
#1=\!dimenC #2=\!dimenD
\ignorespaces}
\def\!rotsign{}
\def\!!!rotateaboutpivot#1#2{\relax}
\def\!!!rotateonly#1#2{\relax}
\stoprotation
\def\!reverserotateonly#1#2{%
\def\!rotsign{-}%
\!rotateonly{#1}{#2}%
\def\!rotsign{}%
\ignorespaces}
% **********************************
% *** SHADING (Handles shading) ***
% **********************************
% ** User commands
% ** \setshadegrid [span <SPAN>] [point at XSHADE YSHADE]
% ** \setshadesymbol [<LS, RS, BS, TS>] ({SHADESYMBOL}
% ** <XDIMEN,YDIMEN> [ORIENTATION])
% ** Internal commands:
% ** \!startvshade (xS,ybS,ytS)
% ** \!starthshade (yS,xlS,xrS)
% ** \!lshade [<LS,RS,BS,TS>]
% ** ** when shading vertically:
% ** [the region from (xS,ybS,ytS) to] (xE,ybE,ytE)
% ** ** when shading horizontally:
% ** [the region from (yS,xlS,xrS) to] (yE,xlE,xrE)
% ** \!qshade [<LS,RS,BS,TS>]
% ** ** when shading vertically:
% ** [the region from (xS,ybS,ytS) to] (xM,ybM,ytM) (xE,ybE,ytE)
% ** ** when shading horizontally:
% ** [the region from (yS,xlS,xrS) to] (yM,xlM,xrM) (yE,xlE,xrE)
% ** \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
% ** \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
% ** The shading routine can operate either in a "vertical mode" or a
% ** "horizontal mode". In vertical mode, the region to be shaded is specified
% ** in the form
% ** {(x,y): xl <= x <= xr & yb(x) <= y <= yt(x)}
% ** where yb and yt are functions of x. In horizontal mode, the region
% ** is specified in the form
% ** {(x,y): yb <= y <= yt & xl(y) <= x <= xr(y)}.
% ** The functions yb and yt may be either both linear or both quadratic;
% ** similarly for xl and xr. A region with say, piecewise quadratic bottom
% ** and top boundaries, can be shaded by consecutive (vertical) \!qshades,
% ** proceeding from left to right. Similarly, a region with piecewise
% ** quadratic left and right boundaries can be shaded by consecutive
% ** (horizontal) \!qshades, proceeding from bottom to top. More complex
% ** regions can be shaded by partitioning them into appropriate subregions,
% ** and shading those.
% ** Shading is accomplished by placing a user-selected shading symbol at
% ** those points of a regular grid which fall within the region to be
% ** shaded. This region can be "shrunk" so that a largish shading symbol
% ** will not extend outside it. Shrinking is accomplished by specifying
% ** shrinkages for the left, right, bottom, and top boundaries, in a manner
% ** discussed further below.
% ** \shades and \!joins MUST NOT be intermingled. Finish drawing a curve
% ** before starting to shade a region, and finish shading a region before
% ** starting to draw a curve.
% ** \setshadegrid [span <SPAN>] [point at XSHADE YSHADE]
% ** The shading symbol is placed down on the points of a grid centered
% ** at the coordinate point (XSHADE,YSHADE). The grid points are of the
% ** form (j*SPAN,k*SPAN), with j+k even. SPAN is specified
% ** as a dimension.
% ** (XSHADE,YSHADE) defaults to previous (XSHADE,YSHADE) (or (0,0) if none)
% ** SPAN defaults to previous span (or 5pt if none)
% ** See Subsection 7.2 of the manual.
\def\setshadegrid{%
\!ifnextchar{s}{\!getspan }
{\!getspan span <\!dshade>}}
\def\!getspan span <#1>{%
\!dshade=#1\relax
\!ifcoordmode
\let\!GRnext=\!GRccheckforAP
\else
\let\!GRnext=\!GRdcheckforAP
\fi
\!GRnext}
\def\!GRccheckforAP{%
\!ifnextchar{p}{\!cgetanchor }
{\!cgetanchor point at {\!xshadesave} {\!yshadesave} }}
\def\!cgetanchor point at #1 #2 {%
\edef\!xshadesave{#1}\edef\!yshadesave{#2}%
\!xshade=\!xshadesave\!xunit \!yshade=\!yshadesave\!yunit
\ignorespaces}
\def\!GRdcheckforAP{%
\!ifnextchar{p}{\!dgetanchor}%
{\ignorespaces}}
\def\!dgetanchor point at #1 #2 {%
\!xshade=#1\relax \!yshade=#2\relax
\ignorespaces}
% ** \setshadesymbol [<LS, RS, BS, TS>] ({SHADESYMBOL}
% ** <XDIMEN,YDIMEN> [ORIENTATION])
% ** Saves SHADESYMBOL away in an hbox for use with shading routines.
% ** A shade symbol will not be plotted if its plot position comes within
% ** distance LS of the left boundary, RS of the right boundary, TS of the
% ** top boundary, BS of the bottom boundary. These parameters have
% ** default values that should work in most cases (see below).
% ** To override a default value, specify the replacement value
% ** in the appropriate subfield of the shrinkages field.
% ** 0pt may be coded as "z" (without the quotes). To accept a
% ** default value, leave the field empty. Thus
% ** [,z,,5pt] sets LS=default, RS=0pt, BS=default, TS=5pt .
% ** Skipping the shrinkages field accepts all the defaults.
% ** See Subsection 7.1 of the manual.
\def\setshadesymbol{%
\!ifnextchar<{\!setshadesymbol}{\!setshadesymbol<,,,> }}
\def\!setshadesymbol <#1,#2,#3,#4> (#5#6){%
% ** set the shadesymbol
\!setputobject{#5}{#6}%
\setbox\!shadesymbol=\box\!putobject%
\!shadesymbolxshift=\!xshift \!shadesymbolyshift=\!yshift
%
% ** set the shrinkages
\!dimenA=\!xshift \advance\!dimenA \!smidge% ** default LS = xshift - smidge
\!override\!dimenA{#1}\!lshrinkage%
\!dimenA=\!wd \advance \!dimenA -\!xshift% ** default RS = width - xshift
\advance\!dimenA \!smidge% - smidge
\!override\!dimenA{#2}\!rshrinkage
\!dimenA=\!dp \advance \!dimenA \!yshift% ** default BS = depth + yshift
\advance\!dimenA \!smidge% - smidge
\!override\!dimenA{#3}\!bshrinkage
\!dimenA=\!ht \advance \!dimenA -\!yshift% ** default TS = height - yshift
\advance\!dimenA \!smidge% - smidge
\!override\!dimenA{#4}\!tshrinkage
\ignorespaces}
\def\!smidge{-.2pt}%
% ** \!override{NOMINAL DIMEN}{REPLACEMENT DIMEN}{DIMEN}
% ** Overrides the NOMINAL DIMEN by the REPLACEMENT DIMEN to produce DIMEN,
% ** according to the following rules:
% ** REPLACEMENT DIMEN empty: DIMEN <-- NOMINAL DIMEN
% ** REPLACEMENT DIMEN z: DIMEN <-- 0pt
% ** otherwise: DIMEN <-- REPLACEMENT DIMEN
% ** DIMEN must be a dimension register
\def\!override#1#2#3{%
\edef\!!override{#2}%
\ifx \!!override\empty
#3=#1\relax
\else
\if z\!!override
#3=\!zpt
\else
\ifx \!!override\!blankz
#3=\!zpt
\else
#3=#2\relax
\fi
\fi
\fi
\ignorespaces}
\def\!blankz{ z}
\setshadesymbol ({\fiverm .})% ** initialize plotsymbol
% ** \fivesy ^^B is a small cross
% ** \!startvshade [at] (xS,ybS,ytS)
% ** Initiates vertical shading mode
\def\!startvshade#1(#2,#3,#4){%
\let\!!xunit=\!xunit%
\let\!!yunit=\!yunit%
\let\!!xshade=\!xshade%
\let\!!yshade=\!yshade%
\def\!getshrinkages{\!vgetshrinkages}%
\let\!setshadelocation=\!vsetshadelocation%
\!xS=\!M{#2}\!!xunit
\!ybS=\!M{#3}\!!yunit
\!ytS=\!M{#4}\!!yunit
\!shadexorigin=\!xorigin \advance \!shadexorigin \!shadesymbolxshift
\!shadeyorigin=\!yorigin \advance \!shadeyorigin \!shadesymbolyshift
\ignorespaces}
% ** \!starthshade [at] (yS,xlS,xrS)
% ** Initiates horizontal shading mode
\def\!starthshade#1(#2,#3,#4){%
\let\!!xunit=\!yunit%
\let\!!yunit=\!xunit%
\let\!!xshade=\!yshade%
\let\!!yshade=\!xshade%
\def\!getshrinkages{\!hgetshrinkages}%
\let\!setshadelocation=\!hsetshadelocation%
\!xS=\!M{#2}\!!xunit
\!ybS=\!M{#3}\!!yunit
\!ytS=\!M{#4}\!!yunit
\!shadexorigin=\!xorigin \advance \!shadexorigin \!shadesymbolxshift
\!shadeyorigin=\!yorigin \advance \!shadeyorigin \!shadesymbolyshift
\ignorespaces}
% ** \!lattice{ANCHOR}{SPAN}{LOCATION}{INDEX}{LATTICE LOCATION}
% ** Consider the lattice with points ANCHOR + j*SPAN. This routine determines
% ** the index k of the smallest lattice point >= LOCATION, and sets
% ** LATTICE LOCATION = ANCHOR + k*SPAN.
% ** INDEX is assumed to be a count register, LATTICE LOCATION a dimen reg.
\def\!lattice#1#2#3#4#5{%
\!dimenA=#1% ** dimA = ANCHOR
\!dimenB=#2% ** dimB = SPAN (assumed > 0pt)
\!countB=\!dimenB% ** ctB = SPAN, as a count
%
% ** Determine index of smallest lattice point >= LOCATION
\!dimenC=#3% ** dimC = LOCATION
\advance\!dimenC -\!dimenA% ** now dimC = LOCATION-ANCHOR
\!countA=\!dimenC% ** ctA = above, as a count
\divide\!countA \!countB% ** now ctA = desired index, if dimC <= 0
\ifdim\!dimenC>\!zpt
\!dimenD=\!countA\!dimenB% ** (tentative k)*span
\ifdim\!dimenD<\!dimenC% ** if this is false, ctA = desired index
\advance\!countA 1 % ** if true, have to add 1
\fi
\fi
%
\!dimenC=\!countA\!dimenB% ** lattice location = anchor + ctA*span
\advance\!dimenC \!dimenA
#4=\!countA% ** the desired index
#5=\!dimenC% ** corresponding lattice location
\ignorespaces}
% ** \!qshade [with shrinkages] [[LS,RS,BS,TS]]
% ***** during vertical shading:
% ** [the region from (xS,ybS,ytS) to] (xM,ybM,ytM) [and] (xE,ybE,ytE)
% ** Shades the region {(x,y): xS <= x <= xE, yb(x) <= y <= yt(x)}, where
% ** yb is the quadratic thru (xS,ybS) & (xM,ybM) & (xE,ybE)
% ** yt is the quadratic thru (xS,ytS) & (xM,ybM) & (xE,ytE)
% ** xS,ybS,ytS are either given by \!startvshade or carried over
% ** as the ending values of the immediately preceding \!qshade.
% ** For the interpretation of LS, RS, BS, & TS, see \setshadesymbol. The
% ** values set there can be overridden, for the course of this \!qshade
% ** only, in the same manner as overrides are specified for
% ** \setshadesymbol.
% ***** during horizontal shading:
% ** [the region from (yS,xlS,xrS) to] (yM,xlM,xrM) [and] (yE,xlE,xrE)
\def\!qshade#1(#2,#3,#4)#5(#6,#7,#8){%
\!xM=\!M{#2}\!!xunit
\!ybM=\!M{#3}\!!yunit
\!ytM=\!M{#4}\!!yunit
\!xE=\!M{#6}\!!xunit
\!ybE=\!M{#7}\!!yunit
\!ytE=\!M{#8}\!!yunit
\!getcoeffs\!xS\!ybS\!xM\!ybM\!xE\!ybE\!ybB\!ybC%**Get coefficients B & C for
\!getcoeffs\!xS\!ytS\!xM\!ytM\!xE\!ytE\!ytB\!ytC%**y=y0 + B(x-X0) + C(x-X0)**2
\def\!getylimits{\!qgetylimits}%
\!shade{#1}\ignorespaces}
% ** \!lshade ... (xE,ybE,ytE)
% ** This is like \!qshade, but the top and bottom boundaries are linear,
% ** rather than quadratic.
\def\!lshade#1(#2,#3,#4){%
\!xE=\!M{#2}\!!xunit
\!ybE=\!M{#3}\!!yunit
\!ytE=\!M{#4}\!!yunit
\!dimenE=\!xE \advance \!dimenE -\!xS% ** xE-xS
\!dimenC=\!ytE \advance \!dimenC -\!ytS% ** ytE-ytS
\!divide\!dimenC\!dimenE\!ytB% ** ytB = (ytE-ytS)/(xE-xS)
\!dimenC=\!ybE \advance \!dimenC -\!ybS% ** ybE-ybS
\!divide\!dimenC\!dimenE\!ybB% ** ybB = (ybE-ybS)/(xE-xS)
\def\!getylimits{\!lgetylimits}%
\!shade{#1}\ignorespaces}
% ** \!getcoeffs{X0}{Y0}{X1}{Y1}{X2}{Y2}{B}{C}
% ** Finds B and C such that the quadratic y = Y0 + B(x-X0) + C(x-X0)**2
% ** passes through (X1,Y1) and (X2,Y2): when X0=0=Y0, the formulas are:
% ** B = S1 - X1*C, C = (S2-S1)/X2
% ** with
% ** S1 = Y1/X1, S2 = (Y2-Y1)/(X2-X1).
\def\!getcoeffs#1#2#3#4#5#6#7#8{%
\!dimenC=#4\advance \!dimenC -#2% ** dimC=Y1-Y0
\!dimenE=#3\advance \!dimenE -#1% ** dimE=X1-X0
\!divide\!dimenC\!dimenE\!dimenF% ** dimF=S1
\!dimenC=#6\advance \!dimenC -#4% ** dimC=Y2-Y1
\!dimenH=#5\advance \!dimenH -#3% ** dimH=X2-X1
\!divide\!dimenC\!dimenH\!dimenG% ** dimG=S2
\advance\!dimenG -\!dimenF% ** dimG=S2-S1
\advance \!dimenH \!dimenE% ** dimH=X2-X0
\!divide\!dimenG\!dimenH#8% ** C=(S2-S1)/(X2-X0)
\!removept#8\!t% ** C, without "pt"
#7=-\!t\!dimenE% ** -C*(X1-X0)
\advance #7\!dimenF% ** B=S1-C*(X1-X0)
\ignorespaces}
\def\!shade#1{%
% ** Get LS,RS,BS,TS for this panel
\!getshrinkages#1<,,,>\!nil% % ** now effective LS=dimE, RS=dimF,
% ** BS=dimG, TS=dimH
\advance \!dimenE \!xS% ** now dimE=xS+LS
\!lattice\!!xshade\!dshade\!dimenE% ** set parity=index of left-mst x-lattice
\!parity\!xpos% ** point >= xS+LS, xpos=its location
\!dimenF=-\!dimenF% ** set dimF=xE-RS
\advance\!dimenF \!xE
%
\!loop\!not{\ifdim\!xpos>\!dimenF}% ** loop over x-lattice points <= xE-RS
\!shadecolumn%
\advance\!xpos \!dshade% ** move over to next column
\advance\!parity 1% ** increase index of x-point
\repeat
%
\!xS=\!xE% ** shift ending values to starting values
\!ybS=\!ybE
\!ytS=\!ytE
\ignorespaces}
\def\!vgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
\!override\!lshrinkage{#2}\!dimenE
\!override\!rshrinkage{#3}\!dimenF
\!override\!bshrinkage{#4}\!dimenG
\!override\!tshrinkage{#5}\!dimenH
\ignorespaces}
\def\!hgetshrinkages#1<#2,#3,#4,#5>#6\!nil{%
\!override\!lshrinkage{#2}\!dimenG
\!override\!rshrinkage{#3}\!dimenH
\!override\!bshrinkage{#4}\!dimenE
\!override\!tshrinkage{#5}\!dimenF
\ignorespaces}
\def\!shadecolumn{%
\!dxpos=\!xpos
\advance\!dxpos -\!xS% ** dx = x - xS
\!removept\!dxpos\!dx% ** ditto, without "pt"
\!getylimits% ** get top and bottom y-values
\advance\!ytpos -\!dimenH% ** less TS
\advance\!ybpos \!dimenG% ** plus BS
\!yloc=\!!yshade% ** get anchor point for this column
\ifodd\!parity
\advance\!yloc \!dshade
\fi
\!lattice\!yloc{2\!dshade}\!ybpos%
\!countA\!ypos% ** ypos=smallest y point for this column
\!dimenA=-\!shadexorigin \advance \!dimenA \!xpos% ** over
\loop\!not{\ifdim\!ypos>\!ytpos}% ** loop over ypos <= yt(t)
\!setshadelocation% ** vmode: xloc=xpos, yloc=ypos
% ** hmode: xloc=ypos, yloc=xpos
\!rotateaboutpivot\!xloc\!yloc%
\!dimenA=-\!shadexorigin \advance \!dimenA \!xloc% ** over
\!dimenB=-\!shadeyorigin \advance \!dimenB \!yloc% ** up
\kern\!dimenA \raise\!dimenB\copy\!shadesymbol \kern-\!dimenA
\advance\!ypos 2\!dshade
\repeat
\ignorespaces}
\def\!qgetylimits{%
\!dimenA=\!dx\!ytC
\advance\!dimenA \!ytB% ** yt(t)=ytS + dx*(Bt + dx*Ct)
\!ytpos=\!dx\!dimenA
\advance\!ytpos \!ytS
\!dimenA=\!dx\!ybC
\advance\!dimenA \!ybB% ** yb(t)=ybS + dx*(Bb + dx*Cb)
\!ybpos=\!dx\!dimenA
\advance\!ybpos \!ybS}
\def\!lgetylimits{%
\!ytpos=\!dx\!ytB% ** yt(t)=ytS + dx*Bt
\advance\!ytpos \!ytS
\!ybpos=\!dx\!ybB% ** yb(t)=ybS + dx*Bb
\advance\!ybpos \!ybS}
\def\!vsetshadelocation{% ** vmode: xloc=xpos, yloc=ypos
\!xloc=\!xpos
\!yloc=\!ypos}
\def\!hsetshadelocation{% ** hmode: xloc=ypos, yloc=xpos
\!xloc=\!ypos
\!yloc=\!xpos}
% **************************************
% *** TICKS (Draws ticks on graphs) ***
% **************************************
% ** User commands
% ** \ticksout
% ** \ticksin
% ** \gridlines
% ** \nogridlines
% ** \loggedticks
% ** \unloggesticks
% ** See Subsection 3.4 of the manual
% ** The following is an option of the \axis command
% ** ticks
% ** [in] [out]
% ** [long] [short] [length <LENGTH>]
% ** [width <WIDTH>]
% ** [andacross] [butnotacross]
% ** [logged] [unlogged]
% ** [unlabeled] [numbered] [withvalues VALUE1 VALUE2 ... VALUEk / ]
% ** [quantity Q] [at LOC1 LOC2 ... LOCk / ] [from LOC1 to LOC2 by
% ** LOC_INCREMENT]
% ** See Subsection 3.2 of the manual for the rules.
% ** The various options of the tick field are processed by the
% ** \!nextkeyword command defined below.
% ** For example, `\!nextkeyword short ' expands to `\!ticksshort',
% ** while `\!nextkeyword withvalues' expands to `\!tickswithvalues'.
\def\!axisticks {%
\def\!nextkeyword##1 {%
\expandafter\ifx\csname !ticks##1\endcsname \relax
\def\!next{\!fixkeyword{##1}}%
\else
\def\!next{\csname !ticks##1\endcsname}%
\fi
\!next}%
\!axissetup
\def\!axissetup{\relax}%
\edef\!ticksinoutsign{\!ticksinoutSign}%
\!ticklength=\longticklength
\!tickwidth=\linethickness
\!gridlinestatus
\!setticktransform
\!maketick
\!tickcase=0
\def\!LTlist{}%
\!nextkeyword}
\def\ticksout{%
\def\!ticksinoutSign{+}}
\def\ticksin{%
\def\!ticksinoutSign{-}}
\ticksout
\def\gridlines{%
\def\!gridlinestatus{\!gridlinestootrue}}
\def\nogridlines{%
\def\!gridlinestatus{\!gridlinestoofalse}}
\nogridlines
\def\loggedticks{%
\def\!setticktransform{\let\!ticktransform=\!logten}}
\def\unloggedticks{%
\def\!setticktransform{\let\!ticktransform=\!donothing}}
\def\!donothing#1#2{\def#2{#1}}
\unloggedticks
% ** \!ticks/ : terminates read of tick options
\expandafter\def\csname !ticks/\endcsname{%
\!not {\ifx \!LTlist\empty}
\!placetickvalues
\fi
\def\!tickvalueslist{}%
\def\!LTlist{}%
\expandafter\csname !axis/\endcsname}
\def\!maketick{%
\setbox\!boxA=\hbox{%
\beginpicture
\!setdimenmode
\setcoordinatesystem point at {\!zpt} {\!zpt}
\linethickness=\!tickwidth
\ifdim\!ticklength>\!zpt
\putrule from {\!zpt} {\!zpt} to
{\!ticksinoutsign\!tickxsign\!ticklength}
{\!ticksinoutsign\!tickysign\!ticklength}
\fi
\if!gridlinestoo
\putrule from {\!zpt} {\!zpt} to
{-\!tickxsign\!xaxislength} {-\!tickysign\!yaxislength}
\fi
\endpicturesave <\!Xsave,\!Ysave>}%
\wd\!boxA=\!zpt}
\def\!ticksin{%
\def\!ticksinoutsign{-}%
\!maketick
\!nextkeyword}
\def\!ticksout{%
\def\!ticksinoutsign{+}%
\!maketick
\!nextkeyword}
\def\!tickslength<#1> {%
\!ticklength=#1\relax
\!maketick
\!nextkeyword}
\def\!tickslong{%
\!tickslength<\longticklength> }
\def\!ticksshort{%
\!tickslength<\shortticklength> }
\def\!tickswidth<#1> {%
\!tickwidth=#1\relax
\!maketick
\!nextkeyword}
\def\!ticksandacross{%
\!gridlinestootrue
\!maketick
\!nextkeyword}
\def\!ticksbutnotacross{%
\!gridlinestoofalse
\!maketick
\!nextkeyword}
\def\!tickslogged{%
\let\!ticktransform=\!logten
\!nextkeyword}
\def\!ticksunlogged{%
\let\!ticktransform=\!donothing
\!nextkeyword}
\def\!ticksunlabeled{%
\!tickcase=0
\!nextkeyword}
\def\!ticksnumbered{%
\!tickcase=1
\!nextkeyword}
\def\!tickswithvalues#1/ {%
\edef\!tickvalueslist{#1! /}%
\!tickcase=2
\!nextkeyword}
\def\!ticksquantity#1 {%
\ifnum #1>1
\!updatetickoffset
\!countA=#1\relax
\advance \!countA -1
\!ticklocationincr=\!axisLength
\divide \!ticklocationincr \!countA
\!ticklocation=\!axisstart
\loop \!not{\ifdim \!ticklocation>\!axisend}
\!placetick\!ticklocation
\ifcase\!tickcase
\relax % Case 0: no labels
\or
\relax % Case 1: numbered -- not available here
\or
\expandafter\!gettickvaluefrom\!tickvalueslist
\edef\!tickfield{{\the\!ticklocation}{\!value}}%
\expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
\fi
\advance \!ticklocation \!ticklocationincr
\repeat
\fi
\!nextkeyword}
\def\!ticksat#1 {%
\!updatetickoffset
\edef\!Loc{#1}%
\if /\!Loc
\def\next{\!nextkeyword}%
\else
\!ticksincommon
\def\next{\!ticksat}%
\fi
\next}
\def\!ticksfrom#1 to #2 by #3 {%
\!updatetickoffset
\edef\!arg{#3}%
\expandafter\!separate\!arg\!nil
\!scalefactor=1
\expandafter\!countfigures\!arg/
\edef\!arg{#1}%
\!scaleup\!arg by\!scalefactor to\!countE
\edef\!arg{#2}%
\!scaleup\!arg by\!scalefactor to\!countF
\edef\!arg{#3}%
\!scaleup\!arg by\!scalefactor to\!countG
\loop \!not{\ifnum\!countE>\!countF}
\ifnum\!scalefactor=1
\edef\!Loc{\the\!countE}%
\else
\!scaledown\!countE by\!scalefactor to\!Loc
\fi
\!ticksincommon
\advance \!countE \!countG
\repeat
\!nextkeyword}
\def\!updatetickoffset{%
\!dimenA=\!ticksinoutsign\!ticklength
\ifdim \!dimenA>\!offset
\!offset=\!dimenA
\fi}
\def\!placetick#1{%
\if!xswitch
\!xpos=#1\relax
\!ypos=\!axisylevel
\else
\!xpos=\!axisxlevel
\!ypos=#1\relax
\fi
\advance\!xpos \!Xsave
\advance\!ypos \!Ysave
\kern\!xpos\raise\!ypos\copy\!boxA\kern-\!xpos
\ignorespaces}
\def\!gettickvaluefrom#1 #2 /{%
\edef\!value{#1}%
\edef\!tickvalueslist{#2 /}%
\ifx \!tickvalueslist\!endtickvaluelist
\!tickcase=0
\fi}
\def\!endtickvaluelist{! /}
\def\!ticksincommon{%
\!ticktransform\!Loc\!t
\!ticklocation=\!t\!!unit
\advance\!ticklocation -\!!origin
\!placetick\!ticklocation
\ifcase\!tickcase
\relax % Case 0: no labels
\or % Case 1: numbered
\ifdim\!ticklocation<-\!!origin
\edef\!Loc{$\!Loc$}%
\fi
\edef\!tickfield{{\the\!ticklocation}{\!Loc}}%
\expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
\or % Case 2: labeled
\expandafter\!gettickvaluefrom\!tickvalueslist
\edef\!tickfield{{\the\!ticklocation}{\!value}}%
\expandafter\!listaddon\expandafter{\!tickfield}\!LTlist%
\fi}
\def\!separate#1\!nil{%
\!ifnextchar{-}{\!!separate}{\!!!separate}#1\!nil}
\def\!!separate-#1\!nil{%
\def\!sign{-}%
\!!!!separate#1..\!nil}
\def\!!!separate#1\!nil{%
\def\!sign{+}%
\!!!!separate#1..\!nil}
\def\!!!!separate#1.#2.#3\!nil{%
\def\!arg{#1}%
\ifx\!arg\!empty
\!countA=0
\else
\!countA=\!arg
\fi
\def\!arg{#2}%
\ifx\!arg\!empty
\!countB=0
\else
\!countB=\!arg
\fi}
\def\!countfigures#1{%
\if #1/%
\def\!next{\ignorespaces}%
\else
\multiply\!scalefactor 10
\def\!next{\!countfigures}%
\fi
\!next}
\def\!scaleup#1by#2to#3{%
\expandafter\!separate#1\!nil
\multiply\!countA #2\relax
\advance\!countA \!countB
\if -\!sign
\!countA=-\!countA
\fi
#3=\!countA
\ignorespaces}
\def\!scaledown#1by#2to#3{%
\!countA=#1\relax% ** get original #
\ifnum \!countA<0 % ** take abs value,
\def\!sign{-}% ** remember sign
\!countA=-\!countA
\else
\def\!sign{}%
\fi
\!countB=\!countA% ** copy |#|
\divide\!countB #2\relax% ** integer part (|#|/sf)
\!countC=\!countB% ** get sf * (|#|/sf)
\multiply\!countC #2\relax
\advance \!countA -\!countC% ** ctA is now remainder
\edef#3{\!sign\the\!countB.}% ** +- integerpart.
\!countC=\!countA % ** Tack on proper number
\ifnum\!countC=0 % ** of zeros after .
\!countC=1
\fi
\multiply\!countC 10
\!loop \ifnum #2>\!countC
\edef#3{#3\!zero}%
\multiply\!countC 10
\repeat
\edef#3{#3\the\!countA}% ** Add on rest of remainder
\ignorespaces}
\def\!placetickvalues{%
\advance\!offset \tickstovaluesleading
\if!xswitch
\setbox\!boxA=\hbox{%
\def\\##1##2{%
\!dimenput {##2} [B] (##1,\!axisylevel)}%
\beginpicture
\!LTlist
\endpicturesave <\!Xsave,\!Ysave>}%
\!dimenA=\!axisylevel
\advance\!dimenA -\!Ysave
\advance\!dimenA \!tickysign\!offset
\if -\!tickysign
\advance\!dimenA -\ht\!boxA
\else
\advance\!dimenA \dp\!boxA
\fi
\advance\!offset \ht\!boxA
\advance\!offset \dp\!boxA
\!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!zpt,\!dimenA)
\else
\setbox\!boxA=\hbox{%
\def\\##1##2{%
\!dimenput {##2} [r] (\!axisxlevel,##1)}%
\beginpicture
\!LTlist
\endpicturesave <\!Xsave,\!Ysave>}%
\!dimenA=\!axisxlevel
\advance\!dimenA -\!Xsave
\advance\!dimenA \!tickxsign\!offset
\if -\!tickxsign
\advance\!dimenA -\wd\!boxA
\fi
\advance\!offset \wd\!boxA
\!dimenput {\box\!boxA} [Bl] <\!Xsave,\!Ysave> (\!dimenA,\!zpt)
\fi}
\normalgraphs
\catcode`!=12 % ***** THIS MUST NEVER BE OMITTED
SHAR_EOF
if test -f 'Pictex/postpictex.tex'
then
echo shar: over-writing existing file "'Pictex/postpictex.tex'"
fi
cat << \SHAR_EOF > 'Pictex/postpictex.tex'
% This is postpictex.tex Version 1.1 9/10/87
% To use the PiCTeX macros under LaTeX, you first need to \input the
% file prepictex.tex, then the main corpus of PiCTeX macros (pictex.tex),
% and finally this file. Do not \input the file latexpicobjs.tex.
\catcode`@=11 \catcode`!=11
% Save meanings of PiCTeX keywords that duplicate LaTeX keywords
\let\!pictexendpicture=\endpicture
\let\!pictexframe=\frame
\let\!pictexlinethickness=\linethickness
\let\!pictexmultiput=\multiput
\let\!pictexput=\put
% Redefine the PiCTeX \beginpicture macro
\def\beginpicture{%
\setbox\!picbox=\hbox\bgroup%
\let\endpicture=\!pictexendpicture
\let\frame=\!pictexframe
\let\linethickness=\!pictexlinethickness
\let\multiput=\!pictexmultiput
\let\put=\!pictexput
\let\input=\@@input % \@@input is LaTeX's saved version of TeX's primitive
\!xleft=\maxdimen
\!xright=-\maxdimen
\!ybot=\maxdimen
\!ytop=-\maxdimen}
% Reestablish LaTeX's meaning of \frame. This makes
% PiCTeX's meaning of \frame available only inside a PiCture.
\let\frame=\!latexframe
% Make PiCTeX's meaning of \frame available everywhere in the
% guise of \pictexframe
\let\pictexframe=\!pictexframe
% Now do the same for \linethickness
\let\linethickness=\!latexlinethickness
\let\pictexlinethickness=\!pictexlinethickness
% Reset LaTeX's default meaning of \\
\let\\=\@normalcr
\catcode`@=12 \catcode`!=12
SHAR_EOF
if test -f 'Pictex/prepictex.tex'
then
echo shar: over-writing existing file "'Pictex/prepictex.tex'"
fi
cat << \SHAR_EOF > 'Pictex/prepictex.tex'
% This is prepictex.tex Version 1.1 9/10/87
% To use the PiCTeX macros under LaTeX, you first need to \input this
% file, then the main corpus of PiCTeX macros (pictex.tex), and then
% the file postpictex.tex. Do not \input the file latexpicobjs.tex.
\catcode`@=11 \catcode`!=11
% First of all, see if \fiverm is defined. If so do nothing;
% if not, let \fiverm take on meaning of LaTeX's \fivrm.
\expandafter\ifx\csname fiverm\endcsname\relax
\let\fiverm\fivrm
\fi
% Save meanings of LaTeX keywords that duplicate PiCTeX keywords
\let\!latexendpicture=\endpicture
\let\!latexframe=\frame
\let\!latexlinethickness=\linethickness
\let\!latexmultiput=\multiput
\let\!latexput=\put
% Redefine the LaTeX \@picture macro
\def\@picture(#1,#2)(#3,#4){%
\@picht #2\unitlength
\setbox\@picbox\hbox to #1\unitlength\bgroup
\let\endpicture=\!latexendpicture
\let\frame=\!latexframe
\let\linethickness=\!latexlinethickness
\let\multiput=\!latexmultiput
\let\put=\!latexput
\hskip -#3\unitlength \lower #4\unitlength \hbox\bgroup}
\catcode`@=12 \catcode`!=12
SHAR_EOF
# End of shell archive
exit 0