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