diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/pictex |
Initial commit
Diffstat (limited to 'graphics/pictex')
29 files changed, 9461 insertions, 0 deletions
diff --git a/graphics/pictex/README b/graphics/pictex/README new file mode 100644 index 0000000000..63ba8eaa02 --- /dev/null +++ b/graphics/pictex/README @@ -0,0 +1,11 @@ +The PiCTeX macro package is released under the LaTeX Project Public +License, version 1 or (at your option) any later version. + + +NOTE. There is a detailed manual for PiCTeX available from + Michael Wichura + Department of Statistics + University of Chicago. + + (312) 702-8329 + Wichura@Galton.Uchicago.EDU diff --git a/graphics/pictex/addon/00index b/graphics/pictex/addon/00index new file mode 100644 index 0000000000..81b80d1a41 --- /dev/null +++ b/graphics/pictex/addon/00index @@ -0,0 +1,16 @@ +PICTEX.STY
+ Style zum Einladen von PiCTeX als LaTeX-option oder LaTeX-Package.
+ Incl. Einladen von PICCORR.STY und PICMORE.STY, falls vorhanden.
+
+PICCORR.STY
+ Korrektur zu PiCTeXs \betweenarrows-Befehl
+
+PICMORE.STY
+ Erweiterung zu PiCTeX f"ur Impulsdiagramme
+
+PICTEXWD.TEX
+ Gepatchtes PICTEX.TEX, das weniger Dimensionsregister benutzt.
+ Fehlermeldungen an Andreas.Schrell@RS.maus.de
+
+PICTEXWD.STY
+ Wie PICTEX.STY, aber es wird PICTEXWD.TEX eingeladen.
diff --git a/graphics/pictex/addon/autoarea/ANNOUNCE.txt b/graphics/pictex/addon/autoarea/ANNOUNCE.txt new file mode 100644 index 0000000000..fa1d7034b5 --- /dev/null +++ b/graphics/pictex/addon/autoarea/ANNOUNCE.txt @@ -0,0 +1,24 @@ +SUMMARY: automatic bounding boxes with PiCTeX + +PiCTeX is a "generic" set of TeX macros for drawing diagrams and +pictures, dating from 1987, written and described by Michael J. Wichura. +The last extensions contributed by other authors may have occurred +1999. It may be difficult to find somebody who uses it today ... +yet two users asked me for help this year ... + +A new generic package `autoarea.sty' makes PiCTeX recognize lines +and arcs in determining the "bounding box" of a picture +(PiCTeX so far accounted for put commands only). +The "bounding box" is essential for proper placement of a picture +between running text and margins and for keeping the running text away. +Examples provided demonstrate what `autoarea.sty' does. + +Yes, it should suffice to load the package to have this effect. +Read additional instructions and informations in the file +`autoarea.sty'. + +`autoarea.sty' has been tested successfully on 42 geometric figures +from a work by medieval scholar N. Oresme, as reproduced by Dr. +Richard Lorch using PiCTeX. + + diff --git a/graphics/pictex/addon/autoarea/README b/graphics/pictex/addon/autoarea/README new file mode 120000 index 0000000000..d48b930fc0 --- /dev/null +++ b/graphics/pictex/addon/autoarea/README @@ -0,0 +1 @@ +README.aa
\ No newline at end of file diff --git a/graphics/pictex/addon/autoarea/README.aa b/graphics/pictex/addon/autoarea/README.aa new file mode 100644 index 0000000000..5ab324fe2f --- /dev/null +++ b/graphics/pictex/addon/autoarea/README.aa @@ -0,0 +1,14 @@ + File README.aa for + [tex-archive]/graphics/pictex/addon/autoarea/ + + +AUTOAREA.STY + makes PiCTeX's bounding boxes account for lines and arcs. + License is LPPL. Read the file for additional informations. + +AUTODEMO + this subdirectory demonstrates the effect of autoarea.sty . + + +________________________________________________________________________ +This file version 2008/04/25 Uwe Lueck, http://contact-ednotes.sty.de.vu diff --git a/graphics/pictex/addon/autoarea/autoarea.sty b/graphics/pictex/addon/autoarea/autoarea.sty new file mode 100644 index 0000000000..84aa0160a7 --- /dev/null +++ b/graphics/pictex/addon/autoarea/autoarea.sty @@ -0,0 +1,220 @@ +%% Macro package `autoarea.sty', supporting but not needing LaTeX2e, +%% copyright (C) 2008 Uwe Lueck [L\"uck] +%% http://www.contact-ednotes.sty.de.vu +%% - author-maintained, extending PiCTeX: + +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname ProvidesPackage\endcsname\relax\else + % german.sty trick + \ProvidesPackage{autoarea}[2008/08/12 v0.3a + automatic accounting for PiCTeX lines and arcs] + % +\fi + +% LEGAL/CONTACT +% +%% This file can be redistributed and/or modified under the terms +%% of the LaTeX Project Public License, version 1.3c or later, cf. +%% http://www.latex-project.org/lppl.txt +%% -- NO WARRANTY! Please report bugs, problems, and suggestions via +%% http://www.contact-ednotes.sty.de.vu + +% FEATURES/USAGE +% +% This is an experimental package for use with pictex[wd].sty/.tex. +% It works with LaTeX2e as well as with Plain TeX or LaTeX2.09. +% It is "experimental" in that it has come from a mixture of knowing +% PiCTeX internals and guesses that surprisingly seem to work. +% +% PiCTeX's \plot, \circulararc and \ellipticalarc normally don't contribute to +% proper placement of the picture between text and margins, which may result +% in pictures overlapping with text or in uneven distances to text margins. +% You should find a file autodemo-.pdf nearby that illustrates how this may +% look. +% +% In such cases, the document author must use PiCTeX's \setplotarea to correct +% this manually, determining the "bounding box" (cf. documentation as indicated +% after \endinput below). PiCTeX's \put, on the opposite, normally DOES +% contribute to PiCTeX's automatical calculation of the boundaries. +% +% autoarea.sty tries to determine the bounding box even for lines and arcs +% automatically instead, so you can omit \setplotarea (at least for this +% purpose). You just have to load it (we hope) after pictex[wd].sty/.tex, by, +% e.g., +% +% \usepackage{pictexwd,autoarea} +% or +% \input pictexwd +% \input autoarea.sty +% +% The package defines just three user commands \plottedat, \autoaccountingoff, +% and \autoaccountingon - which you perhaps won't need, just loading the +% package may suffice. The samples autodemo-.pdf and autodemo+.pdf nearby both +% were generated by omitting \setplotarea, the difference being that +% autodemo+.pdf profits from \usepackage{autoarea}, which may convince you +% that it's worth trying autoarea. +% +% \plottedat XMIN YMIN \plottedat XMAX YMAX may (otherwise) replace +% \setplotarea x from XMIN to XMAX, y from YMIN to YMAX +% A single "\plottedat ..." may suffice if other \put commands +% contribute to proper placement of the picture sufficiently already. + + \expandafter %% ersatz-\newcommand if without LaTeX + \ifx \csname newcommand\endcsname \relax + \def\newcommand#1{\def#1} \fi + +\newcommand{\plottedat}{\put {} at } + +% (If the user doesn't want it, we still need it here!) +% +% Should a \plot or \circulararc command seem to produce more space than +% you want, put it between \autoaccountingoff and \autoaccountingon, +% then try \plottedat and \setplotarea if needed. +% +% Our trick will account for starting, ending, or corner points of curves. +% This may not suffice in general (e.g., with \setquadratic), +% then you still may need \plottedat or \setplotarea. Below \endinput you +% find more on CAVEATS etc. + +% INTERNALS + +\catcode`\!=11 % use and change PiCTeX internals + +\let\PT!!start\!start \let\PT!!ljoin\!ljoin \let\PT!!qjoin\!qjoin +\def\PTaa!start (#1,#2){\plottedat #1 #2 \PT!!start (#1,#2)} +\def\PTaa!ljoin (#1,#2){\plottedat #1 #2 \PT!!ljoin (#1,#2)} +\def\PTaa!qjoin (#1,#2) (#3,#4){% + \plottedat #1 #2 \plottedat #3 #4 \PT!!qjoin (#1,#2) (#3,#4)} + +\expandafter\ifx\csname newcommand\endcsname \def\newcommand#1{\def#1} \fi + +\newcommand{\autoaccountingon}{% + \let\!start\PTaa!start \let\!ljoin\PTaa!ljoin \let\!qjoin\PTaa!qjoin} + +\newcommand{\autoaccountingoff}{% + \let\!start\PT!!start \let\!ljoin\PT!!ljoin \let\!qjoin\PT!!qjoin} + +\catcode`\!=12 + +\autoaccountingon % turns on automatic accounting for lines and arcs. + +\endinput %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +CAVEATS + +1. I won't try to find out whether autoarea.sty makes \setplotarea entirely +superfluous: will drawing a coordinate system work without \setplotarea? + +2. Certainly it was not due to dullness that PiCTeX didn't provide autoarea's +feature originally. Around 1990, it was important to care for speed with PiCTeX +(and it may still be, I won't try complex examples). +Apart from up to four, line and arc commands are irrelevant for placing the +picture correctly. About the same holds for put commands, and that's why PiCTeX +has \accountingoff and \accountingon to ignore many of them. Our \autoaccountingoff +and \autoaccountingon serve the analoguous purpose for line and arc commands. + +3. I don't know exactly how arc commands work, therefore I wouldn't be astonished +if the result still is not properly centered. Our trick is take account of some +points all of which an approximating curve must meet. Can that curve bend out of +the bounding rectangle of those points? + + +ACKNOWLEDGEMENTS + +This work has been supported by edition projects at the Institute for +the History of the Sciences directed by Prof. Dr. Menso Folkerts. +Thanks to Dr. Richard Lorch for introducing me to the subject. + + + +CHANGE HISTORY + +v0.1 2008/02/14 Working, addressed compatibility with ArabTeX. +v0.2 2008/02/14a Moved compatibility to lorchpic.sty. + This one submitted to CTAN, soon kind of withdrawn. +v0.3 2008/04/19 Made generic, expanded prose. + 2008/04/25 `Lueck', not `Lück', for UNIX etc. + 2008/05/07 ersatz-\newcommand earlier, typo; + removed remarks on PiCTeX documentation. + 2008/05/08 Added version numbers, corrected ersatz-\newcommand; + uploaded in pictex_may_2008.zip - in vain. +v0.3a 2008/08/12 typo fix "too text" -> "to text". + +_________________________________________________________________________ + +FORMER VERSION 2008/02/13 (ul, 2008/02/14): + +I couldn't find a working redefinition of \circulararc +("Use of \ellipticalarc doesn't match its definition"); +on the other hand its internals seem to the job all ready; +and my redefinition seemed to raise further difficulties. +Here's what I had tried before: + +% \circulararc may do the trick for full circles (360 degree) only. +% CAVEAT: assumes that x and y units are the same. +% Otherwise or when something else goes wrong, put \circulararc between +% \autoaccountingarcoff and \autoaccountingarcon. +% +% These features come from the start if you load the present package. + +\catcode`\!=11 % use and change PiCTeX internals + +\let\PT@@start\!start \let\PT@@ljoin\!ljoin \let\PT@@qjoin\!qjoin +\def\PTaa@start (#1,#2){\plottedat #1 #2 \PT@@start (#1,#2)} +\def\PTaa@ljoin (#1,#2){\plottedat #1 #2 \PT@@ljoin (#1,#2)} +\def\PTaa@qjoin (#1,#2) (#3,#4){% + \plottedat #1 #2 \plottedat #3 #4 \PT@@qjoin (#1,#2) (#3,#4)} + +\let\PT@@circulararc\circulararc +\def\PTaa@circulararc #1 degrees from #2 #3 center at #4 #5 {% + \ifnum #1=360 + \!dimenE=#2pt \advance\!dimenE-#4pt + \!dimenF=#2pt \advance\!dimenF-#4pt + \!Pythag\!dimenE\!dimenF\!dimenG + \PTaa@plotcorner{#4}{#5}{-}% + \PTaa@plotcorner{#4}{#5}{}% + \fi + % \PT@@circulararc #1 degrees from #2 #3 center at #4 #5 + %\PT@@circulararc #1 degrees from #2 #3 center at #4 #5 } + \ellipticalarc axes ratio 1:1 360 degrees from 0 25 center at 0 0 } + %\ellipticalarc axes ratio 1:1 #1 degrees from #2 #3 center at #4 #5 } +\def\PTaa@plotcorner#1#2#3{% + \!dimenE#1pt \!dimenF#2pt + \advance\!dimenE#3\!dimenG \advance\!dimenF#3\!dimenG + \!removept\!dimenE\@tempa \!removept\!dimenF\@tempb + \edef\@tempc{\noexpand\plottedat \@tempa\space\@tempb}% + \@tempc +} +% <-: +% 1. May be \!qjoin of \ellipticalarc does the trick already. +% 2. FUTURE: \accountingcircle[tbrl] if circle isn't full. +% 3. CAVEAT: May not work in dimension mode. +% 4. May be improvable with better knowledge of internals than mine. + +\newcommand{\autoaccountingon}{% + \let\!start\PTaa@start \let\!ljoin\PTaa@ljoin \let\!qjoin\PTaa@qjoin + \autoaccountingarcon} +\newcommand{\autoaccountingarcon}{\let\circulararc\PTaa@circulararc} +\newcommand{\autoaccountingoff}{% + \let\!start\PT@@start \let\!ljoin\PT@@ljoin \let\!qjoin\PT@@qjoin + % <- Yet I can't imagine why this could be needed, just in case ... + \autoaccountingarcoff} +\newcommand{\autoaccountingarcoff}{\let\circulararc\PT@@circulararc} + +% \setnone FROM ARABTEX SUFFICES INSTEAD OF: +% +% COMPATIBILITY WITH ARABTEX ETC. +% +% ArabTeX and possibly other packages may disable PiCTeX commands +% using "<...,...>" syntax, notably \setcoordinatesystem units <1mm,1mm> etc. +%% TODO: TeX error: +% Precede such a command (if it breaks) with \restoreanglesyntax, +% best after \beginpicture to avoid disabling the other package. + +\newcommand{\restoreanglesyntax}{\@makeother\<\@makeother\>} + +%% todo: or better "compatibility" package ptangles.sty introducing +%% syntax without <...>!? + +%%% end of file diff --git a/graphics/pictex/addon/autoarea/autodemo/README.autodemo b/graphics/pictex/addon/autoarea/autodemo/README.autodemo new file mode 100644 index 0000000000..39b8f0abda --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/README.autodemo @@ -0,0 +1,26 @@ + File README.autodemo for + [tex-archive]/graphics/pictex/addon/autoarea/autodemo/ + + +AUTODEMO.TEX + + contains a sample of code for a PiCTeX picture placed in the + middle running text on one page. + +AUTODEMO-.TEX + + runs AUTODEMO.TEX without loading AUTOAREA.STY. The outcome is + + AUTODEMO-.PDF + +AUTODEMO+.TEX + + runs AUTODEMO.TEX after loading AUTOAREA.STY. The outcome is + + AUTODEMO+.PDF + +Print both pages and watch them side by side. + + +________________________________________________________________________ +This file version 2008/04/25 Uwe Lueck, http://contact-ednotes.sty.de.vu diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo+.log b/graphics/pictex/addon/autoarea/autodemo/autodemo+.log new file mode 100644 index 0000000000..4943212fba --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo+.log @@ -0,0 +1,82 @@ +This is pdfTeX, Version 3.141592-1.40.4 (MiKTeX 2.7) (preloaded format=pdflatex 2008.2.19) 7 MAY 2008 22:29 +entering extended mode +**autodemo+.tex +(autodemo+.tex +LaTeX2e <2005/12/01> +Babel <v3.8h> and hyphenation patterns for english, dumylang, nohyphenation, ge +rman, ngerman, french, loaded. +File: autodemo+.tex 2008/04/19 autoarea.sty's effect +(autodemo.tex +File: autodemo.tex 2008/04/19 common sample for autoarea.sty + ("C:\Programme\MiKTeX 2.7\tex\latex\base\article.cls" +Document Class: article 2005/09/16 v1.4f Standard LaTeX document class +("C:\Programme\MiKTeX 2.7\tex\latex\base\size12.clo" +File: size12.clo 2005/09/16 v1.4f Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\pictex.sty" +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\prepictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\pictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\postpictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\picmore.tex")) +("C:\Programme\MiKTeX 2.7\tex\latex\lipsum\lipsum.sty" +Package: lipsum 2005/01/26 v1.0 150 paragraphs of Lorem Ipsum dummy text +File: lipsum.dtx 2005/01/26 v1.0 150 paragraphs of Lorem Ipsum dummy text +\c@lips@count=\count103 +) (autoarea.sty +Package: autoarea 2008/05/07 automatic accounting for PiCTeX lines and arcs +) +No auxiliary output files. + +No file autodemo+.aux. +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <12> on input line 10. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line 10. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line 10. +[1 + +{C:/Dokumente und Einstellungen/akuehne/Lokale Einstellungen/Anwendungsdaten/Mi +KTeX/2.7/pdftex/config/pdftex.map}] ) ) +Here is how much of TeX's memory you used: + 1061 strings out of 95340 + 10992 string characters out of 1184281 + 171027 words of memory out of 1500000 + 4300 multiletter control sequences out of 110000 + 7336 words of font info for 26 fonts, out of 1200000 for 2000 + 14 hyphenation exceptions out of 8191 + 23i,4n,21p,256b,229s stack positions out of 5000i,500n,10000p,200000b,5000s +<C:/Programme/MiKTeX 2.7/fonts/type1/blu +esky/cm/cmbxti10.pfb><C:/Programme/MiKTeX 2.7/fonts/type1/bluesky/cm/cmr12.pfb> +<C:/Programme/MiKTeX 2.7/fonts/type1/bluesky/cm/cmr5.pfb><C:/Programme/MiKTeX 2 +.7/fonts/type1/bluesky/cm/cmssbx10.pfb> +Output written on autodemo+.pdf (1 page, 24873 bytes). +PDF statistics: + 22 PDF objects out of 1000 (max. 8388607) + 0 named destinations out of 1000 (max. 131072) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo+.pdf b/graphics/pictex/addon/autoarea/autodemo/autodemo+.pdf Binary files differnew file mode 100644 index 0000000000..4ceb8ed8c8 --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo+.pdf diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo+.tex b/graphics/pictex/addon/autoarea/autodemo/autodemo+.tex new file mode 100644 index 0000000000..e59401a480 --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo+.tex @@ -0,0 +1,4 @@ +\ProvidesFile{autodemo+.tex}[2008/04/19 autoarea.sty's effect] +\newcommand{\autouse}{\usepackage{autoarea}} +\newcommand{\autofoot}{loaded autoarea.sty -- circle centered} +\input autodemo
\ No newline at end of file diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo-.log b/graphics/pictex/addon/autoarea/autodemo/autodemo-.log new file mode 100644 index 0000000000..454cccbfff --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo-.log @@ -0,0 +1,80 @@ +This is pdfTeX, Version 3.141592-1.40.4 (MiKTeX 2.7) (preloaded format=pdflatex 2008.2.19) 7 MAY 2008 22:28 +entering extended mode +**autodemo-.tex +(autodemo-.tex +LaTeX2e <2005/12/01> +Babel <v3.8h> and hyphenation patterns for english, dumylang, nohyphenation, ge +rman, ngerman, french, loaded. +File: autodemo-.tex 2008/04/19 what's missing without autoarea.sty +(autodemo.tex +File: autodemo.tex 2008/04/19 common sample for autoarea.sty + ("C:\Programme\MiKTeX 2.7\tex\latex\base\article.cls" +Document Class: article 2005/09/16 v1.4f Standard LaTeX document class +("C:\Programme\MiKTeX 2.7\tex\latex\base\size12.clo" +File: size12.clo 2005/09/16 v1.4f Standard LaTeX file (size option) +) +\c@part=\count79 +\c@section=\count80 +\c@subsection=\count81 +\c@subsubsection=\count82 +\c@paragraph=\count83 +\c@subparagraph=\count84 +\c@figure=\count85 +\c@table=\count86 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\pictex.sty" +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\prepictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\pictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\postpictex.tex") +("C:\Programme\MiKTeX 2.7\tex\generic\pictex\picmore.tex")) +("C:\Programme\MiKTeX 2.7\tex\latex\lipsum\lipsum.sty" +Package: lipsum 2005/01/26 v1.0 150 paragraphs of Lorem Ipsum dummy text +File: lipsum.dtx 2005/01/26 v1.0 150 paragraphs of Lorem Ipsum dummy text +\c@lips@count=\count103 +) +No auxiliary output files. + +No file autodemo-.aux. +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 8. +LaTeX Font Info: ... okay on input line 8. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <12> on input line 10. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line 10. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line 10. +[1 + +{C:/Dokumente und Einstellungen/akuehne/Lokale Einstellungen/Anwendungsdaten/Mi +KTeX/2.7/pdftex/config/pdftex.map}] ) ) +Here is how much of TeX's memory you used: + 1046 strings out of 95340 + 10812 string characters out of 1184281 + 171053 words of memory out of 1500000 + 4288 multiletter control sequences out of 110000 + 7336 words of font info for 26 fonts, out of 1200000 for 2000 + 14 hyphenation exceptions out of 8191 + 23i,4n,19p,256b,207s stack positions out of 5000i,500n,10000p,200000b,5000s +<C:/Programme/MiKTeX 2.7/fonts/type1/blu +esky/cm/cmbxti10.pfb><C:/Programme/MiKTeX 2.7/fonts/type1/bluesky/cm/cmr12.pfb> +<C:/Programme/MiKTeX 2.7/fonts/type1/bluesky/cm/cmr5.pfb><C:/Programme/MiKTeX 2 +.7/fonts/type1/bluesky/cm/cmssbx10.pfb> +Output written on autodemo-.pdf (1 page, 25493 bytes). +PDF statistics: + 22 PDF objects out of 1000 (max. 8388607) + 0 named destinations out of 1000 (max. 131072) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo-.pdf b/graphics/pictex/addon/autoarea/autodemo/autodemo-.pdf Binary files differnew file mode 100644 index 0000000000..03887de455 --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo-.pdf diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo-.tex b/graphics/pictex/addon/autoarea/autodemo/autodemo-.tex new file mode 100644 index 0000000000..3512c1d65a --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo-.tex @@ -0,0 +1,5 @@ +\ProvidesFile{autodemo-.tex}[2008/04/19 what's missing without autoarea.sty] +\newcommand{\autouse}{\relax} +\newcommand{\autofoot}{didn't load autoarea.sty -- + {\bf \textit{X}} centered, circle ignored} +\input autodemo
\ No newline at end of file diff --git a/graphics/pictex/addon/autoarea/autodemo/autodemo.tex b/graphics/pictex/addon/autoarea/autodemo/autodemo.tex new file mode 100644 index 0000000000..e033f3ff52 --- /dev/null +++ b/graphics/pictex/addon/autoarea/autodemo/autodemo.tex @@ -0,0 +1,17 @@ +\ProvidesFile{autodemo.tex}[2008/04/19 common sample for autoarea.sty] +\documentclass[12pt]{article} +\usepackage{pictex,lipsum} +\autouse +\pagestyle{plain} +\renewcommand{\thepage}{\bfseries \sffamily \autofoot} +\nofiles +\begin{document} +\lipsum[1] +\[\beginpicture +\setcoordinatesystem units <1mm,1mm> point at 0 0 +% \setplotarea x from -35 to 35, y from -35 to 35 %% compare to autoarea.sty +\circulararc 360 degrees from 0 35 center at 0 0 +\put {\textbf{\itshape X}} at -20 20 +\endpicture\] +\lipsum[2] +\end{document} diff --git a/graphics/pictex/addon/piccorr.sty b/graphics/pictex/addon/piccorr.sty new file mode 100644 index 0000000000..d0658aeaf0 --- /dev/null +++ b/graphics/pictex/addon/piccorr.sty @@ -0,0 +1,118 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% Correction to PiCTeX 1.1 9/21/87 % +% by Andreas Schrell, Wuppertal, FRG, 9/30/91 % +% % +% The bug forces wrong height and position of the % +% vertical \betweenarrows - structure if the % +% coordinate difference is negative. % +% You can search for ERROR in this file. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +{\catcode`!=11 + +\global +\def\betweenarrows #1#2 from #3 #4 to #5 #6 {% + \!xloc=\!M{#3}\!xunit \!xxloc=\!M{#5}\!xunit% + \!yloc=\!M{#4}\!yunit \!yyloc=\!M{#6}\!yunit% + \!dxpos=\!xxloc \advance\!dxpos by -\!xloc + \!dypos=\!yyloc \advance\!dypos by -\!yloc + \advance\!xloc .5\!dxpos + \advance\!yloc .5\!dypos +% + \let\!MBA=\!M% ** save current coord\dimen mode + \!setdimenmode% ** express locations in dimens + \ifdim\!dypos=\!zpt + \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi + \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc} + \else + \ifdim\!dxpos=\!zpt +% \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi +% ^^^^^ ERROR! + \ifdim\!dypos<\!zpt \!dypos=-\!dypos \fi +% ^^^^^^^ CORRECTION! + \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc} + \fi + \fi + \let\!M=\!MBA% ** restore previous c/d mode + \ignorespaces} + + +% correction added by Robin Fairbairns (rf10@cam.ac.uk) 1999/09/14 + +\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}% WRONG +% ^^^^^^^^ + \!dimenA=#2\relax \edef\!ymidpt{\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} +} + +\endinput + diff --git a/graphics/pictex/addon/picmore.tex b/graphics/pictex/addon/picmore.tex new file mode 100644 index 0000000000..b6cec46a3a --- /dev/null +++ b/graphics/pictex/addon/picmore.tex @@ -0,0 +1,76 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% PiCTeX Erweiterungen von Andreas Schrell %
+% Windhoevel 2 %
+% 5600 Wuppertal 2 %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Version 1.0 29.10.1989 %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Befehle fr die Benutzer:
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \setsignal zur Benutzung wie \setlinear %
+% \plot erzeugt danach Signalverlaeufe%
+% fuer Impulsdiagramme. Es werden TeX-%
+% Linien benutzt, daher schneller als %
+% \plot mit \setlinear %
+% Bsp: %
+% \setsignal \plot 0 1 1 0 2 1 4 0 7 1 8 0 / %
+% erzeugt %
+% 0 1 2 3 4 5 6 7 8 %
+% __ ___ _ %
+% ! ! ! ! ! %
+% !_! !_____! ! %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \setmsignal zur Benutzung wie \setlinear %
+% \plot erzeugt danach Signalverlaeufe%
+% fuer Impulsdiagramme. Es werden TeX-%
+% Linien benutzt, daher schneller als %
+% \plot mit \setlinear %
+% Bsp: %
+% \setmsignal \plot 0 1 1 2 2 4 3 6 0 7 1 1 %
+% erzeugt %
+% 0 1 2 3 4 5 6 7 8 %
+% --- %
+% ! ! %
+% - ! %
+% --! ! - %
+% !___! %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\catcode`!=11
+
+\def\setsignal{%
+ \let\!drawcurve=\!scurve}
+
+\def\!scurve #1 #2 {%
+ \edef\!hxS{#1}%
+ \edef\!hyS{#2}%
+ \!sjoin}
+
+\def\!sjoin#1 #2 {%
+ \putrule from {\!hxS} {\!hyS} to {#1} {\!hyS}
+ \putrule from {#1} {\!hyS} to {#1} {#2}
+ \edef\!hxS{#1}%
+ \edef\!hyS{#2}%
+ \!ifnextchar/{\!finish}{\!sjoin}}
+
+
+\def\setmsignal{%
+ \let\!drawcurve=\!smcurve}
+
+\def\!smcurve #1 #2 #3 {%
+ \edef\!hxS{#2}%
+ \edef\!hyS{#3}%
+ \putrule from {#1} {\!hyS} to {\!hxS} {\!hyS}
+ \!smjoin}
+
+\def\!smjoin#1 #2 {%
+ \putrule from {\!hxS} {\!hyS} to {\!hxS} {#2}
+ \putrule from {\!hxS} {#2} to {#1} {#2}
+ \edef\!hxS{#1}%
+ \edef\!hyS{#2}%
+ \!ifnextchar/{\!finish}{\!smjoin}}
+
+\catcode`!=12
+
diff --git a/graphics/pictex/addon/pictex.sty b/graphics/pictex/addon/pictex.sty new file mode 100644 index 0000000000..d64c99790a --- /dev/null +++ b/graphics/pictex/addon/pictex.sty @@ -0,0 +1,17 @@ +\def\fileversion{1.0}
+\def\filedate{1994/03/31}
+
+% PiCTeX als LaTeX-Style oder LaTeX2e-Package einladen.
+% von Andreas Schrell
+
+\ifx\fiverm\undefined
+ \newfont\fiverm{cmr5}
+\fi
+\input prepictex
+\input pictex
+\input postpictex
+\catcode`\@=11
+\@input{picmore.tex}
+\@input{piccorr.sty}
+
+\endinput
diff --git a/graphics/pictex/addon/pictexwd.sty b/graphics/pictex/addon/pictexwd.sty new file mode 100644 index 0000000000..42edb401e0 --- /dev/null +++ b/graphics/pictex/addon/pictexwd.sty @@ -0,0 +1,19 @@ +\def\fileversion{1.0}
+\def\filedate{1994/03/31}
+
+% PiCTeX als LaTeX-Style oder LaTeX2e-Package einladen. Allerdings
+% wird eine Datei pictexwd.tex geladen, die weniger Dimensionsregister
+% benutzt.
+%
+% Style von Andreas Schrell
+
+\ifx\fiverm\undefined
+ \newfont\fiverm{cmr5}
+\fi
+\input prepictex
+\input pictexwd
+\input postpictex
+\catcode`\@=11
+\@input{picmore.tex}
+\@input{piccorr.sty}
+\endinput
diff --git a/graphics/pictex/addon/pictexwd.tex b/graphics/pictex/addon/pictexwd.tex new file mode 100644 index 0000000000..43141efe6b --- /dev/null +++ b/graphics/pictex/addon/pictexwd.tex @@ -0,0 +1,3677 @@ +% G"andertes PiCTeX.TEX mit weniger Dimensionsregistern %
+% von Andreas Schrell, ohne Gew"ahr!!!!!!!
+% Version 0.0 vom 31.03.1994
+% FEHLERMELDUNGEN an Andreas.Schrell@RS.maus.de
+
+% This is PiCTeXWD, Version 1.1 9/21/87
+
+% CAVEAT: The PiCTeX manual often has a more lucid explanation
+% of any given topic than you will find in the internal documentation
+% of the macros.
+
+% PiCTeX's commands can be classified into two groups: (1) public (or
+% external), and (2) private (or internal). The public macros are
+% discussed at length in the manual. The only discussion of the private
+% macros is the internal documentation. The private macros all have
+% names beginning with an exclamation point (!) of category code 11.
+% Since in normal usage "!" has category code 12, these macros can't
+% be accessed or modified by the general user.
+
+% The macros are organized into thematically related groups. For example,
+% the macros dealing with dots & dashes are all in the DASHPATTERN group.
+% The table below shows which macros are in which groups. The table
+% covers all public macros, and many (but not all) of PiCTeX's upper level
+% private macros. Following the table, the various groups are listed
+% in the order in which they appear in the table.
+
+% *********************** TABLE OF GROUPS OF MACROS **********************
+
+% HACKS: Utility macros
+% \PiC
+% \PiCTeX
+% \placevalueinpts
+% \!!loop
+% \!cfor
+% \!copylist
+% \!ecfor
+% \!etfor
+% \!getnext
+% \!getnextvalueof
+% \!ifempty
+% \!ifnextchar
+% \!leftappend
+% \!listaddon
+% \!loop
+% \!lop
+% \!mlap
+% \!not
+% \!removept
+% \!rightappend
+% \!tfor
+% \!vmlap
+% \!wlet
+
+% ALLOCATION: Allocates registers
+
+% AREAS: Deals with plot areas
+% \axis
+% \grid
+% \invisibleaxes
+% \normalgraphs
+% \plotheading
+% \setplotarea
+% \visibleaxes
+
+% ARROWS: Draws arrows
+% \arrow
+% \betweenarrows
+
+% BARS: Draws bars
+% \putbar
+% \setbars
+
+% BOXES: Draws rectangles
+% \frame
+% \putrectangle
+% \rectangle
+% \shaderectangleson
+% \shaderectanglesoff
+
+% CURVES: Upper level plot commands
+% \hshade
+% \plot
+% \sethistograms
+% \setlinear
+% \setquadratic
+% \vshade
+
+% DASHPATTERNS: Sets up dash patterns
+% \findlength
+% \setdashes
+% \setdashesnear
+% \setdashpattern
+% \setdots
+% \setdotsnear
+% \setsolid
+% \!dashingoff
+% \!dashingon
+
+% DIVISION: Does long division of dimension registers
+% \Divide
+% \!divide
+
+% ELLIPSES: Draws ellipses and circles
+% \circulararc
+% \ellipticalarc
+
+% RULES: Draws rules, i.e., horizontal & vertical lines
+% \putrule
+% \!putdashedhline
+% \!putdashedvline
+% \!puthline
+% \!putsolidhline
+% \!putsolidvline
+% \!putvline
+
+% LINEAR ARC: Draws straight lines -- solid and dashed
+% \inboundscheckoff
+% \inboundscheckon
+% \!advancedashing
+% \!drawlinearsegment
+% \!initinboundscheck
+% \!linearsolid
+% \!lineardashed
+% \!ljoin
+% \!plotifinbounds
+% \!start
+
+% LOGTEN: Log_10 function
+% \!logten
+
+% PICTURES: Basic setups for PiCtures; \put commands
+% \accountingoff
+% \accountingon
+% \beginpicture
+% \endpicture
+% \endpicturesave
+% \lines
+% \multiput
+% \put
+% \setcoordinatemode
+% \setcoordinatesystem
+% \setdimensionmode
+% \stack
+% \Lines
+% \Xdistance
+% \Ydistance
+% \!dimenput
+% \!ifcoordmode
+% \!ifdimenmode
+% \!setcoordmode
+% \!setdimenmode
+% \!setputobject
+
+% PLOTTING: Things to do with plotting
+% \dontsavelinesandcurves
+% \replot
+% \savelinesandcurves
+% \setplotsymbol
+% \writesavefile
+% \!plot
+
+% PYTHAGORAS: Euclidean distance function
+% \placehypotenuse
+% \!Pythag
+
+% QUADRATIC ARC: Draws a quadratic arc
+% \!qjoin
+
+% ROTATIONS: Handles rotations
+% \startrotation
+% \stoprotation
+% \!rotateaboutpivot
+% \!rotateonly
+
+% SHADING: Handles shading
+% \setshadegrid
+% \setshadesymbol
+% \!lshade
+% \!qshade
+% \!starthshade
+% \!startvshade
+
+% TICKS: Draws ticks on graphs
+% \gridlines
+% \loggedticks
+% \nogridlines
+% \ticksin
+% \ticksout
+% \unloggesticks
+
+% ***************** END OF TABLE OF GROUPS OF MACROS ********************
+
+
+\catcode`!=11 % ***** THIS MUST NEVER BE OMITTED
+% *******************************
+% *** HACKS (Utility macros) ***
+% *******************************
+
+% ** User commands
+% ** \PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
+% ** \PiCTeX{\PiC\kern-.11em\TeX}
+% ** \placevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
+
+% ** Internal commands
+% ** \!ifnextchar{CHARACTER}{TRUE ACTION}{FALSE ACTION}
+% ** \!tfor NAME := LIST \do {BODY}
+% ** \!etfor NAME:= LIST \do {BODY}
+% ** \!cfor NAME := LIST \do {BODY}
+% ** \!ecfor NAME:= LIST \do {BODY}
+% ** \!ifempty{MACRO}{TRUE ACTION}{FALSE ACTION}
+% ** \!getnext\\ITEMfrom\LIST
+% ** \!getnextvalueof\DIMEN\from\LIST
+% ** \!copylist\LISTMACRO_A\to\LISTMACRO_B
+% ** \!wlet\CONTROL_SEQUENCE_A=\CONTROL_SEQUENCE_B
+% ** \!listaddon ITEM LIST
+% ** \!rightappendITEM\withCS\to\LISTMACRO
+% ** \!leftappendITEM\withCS\to\LISTMACRO
+% ** \!lop\LISTMACRO\to\ITEM
+% ** \!loop ... repeat
+% ** \!!loop ... repeat
+% ** \!removept{DIMENSION REGISTER}{CONTROL SEQUENCE}
+% ** \!mlap{...}
+% ** \!vmlap{...}
+% ** \!not{TEK if-CONDITION}
+
+% ** First, here are the the PiCTeX logo, and the syllable PiC:
+\def\PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC}
+\def\PiCTeX{\PiC\kern-.11em\TeX}
+
+% ** The following macro expands to parameter #2 or parameter #3 according to
+% ** whether the next non-blank character following the macro is or is not #1.
+% ** Blanks following the macro are gobbled.
+\def\!ifnextchar#1#2#3{%
+ \let\!testchar=#1%
+ \def\!first{#2}%
+ \def\!second{#3}%
+ \futurelet\!nextchar\!testnext}
+\def\!testnext{%
+ \ifx \!nextchar \!spacetoken
+ \let\!next=\!skipspacetestagain
+ \else
+ \ifx \!nextchar \!testchar
+ \let\!next=\!first
+ \else
+ \let\!next=\!second
+ \fi
+ \fi
+ \!next}
+\def\\{\!skipspacetestagain}
+ \expandafter\def\\ {\futurelet\!nextchar\!testnext}
+\def\\{\let\!spacetoken= } \\ % ** set \spacetoken to a space token
+
+
+% ** Borrow the "tfor" macro from Latex:
+% ** \!tfor NAME := LIST \do {BODY}
+% ** if, before expansion, LIST = T1 ... Tn, where each Ti is a token
+% ** or {...}, then executes BODY n times, with NAME = Ti on the
+% ** i-th iteration. Works for n=0.
+\def\!tfor#1:=#2\do#3{%
+ \edef\!fortemp{#2}%
+ \ifx\!fortemp\!empty
+ \else
+ \!tforloop#2\!nil\!nil\!!#1{#3}%
+ \fi}
+\def\!tforloop#1#2\!!#3#4{%
+ \def#3{#1}%
+ \ifx #3\!nnil
+ \let\!nextwhile=\!fornoop
+ \else
+ #4\relax
+ \let\!nextwhile=\!tforloop
+ \fi
+ \!nextwhile#2\!!#3{#4}}
+
+
+% ** \!etfor NAME:= LIST\do {BODY}
+% ** This is like \!cfor, but LIST is any balanced token list whose complete
+% ** expansion has the form T1 ... Tn
+\def\!etfor#1:=#2\do#3{%
+ \def\!!tfor{\!tfor#1:=}%
+ \edef\!!!tfor{#2}%
+ \expandafter\!!tfor\!!!tfor\do{#3}}
+
+
+% ** modify the Latex \tfor (token-for) loop to a \cfor (comma-for) loop.
+% ** \!cfor NAME := LIST \do {BODY}
+% ** if, before expansion, LIST = a1,a2,...an, then executes BODY n times,
+% ** with NAME = ai on the i-th iteration. Works for n=0.
+\def\!cfor#1:=#2\do#3{%
+ \edef\!fortemp{#2}%
+ \ifx\!fortemp\!empty
+ \else
+ \!cforloop#2,\!nil,\!nil\!!#1{#3}%
+ \fi}
+\def\!cforloop#1,#2\!!#3#4{%
+ \def#3{#1}%
+ \ifx #3\!nnil
+ \let\!nextwhile=\!fornoop
+ \else
+ #4\relax
+ \let\!nextwhile=\!cforloop
+ \fi
+ \!nextwhile#2\!!#3{#4}}
+
+
+% ** \!ecfor NAME:= LIST\do {BODY}
+% ** This is like \!cfor, but LIST is any balanced token list whose complete
+% ** expansion has the form a1,a2,...,an.
+\def\!ecfor#1:=#2\do#3{%
+ \def\!!cfor{\!cfor#1:=}%
+ \edef\!!!cfor{#2}%
+ \expandafter\!!cfor\!!!cfor\do{#3}}
+
+
+\def\!empty{}
+\def\!nnil{\!nil}
+\def\!fornoop#1\!!#2#3{}
+
+
+% ** \!ifempty{ARG}{TRUE ACTION}{FALSE ACTION}
+\def\!ifempty#1#2#3{%
+ \edef\!emptyarg{#1}%
+ \ifx\!emptyarg\!empty
+ #2%
+ \else
+ #3%
+ \fi}
+
+% ** \!getnext\\ITEMfrom\LIST
+% ** \LIST has the form \\{item1}\\{item2}\\{item3}...\\{itemk}
+% ** This routine sets \ITEM to item1, and cycles \LIST to
+% ** \\{item2}\\{item3}...\\{itemk}\\{item1}
+\def\!getnext#1\from#2{%
+ \expandafter\!gnext#2\!#1#2}%
+\def\!gnext\\#1#2\!#3#4{%
+ \def#3{#1}%
+ \def#4{#2\\{#1}}%
+ \ignorespaces}
+
+
+% ** \!getnextvalueof\DIMEN\from\LIST
+% ** Similar to !getnext.
+% ** \LIST has the form \\{dimen1}\\{dimen2}\\{dimen3} ...
+% ** \DIMEN is a dimension register
+% ** Works also for counts
+%
+\def\!getnextvalueof#1\from#2{%
+ \expandafter\!gnextv#2\!#1#2}%
+\def\!gnextv\\#1#2\!#3#4{%
+ #3=#1%
+ \def#4{#2\\{#1}}%
+ \ignorespaces}
+
+
+% ** \!copylist\LISTMACROA\to\LISTMACROB
+% ** makes the replacement text of LISTMACRO B identical to that of
+% ** list macro A.
+\def\!copylist#1\to#2{%
+ \expandafter\!!copylist#1\!#2}
+\def\!!copylist#1\!#2{%
+ \def#2{#1}\ignorespaces}
+
+
+% ** \!wlet\CSA=\CSB
+% ** lets control sequence \CSB = control sequence \CSA, and writes a
+% ** message to that effect in the log file using plain TEK's \wlog
+\def\!wlet#1=#2{%
+ \let#1=#2
+ \wlog{\string#1=\string#2}}
+
+% ** \!listaddon ITEM LIST
+% ** LIST <-- LIST \\ ITEM
+\def\!listaddon#1#2{%
+ \expandafter\!!listaddon#2\!{#1}#2}
+\def\!!listaddon#1\!#2#3{%
+ \def#3{#1\\#2}}
+
+% ** \!rightappendITEM\to\LISTMACRO
+% ** \LISTMACRO --> \LISTMACRO\\{ITEM}
+%\def\!rightappend#1\to#2{\expandafter\!!rightappend#2\!{#1}#2}
+%\def\!!rightappend#1\!#2#3{\def#3{#1\\{#2}}}
+
+
+% ** \!rightappendITEM\withCS\to\LISTMACRO
+% ** \LISTMACRO --> \LISTMACRO||CS||{ITEM}
+\def\!rightappend#1\withCS#2\to#3{\expandafter\!!rightappend#3\!#2{#1}#3}
+\def\!!rightappend#1\!#2#3#4{\def#4{#1#2{#3}}}
+
+
+% ** \!leftappendITEM\withCS\to\LISTMACRO
+% ** \LISTMACRO --> CS||{ITEM}||\LISTMACRO
+\def\!leftappend#1\withCS#2\to#3{\expandafter\!!leftappend#3\!#2{#1}#3}
+\def\!!leftappend#1\!#2#3#4{\def#4{#2{#3}#1}}
+
+
+% ** \!lop\LISTMACRO\to\ITEM
+% ** \\{item1}\\{item2}\\{item3} ... --> \\{item2}\\{item3} ...
+% ** item1 --> \ITEM
+\def\!lop#1\to#2{\expandafter\!!lop#1\!#1#2}
+\def\!!lop\\#1#2\!#3#4{\def#4{#1}\def#3{#2}}
+
+
+% ** \!placeNUMBER\of\LISTMACRO\in\ITEM
+% ** the NUMBERth item of \LISTMACRO --> replacement text of \ITEM
+%\def\!place#1\of#2\in#3{\def#3{\outofrange}%
+%{\count0=#1\def\\##1{\advance\count0-1 \ifnum\count0=0 \gdef#3{##1}\fi}#2}}
+
+
+% ** Following code converts a commalist to a list macro, with all items
+% ** fully expanded.
+%\!ecfor\item:=\commalist\do{\expandafter\!rightappend\item\to\list}
+
+
+% ** \!loop ... repeat
+% ** This is exactly like TEX's \loop ... repeat. It can be used in nesting
+% ** two loops, without puting the inner one inside a group.
+\def\!loop#1\repeat{\def\!body{#1}\!iterate}
+\def\!iterate{\!body\let\!next=\!iterate\else\let\!next=\relax\fi\!next}
+
+% ** \!!loop ... repeat
+% ** This is exactly like TEX's \loop ... repeat. It can be used in nesting
+% ** two loops, without puting the inner one inside a group.
+\def\!!loop#1\repeat{\def\!!body{#1}\!!iterate}
+\def\!!iterate{\!!body\let\!!next=\!!iterate\else\let\!!next=\relax\fi\!!next}
+% (\multiput uses \!!loop)
+
+% ** \!removept{DIMENREG}{\CS}
+% ** Defines the control sequence CS to be the value (in points) in the
+% ** dimension register DIMENREG (but without the "pt" TEK usually adds)
+% ** E.g., after \dimen0=12.3pt \!removept\dimen0\A, \A expands to 12.3
+\def\!removept#1#2{\edef#2{\expandafter\!!removePT\the#1}}
+{\catcode`p=12 \catcode`t=12 \gdef\!!removePT#1pt{#1}}
+
+% ** \pladevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE}
+\def\placevalueinpts of <#1> in #2 {%
+ \!removept{#1}{#2}}
+
+% ** \!mlap{...} \!vmlap{...}
+% ** Center ... in a box of width 0.
+\def\!mlap#1{\hbox to 0pt{\hss#1\hss}}
+\def\!vmlap#1{\vbox to 0pt{\vss#1\vss}}
+
+% ** \!not{TEK if-CONDITION}
+% ** By a TEK if-CONDITION is meant something like
+% ** \ifnum\N<0, or \ifdim\A>\B
+% ** \!not produces an if-condition which is false if the original condition
+% ** is true, and true if the original condition is false.
+\def\!not#1{%
+ #1\relax
+ \!switchfalse
+ \else
+ \!switchtrue
+ \fi
+ \if!switch
+ \ignorespaces}
+
+
+% *******************
+% *** ALLOCATIONS ***
+% *******************
+
+% This section allocates all the registers PiCTeX uses. Following
+% each allocation is a string of the form ....N.D...L......... ;
+% the various letters show which sections of PiCTeX make explicit
+% reference to that register, according to the following code:
+
+% H Hacks
+% A Areas
+% W arroWs
+% B Bars
+% X boXes
+% C Curves
+% D Dashpattterns
+% V diVision
+% E Ellipses
+% U rUles
+% L Linear arc
+% G loGten
+% P Pictures
+% O plOtting
+% Y pYthagoras
+% Q Quadratic arc
+% R Rotations
+% S Shading
+% T Ticks
+
+% Turn off messages from TeX's allocation macros
+\let\!!!wlog=\wlog % "\wlog" is defined in plain TeX
+\def\wlog#1{}
+
+\newskip\headingtoplotskip %.A................. %-as-%
+\newskip\linethickness %.A..X....U........T
+\newskip\longticklength %.A................T %-as-%
+\newskip\plotsymbolspacing %......D...L....Q...
+\newskip\shortticklength %.A................T %-as-%
+\newskip\stackleading %.A..........P...... %-as-%
+\newskip\tickstovaluesleading %.A................T %-as-%
+\newskip\totalarclength %......D...L....Q...
+\newskip\valuestolabelleading %.A................. %-as-%
+
+\newbox\!boxA %.AW...............T
+\newbox\!boxB %..W................
+\newbox\!picbox %............P......
+\newbox\!plotsymbol %..........L..O.....
+\newbox\!putobject %............PO...S.
+\newbox\!shadesymbol %.................S.
+
+\newcount\!countA %.A....D..UL....Q.ST
+\newcount\!countB %......D..U.....Q.ST
+\newcount\!countC %...............Q..T
+\newcount\!countD %...................
+\newcount\!countE %.............O....T
+\newcount\!countF %.............O....T
+\newcount\!countG %..................T
+\newcount\!fiftypt %.........U.........
+\newcount\!intervalno %..........L....Q...
+\newcount\!npoints %..........L........
+\newcount\!nsegments %.........U.........
+\newcount\!ntemp %............P......
+\newcount\!parity %.................S.
+\newcount\!scalefactor %..................T
+\newcount\!tickcase %..................T
+
+\newskip\!Xleft %............P......
+\newskip\!Xright %............P......
+\newskip\!Xsave %.A................T
+\newskip\!Ybot %............P......
+\newskip\!Ysave %.A................T
+\newskip\!Ytop %............P......
+\newskip\!angle %........E..........
+\newskip\!arclength %..W......UL....Q...
+\newskip\!areabloc %.A........L........
+\newskip\!arealloc %.A........L........
+\newskip\!arearloc %.A........L........
+\newskip\!areatloc %.A........L........
+\newskip\!bshrinkage %.................S.
+\newskip\!checkbot %..........L........
+\newskip\!checkleft %..........L........
+\newskip\!checkright %..........L........
+\newskip\!checktop %..........L........
+\newdimen\!dimenA %.AW.X.DVEUL..OYQRST
+\newdimen\!dimenB %....X.DVEU...O.QRS.
+\newdimen\!dimenC %..W.X.DVEU......RS.
+\newdimen\!dimenD %..W.X.DVEU....Y.RS.
+\newdimen\!dimenE %..W........G..YQ.S.
+\newdimen\!dimenF %...........G..YQ.S.
+\newdimen\!dimenG %...........G..YQ.S.
+\newdimen\!dimenH %...........G..Y..S.
+\newdimen\!dimenI %...BX.........Y....
+\newdimen\!distacross %..........L....Q...
+\newdimen\!downlength %..........L........
+\newdimen\!dp %.A..X.......P....S.
+\newdimen\!dshade %.................S.
+\newdimen\!dxpos %..W......U..P....S.
+\newdimen\!dxprime %...............Q...
+\newdimen\!dypos %..WB.....U..P......
+\newdimen\!dyprime %...............Q...
+\newdimen\!ht %.A..X.......P....S.
+\newdimen\!leaderlength %......D..U.........
+\newdimen\!lshrinkage %.................S.
+\newdimen\!midarclength %...............Q...
+\newdimen\!offset %.A................T
+\newdimen\!plotheadingoffset %.A.................
+\newdimen\!plotsymbolxshift %..........L..O.....
+\newdimen\!plotsymbolyshift %..........L..O.....
+\newdimen\!plotxorigin %..........L..O.....
+\newdimen\!plotyorigin %..........L..O.....
+\newdimen\!rshrinkage %.................S.
+\newdimen\!shadesymbolxshift %.................S.
+\newdimen\!shadesymbolyshift %.................S.
+\newdimen\!tshrinkage %.................S.
+\newdimen\!uplength %..........L........
+\newdimen\!wd %....X.......P....S.
+\newdimen\!xB %...............Q...
+\newdimen\!xC %...............Q...
+\newdimen\!xE %..W.....E.L....Q.S.
+\newdimen\!xM %..W.....E......Q.S.
+\newdimen\!xS %..W.....E.L....Q.S.
+\newdimen\!xaxislength %.A................T
+\newdimen\!xdiff %..........L........
+\newdimen\!xleft %............P......
+\newdimen\!xloc %..WB.....U.......S.
+\newdimen\!xorigin %.A........L.P....S.
+\newdimen\!xpivot %................R..
+\newdimen\!xpos %..........L.P..Q.ST
+\newdimen\!xprime %...............Q...
+\newdimen\!xright %............P......
+\newdimen\!xshade %.................S.
+\newdimen\!xshift %..W.........PO...S.
+\newdimen\!xtemp %............P......
+\newdimen\!xunit %.AWBX...EUL.P..QRS.
+\newdimen\!xxE %........E..........
+\newdimen\!xxM %........E..........
+\newdimen\!xxS %........E..........
+\newdimen\!xxloc %..WB....EU.........
+\newdimen\!yB %...............Q...
+\newdimen\!yC %...............Q...
+\newdimen\!yE %..W.....E.L....Q...
+\newdimen\!yM %..W.....E......Q...
+\newdimen\!yS %..W.....E.L....Q...
+\newdimen\!yaxislength %.A................T
+\newdimen\!ybot %............P......
+\newdimen\!ydiff %..........L........
+\newdimen\!yloc %..WB.....U.......S.
+\newdimen\!yorigin %.A........L.P....S.
+\newdimen\!ypivot %................R..
+\newdimen\!ypos %..........L.P..Q.ST
+\newdimen\!yprime %...............Q...
+\newdimen\!yshade %.................S.
+\newdimen\!yshift %..W.........PO...S.
+\newdimen\!ytemp %............P......
+\newdimen\!ytop %............P......
+\newdimen\!yunit %.AWBX...EUL.P..QRS.
+\newdimen\!yyE %........E..........
+\newdimen\!yyM %........E..........
+\newdimen\!yyS %........E..........
+\newdimen\!yyloc %..WB....EU.........
+
+\newif\if!axisvisible %.A.................
+\newif\if!gridlinestoo %..................T
+\newif\if!keepPO %...................
+\newif\if!placeaxislabel %.A.................
+\newif\if!switch %H..................
+\newif\if!xswitch %.A................T
+
+\newtoks\!axisLaBeL %.A.................
+\newtoks\!keywordtoks %.A.................
+
+\newwrite\!replotfile %.............O.....
+
+\newhelp\!keywordhelp{The keyword mentioned in the error message in unknown.
+Replace NEW KEYWORD in the indicated response by the keyword that
+should have been specified.} %.A.................
+
+% The following commands assign alternate names to some of the
+% above registers. "\!wlet" is defined in Hacks.
+\!wlet\!!origin=\!xM %.A................T
+\!wlet\!!unit=\!uplength %.A................T
+\!wlet\!Lresiduallength=\!dimenG %.........U.........
+\!wlet\!Rresiduallength=\!dimenF %.........U.........
+\!wlet\!axisLength=\!distacross %.A................T
+\!wlet\!axisend=\!ydiff %.A................T
+\!wlet\!axisstart=\!xdiff %.A................T
+\!wlet\!axisxlevel=\!arclength %.A................T
+\!wlet\!axisylevel=\!downlength %.A................T
+\!wlet\!beta=\!dimenE %...............Q...
+\!wlet\!gamma=\!dimenF %...............Q...
+\!wlet\!shadexorigin=\!plotxorigin %.................S.
+\!wlet\!shadeyorigin=\!plotyorigin %.................S.
+\!wlet\!ticklength=\!xS %..................T
+\!wlet\!ticklocation=\!xE %..................T
+\!wlet\!ticklocationincr=\!yE %..................T
+\!wlet\!tickwidth=\!yS %..................T
+\!wlet\!totalleaderlength=\!dimenE %.........U.........
+\!wlet\!xone=\!xprime %....X..............
+\!wlet\!xtwo=\!dxprime %....X..............
+\!wlet\!ySsave=\!yM %...................
+\!wlet\!ybB=\!yB %.................S.
+\!wlet\!ybC=\!yC %.................S.
+\!wlet\!ybE=\!yE %.................S.
+\!wlet\!ybM=\!yM %.................S.
+\!wlet\!ybS=\!yS %.................S.
+\!wlet\!ybpos=\!yyloc %.................S.
+\!wlet\!yone=\!yprime %....X..............
+\!wlet\!ytB=\!xB %.................S.
+\!wlet\!ytC=\!xC %.................S.
+\!wlet\!ytE=\!downlength %.................S.
+\!wlet\!ytM=\!arclength %.................S.
+\!wlet\!ytS=\!distacross %.................S.
+\!wlet\!ytpos=\!xxloc %.................S.
+\!wlet\!ytwo=\!dyprime %....X..............
+
+
+% Initial values for registers
+\def\!zpt{0pt} % static
+\!xunit=1pt
+\!yunit=1pt
+\!arearloc=\!xunit
+\!areatloc=\!yunit
+\!dshade=5pt
+\!leaderlength=24in
+\def\!tfs{256} % static
+\def\!wmax{5.3pt} % static
+\def\!wmin{2.7pt} % static
+\!xaxislength=\!xunit
+\!xpivot=\!zpt
+\!yaxislength=\!yunit
+\!ypivot=\!zpt
+\plotsymbolspacing=.4pt
+ \!dimenA=50pt \def\!fiftypt{\the\!dimenA} % static
+
+\def\!rootten{3.162278pt} % static
+\def\!tenAa{8.690286pt} % static (A5)
+\def\!tenAc{2.773839pt} % static (A3)
+\def\!tenAe{2.543275pt} % static (A1)
+
+% Initial values for control sequences
+\def\!cosrotationangle{1} %................R..
+\def\!sinrotationangle{0} %................R..
+\def\!xpivotcoord{0} %................R..
+\def\!xref{0} %............P......
+\def\!xshadesave{0} %.................S.
+\def\!ypivotcoord{0} %................R..
+\def\!yref{0} %............P......
+\def\!yshadesave{0} %.................S.
+\def\!zero{0} %..................T
+
+% Reset TeX to report allocations
+\let\wlog=\!!!wlog
+% *************************************
+% *** AREAS: Deals with plot areas ***
+% *************************************
+%
+% ** User commands
+% ** \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
+% ** to TOP YCOORD
+% ** \axis BOTTOM-LEFT-TOP-RIGHT [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
+% ** [LABEL {label}] [TICKS] /
+% ** \visibleaxes
+% ** \invisibleaxes
+% ** \plotheading {HEADING}
+% ** \grid {# of columns} {# of rows}
+% ** \normalgraphs
+
+% ** \normalgraphs
+% ** Sets defaults for graph setup. See Subsection 3.4 of manual.
+\def\normalgraphs{%
+ \longticklength=.4\baselineskip
+ \shortticklength=.25\baselineskip
+ \tickstovaluesleading=.25\baselineskip
+ \valuestolabelleading=.8\baselineskip
+ \linethickness=.4pt
+ \stackleading=.17\baselineskip
+ \headingtoplotskip=1.5\baselineskip
+ \visibleaxes
+ \ticksout
+ \nogridlines
+ \unloggedticks}
+%
+% ** \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD
+% ** to TOP YCOORD
+% ** Reserves space in PICBOX for a rectangular box with the indicated
+% ** coordinates. Must be specified before calls to \axis,
+% ** \grid, \plotheading.
+% ** See Subsection 3.1 of the manual.
+\def\setplotarea x from #1 to #2, y from #3 to #4 {%
+ \!arealloc=\!M{#1}\!xunit \advance \!arealloc -\!xorigin
+ \!areabloc=\!M{#3}\!yunit \advance \!areabloc -\!yorigin
+ \!arearloc=\!M{#2}\!xunit \advance \!arearloc -\!xorigin
+ \!areatloc=\!M{#4}\!yunit \advance \!areatloc -\!yorigin
+ \!initinboundscheck
+ \!xaxislength=\!arearloc \advance\!xaxislength -\!arealloc
+ \!yaxislength=\!areatloc \advance\!yaxislength -\!areabloc
+ \!plotheadingoffset=\!zpt
+ \!dimenput {{\setbox0=\hbox{}\wd0=\!xaxislength\ht0=\!yaxislength\box0}}
+ [bl] (\!arealloc,\!areabloc)}
+%
+% ** \visibleaxes, \invisibleaxes
+% ** Switches for setting visibility of subsequent axes.
+% ** See Subsection 3.2 of the manual.
+\def\visibleaxes{%
+ \def\!axisvisibility{\!axisvisibletrue}}
+\def\invisibleaxes{%
+ \def\!axisvisibility{\!axisvisiblefalse}}
+%
+% ** The next few macros enable the user to fix up an erroneous keyword
+% ** in the \axis command.
+% \newhelp is in ALLOCATIONS
+% \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown.
+% Replace NEW KEYWORD in the indicated response by the keyword that
+% should have been specified.}
+
+\def\!fixkeyword#1{%
+ \errhelp=\!keywordhelp
+ \errmessage{Unrecognized keyword `#1': \the\!keywordtoks{NEW KEYWORD}'}}
+
+% \newtoks\!keywordtoks In ALLOCATIONS.
+\!keywordtoks={enter `i\fixkeyword}
+
+\def\fixkeyword#1{%
+ \!nextkeyword#1 }
+
+% ** \axis BOTTOM-LEFT-TOP-RIGHT [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE]
+% ** [LABEL {label}] [TICKS] /
+% ** Exactly one of the keywords BOTTOM, LEFT, TOP, RIGHT must be
+% ** specified. Axis is drawn along the indicated edge of the current
+% ** plot area, shifted if the SHIFTEDTO option is used, visible or
+% ** invisible according the selected option, with an optional LABEL,
+% ** and optional TICKS (see ticks.tex for the options avialabel with
+% ** TICKS). The TICKS option must be the last one specified. The \axis
+% ** MUST be terminated with a / followed by a space.
+% ** See Subsection 3.2 of the manual for more information.
+
+% ** The various options of the \axis command are processed by the
+% ** \!nextkeyword macro defined below. For example,
+% ** `\!nextkeyword shiftedto ' expands to `\!axisshiftedto'.
+\def\axis {%
+ \def\!nextkeyword##1 {%
+ \expandafter\ifx\csname !axis##1\endcsname \relax
+ \def\!next{\!fixkeyword{##1}}%
+ \else
+ \def\!next{\csname !axis##1\endcsname}%
+ \fi
+ \!next}%
+ \!offset=\!zpt
+ \!axisvisibility
+ \!placeaxislabelfalse
+ \!nextkeyword}
+
+% ** This and the various macros that follow handle the keyword
+% ** specifications on the \axis command
+% ** See Subsection 3.2 of the manual.
+\def\!axisbottom{%
+ \!axisylevel=\!areabloc
+ \def\!tickxsign{0}%
+ \def\!tickysign{-}%
+ \def\!axissetup{\!axisxsetup}%
+ \def\!axislabeltbrl{t}%
+ \!nextkeyword}
+
+\def\!axistop{%
+ \!axisylevel=\!areatloc
+ \def\!tickxsign{0}%
+ \def\!tickysign{+}%
+ \def\!axissetup{\!axisxsetup}%
+ \def\!axislabeltbrl{b}%
+ \!nextkeyword}
+
+\def\!axisleft{%
+ \!axisxlevel=\!arealloc
+ \def\!tickxsign{-}%
+ \def\!tickysign{0}%
+ \def\!axissetup{\!axisysetup}%
+ \def\!axislabeltbrl{r}%
+ \!nextkeyword}
+
+\def\!axisright{%
+ \!axisxlevel=\!arearloc
+ \def\!tickxsign{+}%
+ \def\!tickysign{0}%
+ \def\!axissetup{\!axisysetup}%
+ \def\!axislabeltbrl{l}%
+ \!nextkeyword}
+
+\def\!axisshiftedto#1=#2 {%
+ \if 0\!tickxsign
+ \!axisylevel=\!M{#2}\!yunit
+ \advance\!axisylevel -\!yorigin
+ \else
+ \!axisxlevel=\!M{#2}\!xunit
+ \advance\!axisxlevel -\!xorigin
+ \fi
+ \!nextkeyword}
+
+\def\!axisvisible{%
+ \!axisvisibletrue
+ \!nextkeyword}
+
+\def\!axisinvisible{%
+ \!axisvisiblefalse
+ \!nextkeyword}
+
+\def\!axislabel#1 {%
+ \!axisLaBeL={#1}%
+ \!placeaxislabeltrue
+ \!nextkeyword}
+
+\expandafter\def\csname !axis/\endcsname{%
+ \!axissetup % This could done already by "ticks"; if so, now \relax
+ \if!placeaxislabel
+ \!placeaxislabel
+ \fi
+ \if +\!tickysign % ** (A "top" axis)
+ \!dimenA=\!axisylevel
+ \advance\!dimenA \!offset % ** dimA = top of the axis structure
+ \advance\!dimenA -\!areatloc % ** dimA = excess over the plot area
+ \ifdim \!dimenA>\!plotheadingoffset
+ \!plotheadingoffset=\!dimenA % ** Greatest excess over the plot area
+ \fi
+ \fi}
+
+% ** \grid {c} {r}
+% ** Partitions the plot area into c columns and r rows; see Subsection 3.3
+% ** of the manual.
+% ** (Other grid patterns can be drawn with the TICKS option of the \axis
+% ** command.
+\def\grid #1 #2 {%
+ \!countA=#1\advance\!countA 1
+ \axis bottom invisible ticks length <\!zpt> andacross quantity {\!countA} /
+ \!countA=#2\advance\!countA 1
+ \axis left invisible ticks length <\!zpt> andacross quantity {\!countA} / }
+
+% ** \plotheading{HEADING}
+% ** Places HEADING centered above the top of the plotarea (and above
+% ** any top axis ticks marks, tick labels, and axis label); see
+% ** Subsection 3.3 of the manual.
+\def\plotheading#1 {%
+ \advance\!plotheadingoffset \headingtoplotskip
+ \!dimenput {#1} [B] <.5\!xaxislength,\!plotheadingoffset>
+ (\!arealloc,\!areatloc)}
+
+% ** From here on, the routines are internal.
+\def\!axisxsetup{%
+ \!axisxlevel=\!arealloc
+ \!axisstart=\!arealloc
+ \!axisend=\!arearloc
+ \!axisLength=\!xaxislength
+ \!!origin=\!xorigin
+ \!!unit=\!xunit
+ \!xswitchtrue
+ \if!axisvisible
+ \!makeaxis
+ \fi}
+
+\def\!axisysetup{%
+ \!axisylevel=\!areabloc
+ \!axisstart=\!areabloc
+ \!axisend=\!areatloc
+ \!axisLength=\!yaxislength
+ \!!origin=\!yorigin
+ \!!unit=\!yunit
+ \!xswitchfalse
+ \if!axisvisible
+ \!makeaxis
+ \fi}
+
+\def\!makeaxis{%
+ \setbox\!boxA=\hbox{% (Make a pseudo-y[x] tick for an x[y]-axis)
+ \beginpicture
+ \!setdimenmode
+ \setcoordinatesystem point at {\!zpt} {\!zpt}
+ \putrule from {\!zpt} {\!zpt} to
+ {\!tickysign\!tickysign\!axisLength}
+ {\!tickxsign\!tickxsign\!axisLength}
+ \endpicturesave <\!Xsave,\!Ysave>}%
+ \wd\!boxA=\!zpt
+ \!placetick\!axisstart}
+
+\def\!placeaxislabel{%
+ \advance\!offset \valuestolabelleading
+ \if!xswitch
+ \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
+ <.5\!axisLength,\!tickysign\!offset> (\!axisxlevel,\!axisylevel)
+ \advance\!offset \!dp % ** advance offset by the "tallness"
+ \advance\!offset \!ht % ** of the label
+ \else
+ \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl]
+ <\!tickxsign\!offset,.5\!axisLength> (\!axisxlevel,\!axisylevel)
+ \fi
+ \!axisLaBeL={}}
+
+
+% *******************************
+% *** ARROWS (Draws arrows) ***
+% *******************************
+%
+% ** User commands
+% ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
+% ** [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
+% ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
+
+% ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION]
+% ** [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO
+% ** Draws an arrow from (XFROM,YFROM) to (XTO,YTO). The arrow head
+% ** is constructed two quadratic arcs, which extend back a distance
+% ** ARROW HEAD LENGTH (a dimension) on both sides of the arrow shaft.
+% ** All the way back the arcs are a distance BASE FRACTION*ARROW HEAD
+% ** LENGTH apart, while half-way back they are a distance MID FRACTION*
+% ** ARROW HEAD LENGTH apart. <XSHIFT,YSHIFT> is optional, and has
+% ** its usual interpreation. See Subsection 5.4 of the manual.
+
+\def\arrow <#1> [#2,#3]{%
+ \!ifnextchar<{\!arrow{#1}{#2}{#3}}{\!arrow{#1}{#2}{#3}<\!zpt,\!zpt> }}
+
+\def\!arrow#1#2#3<#4,#5> from #6 #7 to #8 #9 {%
+%
+% ** convert to dimensions
+ \!xloc=\!M{#8}\!xunit
+ \!yloc=\!M{#9}\!yunit
+ \!dxpos=\!xloc \!dimenA=\!M{#6}\!xunit \advance \!dxpos -\!dimenA
+ \!dypos=\!yloc \!dimenA=\!M{#7}\!yunit \advance \!dypos -\!dimenA
+ \let\!MAH=\!M% ** save current c/d mode
+ \!setdimenmode% ** go into dimension mode
+%
+ \!xshift=#4\relax \!yshift=#5\relax% ** pick up shift
+ \!reverserotateonly\!xshift\!yshift% ** back rotate shift
+ \advance\!xshift\!xloc \advance\!yshift\!yloc
+%
+% ** draw shaft of arrow
+ \!xS=-\!dxpos \advance\!xS\!xshift
+ \!yS=-\!dypos \advance\!yS\!yshift
+ \!start (\!xS,\!yS)
+ \!ljoin (\!xshift,\!yshift)
+%
+% ** find 32*cosine and 32*sine of angle of rotation
+ \!Pythag\!dxpos\!dypos\!arclength
+ \!divide\!dxpos\!arclength\!dxpos
+ \!dxpos=32\!dxpos \!removept\!dxpos\!!cos
+ \!divide\!dypos\!arclength\!dypos
+ \!dypos=32\!dypos \!removept\!dypos\!!sin
+%
+% ** construct arrowhead
+ \!halfhead{#1}{#2}{#3}% ** draw half of arrow head
+ \!halfhead{#1}{-#2}{-#3}% ** draw other half
+%
+ \let\!M=\!MAH% ** restore old c/d mode
+ \ignorespaces}
+%
+% ** draw half of arrow head
+ \def\!halfhead#1#2#3{%
+ \!dimenC=-#1%
+ \divide \!dimenC 2 % ** half way back
+ \!dimenD=#2\!dimenC% ** half the mid width
+ \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xM,\!yM)
+ \!dimenC=-#1% ** all the way back
+ \!dimenD=#3\!dimenC
+ \!dimenD=.5\!dimenD% ** half the full width
+ \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xE,\!yE)
+ \!start (\!xshift,\!yshift)
+ \advance\!xM\!xshift \advance\!yM\!yshift
+ \advance\!xE\!xshift \advance\!yE\!yshift
+ \!qjoin (\!xM,\!yM) (\!xE,\!yE)
+ \ignorespaces}
+
+
+% ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO
+% ** Makes things like <--- text --->, using arrow heads from TeX's fonts.
+% ** See Subsection 5.4 of the manual.
+\def\betweenarrows #1#2 from #3 #4 to #5 #6 {%
+ \!xloc=\!M{#3}\!xunit \!xxloc=\!M{#5}\!xunit%
+ \!yloc=\!M{#4}\!yunit \!yyloc=\!M{#6}\!yunit%
+ \!dxpos=\!xxloc \advance\!dxpos by -\!xloc
+ \!dypos=\!yyloc \advance\!dypos by -\!yloc
+ \advance\!xloc .5\!dxpos
+ \advance\!yloc .5\!dypos
+%
+ \let\!MBA=\!M% ** save current coord\dimen mode
+ \!setdimenmode% ** express locations in dimens
+ \ifdim\!dypos=\!zpt
+ \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi
+ \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc}
+ \else
+ \ifdim\!dxpos=\!zpt
+ \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi
+ \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc}
+ \fi
+ \fi
+ \let\!M=\!MBA% ** restore previous c/d mode
+ \ignorespaces}
+
+% ** Subroutine for left-right between arrows
+\def\!lrarrows#1#2{% #1=width, #2=text
+ {\setbox\!boxA=\hbox{$\mkern-2mu\mathord-\mkern-2mu$}%
+ \setbox\!boxB=\hbox{$\leftarrow$}\!dimenE=\ht\!boxB
+ \setbox\!boxB=\hbox{}\ht\!boxB=2\!dimenE
+ \hbox to #1{$\mathord\leftarrow\mkern-6mu
+ \cleaders\copy\!boxA\hfil
+ \mkern-6mu\mathord-$%
+ \kern.4em $\vcenter{\box\!boxB}$$\vcenter{\hbox{#2}}$\kern.4em
+ $\mathord-\mkern-6mu
+ \cleaders\copy\!boxA\hfil
+ \mkern-6mu\mathord\rightarrow$}}}
+
+% ** Subroutine for up-down between arrows
+\def\!udarrows#1#2{% #1=width, #2=text
+ {\setbox\!boxB=\hbox{#2}%
+ \setbox\!boxA=\hbox to \wd\!boxB{\hss$\vert$\hss}%
+ \!dimenE=\ht\!boxA \advance\!dimenE \dp\!boxA \divide\!dimenE 2
+ \vbox to #1{\offinterlineskip
+ \vskip .05556\!dimenE
+ \hbox to \wd\!boxB{\hss$\mkern.4mu\uparrow$\hss}\vskip-\!dimenE
+ \cleaders\copy\!boxA\vfil
+ \vskip-\!dimenE\copy\!boxA
+ \vskip\!dimenE\copy\!boxB\vskip.4em
+ \copy\!boxA\vskip-\!dimenE
+ \cleaders\copy\!boxA\vfil
+ \vskip-\!dimenE \hbox to \wd\!boxB{\hss$\mkern.4mu\downarrow$\hss}
+ \vskip .05556\!dimenE}}}
+
+
+% ***************************
+% *** BARS (Draws bars) ***
+% ***************************
+%
+% ** User commands:
+% ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
+% ** to XEND YEND
+% ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
+% ** [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
+% ** [endlabels ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
+
+
+% ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART
+% ** to XEND YEND
+% ** Either XSTART=XEND or YSTART=YEND. Draws a rectangle between
+% ** (XSTART,YSTART) & (XEND,YEND). The "depth" of the rectangle
+% ** is determined by those two plot positions; its other
+% ** dimension "breadth" is specified by the dimension BREADTH.
+% ** See Subsection 4.2 of the manual.
+\def\putbar#1breadth <#2> from #3 #4 to #5 #6 {%
+ \!xloc=\!M{#3}\!xunit \!xxloc=\!M{#5}\!xunit%
+ \!yloc=\!M{#4}\!yunit \!yyloc=\!M{#6}\!yunit%
+ \!dypos=\!yyloc \advance\!dypos by -\!yloc
+ \!dimenI=#2
+%
+ \ifdim \!dimenI=\!zpt % ** If 0 breadth
+ \putrule#1from {#3} {#4} to {#5} {#6} % ** Then draw line
+ \else % ** Else, put in a rectangle
+ \let\!MBar=\!M% ** save current c/d mode
+ \!setdimenmode % ** go into dimension mode
+ \divide\!dimenI 2
+ \ifdim \!dypos=\!zpt
+ \advance \!yloc -\!dimenI % ** Equal y coordinates
+ \advance \!yyloc \!dimenI
+ \else
+ \advance \!xloc -\!dimenI % ** Equal x coordinates
+ \advance \!xxloc \!dimenI
+ \fi
+ \putrectangle#1corners at {\!xloc} {\!yloc} and {\!xxloc} {\!yyloc}
+ \let\!M=\!MBar % ** restore c/d mode
+ \fi
+ \ignorespaces}
+
+
+% ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD
+% ** [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)]
+% ** [endlabels ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)]
+% ** This command puts PiCTeX into the bar graph drawing mode described
+% ** in Subsection 4.4 of the manual.
+\def\setbars#1breadth <#2> baseline at #3 = #4 {%
+ \edef\!barshift{#1}%
+ \edef\!barbreadth{#2}%
+ \edef\!barorientation{#3}%
+ \edef\!barbaseline{#4}%
+ \def\!bardobaselabel{\!bardoendlabel}%
+ \def\!bardoendlabel{\!barfinish}%
+ \let\!drawcurve=\!barcurve
+ \!setbars}
+\def\!setbars{%
+ \futurelet\!nextchar\!!setbars}
+\def\!!setbars{%
+ \if b\!nextchar
+ \def\!!!setbars{\!setbarsbget}%
+ \else
+ \if e\!nextchar
+ \def\!!!setbars{\!setbarseget}%
+ \else
+ \def\!!!setbars{\relax}%
+ \fi
+ \fi
+ \!!!setbars}
+\def\!setbarsbget baselabels (#1) {%
+ \def\!barbaselabelorientation{#1}%
+ \def\!bardobaselabel{\!!bardobaselabel}%
+ \!setbars}
+\def\!setbarseget endlabels (#1) {%
+ \edef\!barendlabelorientation{#1}%
+ \def\!bardoendlabel{\!!bardoendlabel}%
+ \!setbars}
+
+% ** \!barcurve
+% ** Draws a bargraph with preset values of barshift, barbreadth,
+% ** barorientation (x or y) and barbaseline (coordinate)
+\def\!barcurve #1 #2 {%
+ \if y\!barorientation
+ \def\!basexarg{#1}%
+ \def\!baseyarg{\!barbaseline}%
+ \else
+ \def\!basexarg{\!barbaseline}%
+ \def\!baseyarg{#2}%
+ \fi
+ \expandafter\putbar\!barshift breadth <\!barbreadth> from {\!basexarg}
+ {\!baseyarg} to {#1} {#2}
+ \def\!endxarg{#1}%
+ \def\!endyarg{#2}%
+ \!bardobaselabel}
+
+\def\!!bardobaselabel "#1" {%
+ \put {#1}\!barbaselabelorientation{} at {\!basexarg} {\!baseyarg}
+ \!bardoendlabel}
+
+\def\!!bardoendlabel "#1" {%
+ \put {#1}\!barendlabelorientation{} at {\!endxarg} {\!endyarg}
+ \!barfinish}
+
+\def\!barfinish{%
+ \!ifnextchar/{\!finish}{\!barcurve}}
+
+
+% ********************************
+% *** BOXES (Draws rectangles) ***
+% ********************************
+%
+% ** User commands:
+% ** \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1
+% ** and XCOORD2 YCOORD2
+% ** \shaderectangleson
+% ** \shaderectanglesoff
+% ** \frame [<SEPARATION>] {TEXT}
+% ** \rectangle <WIDTH> <HEIGHT>
+%
+%
+% ** \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1
+% ** and XCOORD2 YCOORD2
+% ** Draws a rectangle with corners at (X1,Y1), (X2,Y1), (X1,Y2), (X2,Y2)
+% ** Lines have thickness \linethickness, and overlap at the corners.
+% ** The optional field <XSHIFT,YSHIFT> functions as with a \put command.
+% ** See Subsection 4.2 of the manual.
+\def\putrectangle{%
+ \!ifnextchar<{\!putrectangle}{\!putrectangle<\!zpt,\!zpt> }}
+\def\!putrectangle<#1,#2> corners at #3 #4 and #5 #6 {%
+%
+% ** get locations
+ \!xone=\!M{#3}\!xunit \!xtwo=\!M{#5}\!xunit%
+ \!yone=\!M{#4}\!yunit \!ytwo=\!M{#6}\!yunit%
+ \ifdim \!xtwo<\!xone
+ \!dimenI=\!xone \!xone=\!xtwo \!xtwo=\!dimenI
+ \fi
+ \ifdim \!ytwo<\!yone
+ \!dimenI=\!yone \!yone=\!ytwo \!ytwo=\!dimenI
+ \fi
+ \!dimenI=#1\relax \advance\!xone\!dimenI \advance\!xtwo\!dimenI
+ \!dimenI=#2\relax \advance\!yone\!dimenI \advance\!ytwo\!dimenI
+ \let\!MRect=\!M% ** save current coord/dimen mode
+ \!setdimenmode
+%
+% ** shade rectangle if appropriate
+ \!shaderectangle
+%
+% ** draw horizontal edges
+ \!dimenI=.5\linethickness
+ \advance \!xone -\!dimenI% ** adjust x-location to overlap corners
+ \advance \!xtwo \!dimenI% ** ditto
+ \putrule from {\!xone} {\!yone} to {\!xtwo} {\!yone}
+ \putrule from {\!xone} {\!ytwo} to {\!xtwo} {\!ytwo}
+%
+% ** draw vertical edges
+ \advance \!xone \!dimenI% ** restore original x-values
+ \advance \!xtwo -\!dimenI%
+ \advance \!yone -\!dimenI% ** adjust y-location to overlap corners
+ \advance \!ytwo \!dimenI% ** ditto
+ \putrule from {\!xone} {\!yone} to {\!xone} {\!ytwo}
+ \putrule from {\!xtwo} {\!yone} to {\!xtwo} {\!ytwo}
+%
+ \let\!M=\!MRect% ** restore coord/dimen mode
+ \ignorespaces}
+
+% ** \shaderectangleson
+% ** Subsequent rectangles will be shaded according to
+% ** the current shading pattern. Affects \putrectangle, \putbar,
+% ** \frame, \sethistograms, and \setbars. See Subsection 7.5 of the manual.
+\def\shaderectangleson{%
+ \def\!shaderectangle{\!!shaderectangle}%
+ \ignorespaces}
+% ** \shaderectanglesoff
+% ** Suppresses \shaderectangleson. The default.
+\def\shaderectanglesoff{%
+ \def\!shaderectangle{}%
+ \ignorespaces}
+
+\shaderectanglesoff
+
+% ** The following internal routine shades the current rectangle, when
+% ** \!shaderectangle = \!!shaderectangle .
+\def\!!shaderectangle{%
+ \!dimenA=\!xtwo \advance \!dimenA -\!xone
+ \!dimenB=\!ytwo \advance \!dimenB -\!yone
+ \ifdim \!dimenA<\!dimenB
+ \!startvshade (\!xone,\!yone,\!ytwo)
+ \!lshade (\!xtwo,\!yone,\!ytwo)
+ \else
+ \!starthshade (\!yone,\!xone,\!xtwo)
+ \!lshade (\!ytwo,\!xone,\!xtwo)
+ \fi
+ \ignorespaces}
+
+% ** \frame [<SEPARATION>] {TEXT}
+% ** Draws a frame of thickness linethickness about the box enclosing
+% ** TEXT; the frame is separated from the box by a distance of
+% ** SEPARATION. The result is an hbox with the same baseline as TEXT.
+% ** If <SEPARATION> is omitted, you get the effect of <0pt>.
+% ** See Subsection 4.2 of the manual.
+\def\frame{%
+ \!ifnextchar<{\!frame}{\!frame<\!zpt> }}
+\long\def\!frame<#1> #2{%
+ \beginpicture
+ \setcoordinatesystem units <1pt,1pt> point at 0 0
+ \put {#2} [Bl] at 0 0
+ \!dimenA=#1\relax
+ \!dimenB=\!wd \advance \!dimenB \!dimenA
+ \!dimenC=\!ht \advance \!dimenC \!dimenA
+ \!dimenD=\!dp \advance \!dimenD \!dimenA
+ \let\!MFr=\!M
+ \!setdimenmode
+ \putrectangle corners at {-\!dimenA} {-\!dimenD} and {\!dimenB} {\!dimenC}
+ \!setcoordmode
+ \let\!M=\!MFr
+ \endpicture
+ \ignorespaces}
+
+% ** \rectangle <WIDTH> <HEIGHT>
+% ** Constructs a rectangle of width WIDTH and heigth HEIGHT.
+% ** See Subsection 4.2 of the manual.
+\def\rectangle <#1> <#2> {%
+ \setbox0=\hbox{}\wd0=#1\ht0=#2\frame {\box0}}
+
+
+% *********************************************
+% *** CURVES (Upper level \plot commands) ***
+% *********************************************
+%
+% ** User commands
+% ** \plot DATA /
+% ** \plot "FILE NAME"
+% ** \setquadratic
+% ** \setlinear
+% ** \sethistograms
+% ** \vshade ...
+% ** \hshade ...
+
+% \plot: multi-purpose command. Draws histograms, bar graphs, piecewise-linear
+% or piecewise quadratic curves, depending on the setting of \!drawcurve.
+% See Subsections 4.3-4.5, 5.1, 5.2 of the manual.
+\def\plot{%
+ \!ifnextchar"{\!plotfromfile}{\!drawcurve}}
+\def\!plotfromfile"#1"{%
+ \expandafter\!drawcurve \input #1 /}
+
+% Command to set piecewise quadratic mode
+% See Subsections 5.1, 7.3, and 7.4 of the manual.
+\def\setquadratic{%
+ \let\!drawcurve=\!qcurve
+ \let\!!Shade=\!!qShade
+ \let\!!!Shade=\!!!qShade}
+
+% Command to set piecewise linear mode
+% See Subsections 5.1, 7.3, and 7.4 of the manual.
+\def\setlinear{%
+ \let\!drawcurve=\!lcurve
+ \let\!!Shade=\!!lShade
+ \let\!!!Shade=\!!!lShade}
+
+% Command to set histogram mode
+% See Subsection 4.3 of the manual.
+\def\sethistograms{%
+ \let\!drawcurve=\!hcurve}
+
+% Commands to cycle through list of coordinates in piecewise quadratic
+% interpolation mode
+\def\!qcurve #1 #2 {%
+ \!start (#1,#2)
+ \!Qjoin}
+\def\!Qjoin#1 #2 #3 #4 {%
+ \!qjoin (#1,#2) (#3,#4) % \!qjoin is defined in QUADRATIC
+ \!ifnextchar/{\!finish}{\!Qjoin}}
+
+% Commands to cycle through list of coordinates in piecewise linear
+% interpolation mode
+\def\!lcurve #1 #2 {%
+ \!start (#1,#2)
+ \!Ljoin}
+\def\!Ljoin#1 #2 {%
+ \!ljoin (#1,#2) % \!ljoin is defined in LINEAR
+ \!ifnextchar/{\!finish}{\!Ljoin}}
+
+\def\!finish/{\ignorespaces}
+
+% Command to cycle through list of coordinates in histogram mode
+\def\!hcurve #1 #2 {%
+ \edef\!hxS{#1}%
+ \edef\!hyS{#2}%
+ \!hjoin}
+\def\!hjoin#1 #2 {%
+ \putrectangle corners at {\!hxS} {\!hyS} and {#1} {#2}
+ \edef\!hxS{#1}%
+ \!ifnextchar/{\!finish}{\!hjoin}}
+
+
+% \vshade: See Subsection 7.3 of the manual.
+\def\vshade #1 #2 #3 {%
+ \!startvshade (#1,#2,#3)
+ \!Shadewhat}
+
+% \hshade: See Subsection 7.4 of the manual.
+\def\hshade #1 #2 #3 {%
+ \!starthshade (#1,#2,#3)
+ \!Shadewhat}
+
+% Commands to cycle through coordinates and optional "edge effect"
+% fields while shading.
+\def\!Shadewhat{%
+ \futurelet\!nextchar\!Shade}
+\def\!Shade{%
+ \if <\!nextchar
+ \def\!nextShade{\!!Shade}%
+ \else
+ \if /\!nextchar
+ \def\!nextShade{\!finish}%
+ \else
+ \def\!nextShade{\!!!Shade}%
+ \fi
+ \fi
+ \!nextShade}
+\def\!!lShade<#1> #2 #3 #4 {%
+ \!lshade <#1> (#2,#3,#4) % \!lshade is defined in SHADING
+ \!Shadewhat}
+\def\!!!lShade#1 #2 #3 {%
+ \!lshade (#1,#2,#3)
+ \!Shadewhat}
+\def\!!qShade<#1> #2 #3 #4 #5 #6 #7 {%
+ \!qshade <#1> (#2,#3,#4) (#5,#6,#7) % \!qshade is defined in SHADING
+ \!Shadewhat}
+\def\!!!qShade#1 #2 #3 #4 #5 #6 {%
+ \!qshade (#1,#2,#3) (#4,#5,#6)
+ \!Shadewhat}
+
+% ** Set default interpolation mode
+\setlinear
+
+
+% ********************************************
+% *** DASHPATTERNS (Sets up dash patterns) ***
+% ********************************************
+
+% ** User commands:
+% ** \setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
+% ** \setdots <INTRADOT_DISTANCE>
+% ** \setdotsnear <INTRADOT_DISTANCE> for <ARC LENGTH>
+% ** \setdashes <DASH/SKIP_DISTANCE>
+% ** \setdashesnear <DASH/SKIP_DISTANCE> for <ARC LENGTH>
+% ** \setsolid
+% ** \findlength {CURVE CMDS}
+
+% ** Internal commands:
+% ** \!dashingon
+% ** \!dashingoff
+
+% ** Dash patterns are specified by a balanced token list whose complete
+% ** expansion has the form: DIMEN1,DIMEN2,DIMEN3,DIMEN4,... ; this produces
+% ** an arc of length DIMEN1, a skip of length DIMEN2, an arc of length
+% ** DIMEN3, a skip of length DIMEN4, ... . Any number of DIMEN values may
+% ** be given. The pattern is repeated as many times (perhaps fractional)
+% ** as necessary to draw the curve.
+% ** A dash pattern remains in effect until it is overridden by a call to
+% ** \setdashpattern, or to \setdots, \setdotsnear ... , \setdashes,
+% ** \setdashesnear ... , or \setsolid.
+% ** Solid lines are the default.
+
+
+% ** \def\setdashpattern <DIMEN1,DIMEN2,DIMEN3,...>
+% ** The following routine converts a balanced list of tokens whose
+% ** complete expansion has the form DIMEN1,DIMEN2, ... , DIMENk into
+% ** three list macros that are used in drawing dashed rules and curves:
+% ** !Flist: \!Rule{DIMEN1}\!Skip{DIMEN2}\!Rule{DIMEN3}\!Skip{DIMEN4} ...
+% ** !Blist: ...\!Skip{DIMEN4}\!Rule{DIMEN3}\!Skip{DIMEN2}\!Rule{DIMEN1}
+% ** !UDlist: \\{DIMEN1}\\{DIMEN2}\\{DIMEN3}\\{DIMEN4} ...;
+% ** calculates \!leaderlength := DIMEN1 + ... + DIMENk; and
+% ** sets the curve drawing routines to dash mode.
+% ** Those lists are used by the curve drawing routines.
+% ** Dimenj ... may be given as an explicit dimension (e.g., 5pt), or
+% ** as an expression involving a dimension register (e.g., -2.5\dimen0).
+% ** See Subsection 6.2 of the manual
+\def\setdashpattern <#1>{%
+ \def\!Flist{}\def\!Blist{}\def\!UDlist{}%
+ \!countA=0
+ \!ecfor\!item:=#1\do{%
+ \!dimenA=\!item\relax
+ \expandafter\!rightappend\the\!dimenA\withCS{\\}\to\!UDlist%
+ \advance\!countA 1
+ \ifodd\!countA
+ \expandafter\!rightappend\the\!dimenA\withCS{\!Rule}\to\!Flist%
+ \expandafter\!leftappend\the\!dimenA\withCS{\!Rule}\to\!Blist%
+ \else
+ \expandafter\!rightappend\the\!dimenA\withCS{\!Skip}\to\!Flist%
+ \expandafter\!leftappend\the\!dimenA\withCS{\!Skip}\to\!Blist%
+ \fi}%
+ \!leaderlength=\!zpt
+ \def\!Rule##1{\advance\!leaderlength ##1}%
+ \def\!Skip##1{\advance\!leaderlength ##1}%
+ \!Flist%
+ \ifdim\!leaderlength>\!zpt
+ \else
+ \def\!Flist{\!Skip{24in}}\def\!Blist{\!Skip{24in}}\ignorespaces
+ \def\!UDlist{\\{\!zpt}\\{24in}}\ignorespaces
+ \!leaderlength=24in
+ \fi
+ \!dashingon}
+
+
+% ** \!dashingon -- puts the curve drawing routines into dash mode
+% ** \!dashingoff -- puts the curve drawing routines into solid mode
+% ** These are internal commands, invoked by \setdashpattern and \setsolid
+\def\!dashingon{%
+ \def\!advancedashing{\!!advancedashing}%
+ \def\!drawlinearsegment{\!lineardashed}%
+ \def\!puthline{\!putdashedhline}%
+ \def\!putvline{\!putdashedvline}%
+% \def\!putsline{\!putdashedsline}%
+ \ignorespaces}%
+\def\!dashingoff{%
+ \def\!advancedashing{\relax}%
+ \def\!drawlinearsegment{\!linearsolid}%
+ \def\!puthline{\!putsolidhline}%
+ \def\!putvline{\!putsolidvline}%
+% \def\!putsline{\!putsolidsline}%
+ \ignorespaces}
+
+
+% ** \setdots <LENGTH> -- sets up a dot/skip pattern where dot (actually
+% ** the current plotsymbol) is plunked down once for every LENGTH
+% ** traveled along the curve. LENGTH defaults to 5pt.
+% ** See Subsection 6.1 of the manual.
+\def\setdots{%
+ \!ifnextchar<{\!setdots}{\!setdots<5pt>}}
+\def\!setdots<#1>{%
+ \!dimenB=#1\advance\!dimenB -\plotsymbolspacing
+ \ifdim\!dimenB<\!zpt
+ \!dimenB=\!zpt
+ \fi
+\setdashpattern <\plotsymbolspacing,\!dimenB>}
+
+% ** \setdotsnear <LENGTH> for <ARC LENGTH>
+% ** sets up a dot pattern where the dots are approximately LENGTH apart,
+% ** the total length of the pattern is ARC LENGTH, and the pattern
+% ** begins and ends with a dot. See Subsection 6.3 of the manual.
+\def\setdotsnear <#1> for <#2>{%
+ \!dimenB=#2\relax \advance\!dimenB -.05pt
+ \!dimenC=#1\relax \!countA=\!dimenC
+ \!dimenD=\!dimenB \advance\!dimenD .5\!dimenC \!countB=\!dimenD
+ \divide \!countB \!countA
+ \ifnum 1>\!countB
+ \!countB=1
+ \fi
+ \divide\!dimenB \!countB
+ \setdots <\!dimenB>}
+
+% ** \setdashes <LENGTH> -- sets up a dash/skip pattern where the dash
+% ** and the skip are each of length LENGTH (the dash is formed by
+% ** plunking down the current plotsymbol over an arc of length LENGTH
+% ** and so may actually be longer than LENGTH. LENGTH defaults to 5pt.
+% ** See Subsection 6.1 of the manual.
+\def\setdashes{%
+ \!ifnextchar<{\!setdashes}{\!setdashes<5pt>}}
+\def\!setdashes<#1>{\setdashpattern <#1,#1>}
+
+% ** \setdashesnear ...
+% ** Like \setdotsnear; the pattern begins and ends with a dash.
+% ** See Subsection 6.3 of the manual.
+\def\setdashesnear <#1> for <#2>{%
+ \!dimenB=#2\relax
+ \!dimenC=#1\relax \!countA=\!dimenC
+ \!dimenD=\!dimenB \advance\!dimenD .5\!dimenC \!countB=\!dimenD
+ \divide \!countB \!countA
+ \ifodd \!countB
+ \else
+ \advance \!countB 1
+ \fi
+ \divide\!dimenB \!countB
+ \setdashes <\!dimenB>}
+
+% ** \setsolid -- puts the curve drawing routines in "solid line" mode,
+% ** the default mode. See Subsection 6.1 of the manual.
+\def\setsolid{%
+ \def\!Flist{\!Rule{24in}}\def\!Blist{\!Rule{24in}}%
+ \def\!UDlist{\\{24in}\\{\!zpt}}%
+ \!dashingoff}
+\setsolid
+
+% ** \findlength {CURVE CMDS}
+% ** PiCTeX executes the \start, \ljoin, and \qjoin cmds comprising
+% ** CURVE CMDS without plotting anything, but stashes the length
+% ** of the phantom curve away in \totalarclength.
+% ** See Subsection 6.3 of the manual.
+\def\findlength#1{%
+ \begingroup
+ \setdashpattern <0pt, \maxdimen>
+ \setplotsymbol ({})
+ \dontsavelinesandcurves
+ #1%
+ \endgroup
+ \ignorespaces}
+
+
+% *************************************************************
+% *** DIVISION (Does long division of dimension registers) ***
+% *************************************************************
+
+% ** User command:
+% ** \Divide {DIVIDEND} by {DIVISOR} forming {RESULT}
+
+% ** Internal command
+% ** \!divide{DIVIDEND}{DIVISOR}{RESULT}
+
+% ** \!divide DIVIDEND [by] DIVISOR [to get] ANSWER
+% ** Divides the dimension DIVIDEND by the dimension DIVISOR, placing the
+% ** quotient in the dimension register ANSWER. Values are understood to
+% ** be in points. E.g. 12.5pt/1.4pt=8.92857pt.
+% ** Quotient is accurate to 1/65536pt=2**[-16]pt
+% ** |DIVISOR| should be < 2048pt (about 28 inches).
+\def\!divide#1#2#3{%
+ \!dimenB=#1% ** dimB holds current remainder (r)
+ \!dimenC=#2% ** dimC holds divisor (d)
+ \!dimenD=\!dimenB% ** dimD holds quotient q=r/d for this
+ \divide \!dimenD \!dimenC% ** step, in units of scaled pts
+ \!dimenA=\!dimenD% ** dimA eventually holds answer (a)
+ \multiply\!dimenD \!dimenC% ** r <-- r - dq
+ \advance\!dimenB -\!dimenD% ** First step complete. Have integer part
+% ** of a, and corresponding remainder.
+ \!dimenD=\!dimenC% ** Temporarily use dimD to hold |d|
+ \ifdim\!dimenD<\!zpt \!dimenD=-\!dimenD
+ \fi
+ \ifdim\!dimenD<64pt% ** Branch on the magnitude of |d|
+ \!divstep[\!tfs]\!divstep[\!tfs]%
+ \else
+ \!!divide
+ \fi
+ #3=\!dimenA\ignorespaces}
+
+% ** The following code handles divisors d with
+% ** (1) .88in = 64pt <= d < 256pt = 3.54in
+% ** (2) 3.54in = 256pt <= d < 2048pt = 28.34in
+% ** Anything bigger than that may result in an overflow condition.
+% ** For our purposes, we should never even see case (2).
+\def\!!divide{%
+ \ifdim\!dimenD<256pt
+ \!divstep[64]\!divstep[32]\!divstep[32]%
+ \else
+ \!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]%
+ \!dimenA=2\!dimenA
+ \fi}
+
+
+% ** The following macro does the real long division work.
+\def\!divstep[#1]{% ** #1 = "B"
+ \!dimenB=#1\!dimenB% ** r <-- B*r
+ \!dimenD=\!dimenB% ** dimD holds quotient q=r/d for this
+ \divide \!dimenD by \!dimenC% ** step, in units of scaled pts
+ \!dimenA=#1\!dimenA% ** a <-- B*a + q
+ \advance\!dimenA by \!dimenD%
+ \multiply\!dimenD by \!dimenC% ** r <-- r - dq
+ \advance\!dimenB by -\!dimenD}
+
+% ** \Divide: See Subsection 9.3 of the manual.
+\def\Divide <#1> by <#2> forming <#3> {%
+ \!divide{#1}{#2}{#3}}
+
+
+% *********************************************
+% *** ELLIPSES (Draws ellipses and circles) ***
+% *********************************************
+
+% ** User commands
+% ** \ellipticalarc axes ratio A:B DEGREES degrees from XSTART YSTART
+% ** center at XCENTER YCENTER
+% ** \circulararc DEGREES degrees from XSTART YSTART
+% ** center at XCENTER YCENTER
+
+% ** Internal command
+% ** \!sinandcos{32*ANGLE in radians}{32*SIN}{32*COS}
+
+
+% ** \ellipticalarc axes ratio A:B DEGREES degrees from XSTART YSTART
+% ** center at XCENTER YCENTER
+% ** Draws a elliptical arc starting at the coordinate point (XSTART,YSTART).
+% ** The center of the ellipse of which the arc is a segment is at
+% ** (XCENTER,YCENTER).
+% ** The arc extends through an angle of DEGREES degrees (may be + or -).
+% ** A:B is the ratio of the length of the xaxis to the length of
+% ** the yaxis of the ellipse
+% ** Sqrt{[(XSTART-XCENTER)/A]**2 + [(YSTART-YCENTER)/B]**2}
+% ** must be < 512pt (about 7in).
+% ** Doesn't modify the dimensions (ht, dp, wd) of the PiCture under
+% ** construction.
+
+% ** \circulararc -- See Subsection 5.3 of the manual.
+\def\circulararc{%
+ \ellipticalarc axes ratio 1:1 }
+
+% ** \ellipticalarc -- See Subsection 5.3 of the manual.
+\def\ellipticalarc axes ratio #1:#2 #3 degrees from #4 #5 center at #6 #7 {%
+ \!angle=#3pt\relax% ** get angle
+ \ifdim\!angle>\!zpt
+ \def\!sign{}% ** counterclockwise
+ \else
+ \def\!sign{-}\!angle=-\!angle% ** clockwise
+ \fi
+ \!xxloc=\!M{#6}\!xunit% ** convert CENTER to dimension
+ \!yyloc=\!M{#7}\!yunit
+ \!xxS=\!M{#4}\!xunit% ** get STARTing point on rim of ellipse
+ \!yyS=\!M{#5}\!yunit
+ \advance\!xxS -\!xxloc% ** make center of ellipse (0,0)
+ \advance\!yyS -\!yyloc
+ \!divide\!xxS{#1pt}\!xxS % ** scale point on ellipse to point on
+ \!divide\!yyS{#2pt}\!yyS % corresponding circle
+%
+ \let\!MC=\!M% ** save current c/d mode
+ \!setdimenmode% ** go into dimension mode
+%
+ \!xS=#1\!xxS \advance\!xS\!xxloc
+ \!yS=#2\!yyS \advance\!yS\!yyloc
+ \!start (\!xS,\!yS)%
+ \!loop\ifdim\!angle>14.9999pt% ** draw in major portion of ellipse
+ \!rotate(\!xxS,\!yyS)by(\!cos,\!sign\!sin)to(\!xxM,\!yyM)
+ \!rotate(\!xxM,\!yyM)by(\!cos,\!sign\!sin)to(\!xxE,\!yyE)
+ \!xM=#1\!xxM \advance\!xM\!xxloc \!yM=#2\!yyM \advance\!yM\!yyloc
+ \!xE=#1\!xxE \advance\!xE\!xxloc \!yE=#2\!yyE \advance\!yE\!yyloc
+ \!qjoin (\!xM,\!yM) (\!xE,\!yE)
+ \!xxS=\!xxE \!yyS=\!yyE
+ \advance \!angle -15pt
+ \repeat
+ \ifdim\!angle>\!zpt% ** complete remaining arc, if any
+ \!angle=100.53096\!angle% ** convert angle to radians, divide
+ \divide \!angle 360 % ** by 2, and multiply by 32
+ \!sinandcos\!angle\!!sin\!!cos% ** get 32*sin & 32*cos
+ \!rotate(\!xxS,\!yyS)by(\!!cos,\!sign\!!sin)to(\!xxM,\!yyM)
+ \!rotate(\!xxM,\!yyM)by(\!!cos,\!sign\!!sin)to(\!xxE,\!yyE)
+ \!xM=#1\!xxM \advance\!xM\!xxloc \!yM=#2\!yyM \advance\!yM\!yyloc
+ \!xE=#1\!xxE \advance\!xE\!xxloc \!yE=#2\!yyE \advance\!yE\!yyloc
+ \!qjoin (\!xM,\!yM) (\!xE,\!yE)
+ \fi
+%
+ \let\!M=\!MC% ** restore c/d mode
+ \ignorespaces}% ** if appropriate
+
+
+% ** \!rotate(XREG,YREG)by(32cos,32sin)to(XXREG,YYREG)
+% ** rotates (XREG,YREG) by angle with specfied scaled cos & sin to
+% ** (XXREG,YYREG). Uses \!dimenA & \!dimenB as scratch registers.
+\def\!rotate(#1,#2)by(#3,#4)to(#5,#6){%
+ \!dimenA=#3#1\advance \!dimenA -#4#2% ** Rcos(x+t)=Rcosx*cost - Rsinx*sint
+ \!dimenB=#3#2\advance \!dimenB #4#1% ** Rsin(x+t)=Rsinx*cost + Rcosx*sint
+ \divide \!dimenA 32 \divide \!dimenB 32
+ #5=\!dimenA #6=\!dimenB
+ \ignorespaces}
+\def\!sin{4.17684}% ** 32*sin(pi/24) (pi/24=7.5deg)
+\def\!cos{31.72624}% ** 32*cos(pi/24)
+
+
+% ** \!sinandcos{32*ANGLE in radians}{\SINCS}{\COSCS}
+% ** Computes the 32*sine and 32*cosine of a small ANGLE expressed in
+% ** radians/32 and puts these values in the replacement texts of
+% ** \SINCS and \COSCS
+\def\!sinandcos#1#2#3{%
+ \!dimenD=#1% ** angle is expressed in radians/32: 1pt = 1/32rad
+ \!dimenA=\!dimenD% ** dimA will eventually contain 32sin(angle)in pts
+ \!dimenB=32pt% ** dimB will eventually contain 32cos(angle)in pts
+ \!removept\!dimenD\!value% ** get value of 32*angle, without "pt"
+ \!dimenC=\!dimenD% ** holds 32*angle**i/i! in pts
+ \!dimenC=\!value\!dimenC \divide\!dimenC by 64 % ** now 32*angle**2/2
+ \advance\!dimenB by -\!dimenC% ** 32-32*angle**2/2
+ \!dimenC=\!value\!dimenC \divide\!dimenC by 96 % ** now 32*angle**3/3!
+ \advance\!dimenA by -\!dimenC% ** now 32*(angle-angle**3/6)
+ \!dimenC=\!value\!dimenC \divide\!dimenC by 128 % ** now 32*angle**4/4!
+ \advance\!dimenB by \!dimenC%
+ \!removept\!dimenA#2% ** set 32*sin(angle)
+ \!removept\!dimenB#3% ** set 32*cos(angle)
+ \ignorespaces}
+
+
+% *****************************************************************
+% *** RULES (Draws rules, i.e., horizontal & vertical lines) ***
+% *****************************************************************
+
+% ** User command:
+% ** \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1
+% ** to XCOORD2 YCOORD2
+
+% ** Internal commands:
+% ** \!puthline [<XDIMEN,YDIMEN>] (h = horizontal)
+% ** Set by dashpat to either: \!putsolidhline or \!putdashedhline
+% ** \!putvline [<XDIMEN,YDIMEN>] (v = vertical)
+% ** Either: \!putsolidvline or \!putdashedvline
+
+
+% ** \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1
+% ** to XCOORD2 YCOORD2
+% ** Draws a rule -- dashed or solid depending on the current dash pattern --
+% ** from (X1,Y1) to (X2,Y2). Uses TEK's \hrule & \vrule & \leaders
+% ** constructions to handle horizontal & vertical lines efficiently both
+% ** in terms of execution time and space in the DVI file.
+% ** See Subsection 4.1 of the manual.
+\def\putrule#1from #2 #3 to #4 #5 {%
+ \!xloc=\!M{#2}\!xunit \!xxloc=\!M{#4}\!xunit%
+ \!yloc=\!M{#3}\!yunit \!yyloc=\!M{#5}\!yunit%
+ \!dxpos=\!xxloc \advance\!dxpos by -\!xloc
+ \!dypos=\!yyloc \advance\!dypos by -\!yloc
+%
+ \ifdim\!dypos=\!zpt
+ \def\!!Line{\!puthline{#1}}\ignorespaces
+ \else
+ \ifdim\!dxpos=\!zpt
+ \def\!!Line{\!putvline{#1}}\ignorespaces
+ \else
+ \def\!!Line{}
+ \fi
+ \fi
+ \let\!ML=\!M% ** save current coord\dimen mode
+ \!setdimenmode% ** express locations in dimens
+ \!!Line%
+ \let\!M=\!ML% ** restore previous c/d mode
+ \ignorespaces}
+
+
+% ** \!putsolidhline [<XDIMEN,YDIMEN>]
+% ** Place horizontal solid line
+\def\!putsolidhline#1{%
+ \ifdim\!dxpos>\!zpt
+ \put{\!hline\!dxpos}#1[l] at {\!xloc} {\!yloc}
+ \else
+ \put{\!hline{-\!dxpos}}#1[l] at {\!xxloc} {\!yyloc}
+ \fi
+ \ignorespaces}
+
+% ** \!putsolidvline [shifted <XDIMEN,YDIMEN>]
+% ** Place vertical solid line
+\def\!putsolidvline#1{%
+ \ifdim\!dypos>\!zpt
+ \put{\!vline\!dypos}#1[b] at {\!xloc} {\!yloc}
+ \else
+ \put{\!vline{-\!dypos}}#1[b] at {\!xxloc} {\!yyloc}
+ \fi
+ \ignorespaces}
+
+\def\!hline#1{\hbox to #1{\leaders \hrule height\linethickness\hfill}}
+\def\!vline#1{\vbox to #1{\leaders \vrule width\linethickness\vfill}}
+
+
+% ** \!putdashedhline [<XDIMEN,YDIMEN>]
+% ** Place dashed horizontal line
+\def\!putdashedhline#1{%
+ \ifdim\!dxpos>\!zpt
+ \!DLsetup\!Flist\!dxpos
+ \put{\hbox to \!totalleaderlength{\!hleaders}\!hpartialpattern\!Rtrunc}
+ #1[l] at {\!xloc} {\!yloc}
+ \else
+ \!DLsetup\!Blist{-\!dxpos}
+ \put{\!hpartialpattern\!Ltrunc\hbox to \!totalleaderlength{\!hleaders}}
+ #1[r] at {\!xloc} {\!yloc}
+ \fi
+ \ignorespaces}
+
+% ** \!putdashedhline [<XDIMEN,YDIMEN>]
+% ** Place dashed vertical line
+\def\!putdashedvline#1{%
+ \!dypos=-\!dypos% ** vertical leaders go from top to bottom
+ \ifdim\!dypos>\!zpt
+ \!DLsetup\!Flist\!dypos
+ \put{\vbox{\vbox to \!totalleaderlength{\!vleaders}
+ \!vpartialpattern\!Rtrunc}}#1[t] at {\!xloc} {\!yloc}
+ \else
+ \!DLsetup\!Blist{-\!dypos}
+ \put{\vbox{\!vpartialpattern\!Ltrunc
+ \vbox to \!totalleaderlength{\!vleaders}}}#1[b] at {\!xloc} {\!yloc}
+ \fi
+ \ignorespaces}
+
+
+% ** The rest of the macros in this section are subroutines used by
+% ** \!putdashedhline and \!putdashedvline.
+\def\!DLsetup#1#2{% ** Dashed-Line set up
+ \let\!RSlist=#1% ** set !Rule-Skip list
+ \!countB=#2% ** convert rule length to integer (number of sps)
+ \!countA=\!leaderlength% ** ditto, leaderlength
+ \divide\!countB by \!countA% ** number of complete leader units
+ \!totalleaderlength=\!countB\!leaderlength
+ \!Rresiduallength=#2%
+ \advance \!Rresiduallength by -\!totalleaderlength% \** excess length
+ \!Lresiduallength=\!leaderlength
+ \advance \!Lresiduallength by -\!Rresiduallength
+ \ignorespaces}
+
+\def\!hleaders{%
+ \def\!Rule##1{\vrule height\linethickness width##1}%
+ \def\!Skip##1{\hskip##1}%
+ \leaders\hbox{\!RSlist}\hfill}
+
+\def\!hpartialpattern#1{%
+ \!dimenA=\!zpt \!dimenB=\!zpt
+ \def\!Rule##1{#1{##1}\vrule height\linethickness width\!dimenD}%
+ \def\!Skip##1{#1{##1}\hskip\!dimenD}%
+ \!RSlist}
+
+\def\!vleaders{%
+ \def\!Rule##1{\hrule width\linethickness height##1}%
+ \def\!Skip##1{\vskip##1}%
+ \leaders\vbox{\!RSlist}\vfill}
+
+\def\!vpartialpattern#1{%
+ \!dimenA=\!zpt \!dimenB=\!zpt
+ \def\!Rule##1{#1{##1}\hrule width\linethickness height\!dimenD}%
+ \def\!Skip##1{#1{##1}\vskip\!dimenD}%
+ \!RSlist}
+
+\def\!Rtrunc#1{\!trunc{#1}>\!Rresiduallength}
+\def\!Ltrunc#1{\!trunc{#1}<\!Lresiduallength}
+
+\def\!trunc#1#2#3{%
+ \!dimenA=\!dimenB
+ \advance\!dimenB by #1%
+ \!dimenD=\!dimenB \ifdim\!dimenD#2#3\!dimenD=#3\fi
+ \!dimenC=\!dimenA \ifdim\!dimenC#2#3\!dimenC=#3\fi
+ \advance \!dimenD by -\!dimenC}
+
+
+% ****************************************************************
+% *** LINEAR ARC (Draws straight lines -- solid and dashed) ***
+% ****************************************************************
+
+% ** User commands
+% ** \inboundscheckoff
+% ** \inboundscheckon
+
+% ** Internal commands
+% ** \!start (XCOORD,YCOORD)
+% ** \!ljoin (XCOORD,YCOORD)
+% ** \!drawlinearsegment -- set by \dashpat to either
+% ** \!linearsolid or \!lineardashed
+% ** \!advancedashing -- set by \dashpat to either
+% ** \relax or \!!advancedashing
+% ** \!plotifinbounds -- set by \inboundscheck off/on to either
+% ** \!plot or \!!plotifinbounds
+% ** \!initinboundscheck -- set by \inboundscheck off/on to either
+% ** \relax or \!!initinboundscheck
+
+
+% \plotsymbolspacing ** distance between consecutive plot positions
+% \!xS ** starting x
+% \!yS ** starting y
+% \!xE ** ending x
+% \!yE ** ending y
+% \!xdiff ** x_end - x_start
+% \!ydiff ** y_end - y_start
+% \!distacross ** how far along curve next point to be plotted is
+% \!arclength ** approximate length of arc for current interval
+% \!downlength ** remaining length for "pen" to be down
+% \!uplength ** length for "pen" to be down
+% \!intervalno ** counts segments to curve
+% \totalarclength ** cumulative distance along curve
+% \!npoints ** approximately (arc length / plotsymbolspacing)
+
+% ** Calls -- \!Pythag, \!divide, \!plot
+
+
+% ** \!start (XCOORD,YCOORD)
+% ** Sets initial point for linearly (or quadratically) interpolated curve
+\def\!start (#1,#2){%
+ \!plotxorigin=\!xorigin \advance \!plotxorigin by \!plotsymbolxshift
+ \!plotyorigin=\!yorigin \advance \!plotyorigin by \!plotsymbolyshift
+ \!xS=\!M{#1}\!xunit \!yS=\!M{#2}\!yunit
+ \!rotateaboutpivot\!xS\!yS
+ \!copylist\!UDlist\to\!!UDlist% **\!UDlist has the form \\{dimen1}\\{dimen2}..
+% ** Routine will draw dashed line with pen
+% ** down for dimen1, up for dimen2, ...
+ \!getnextvalueof\!downlength\from\!!UDlist
+ \!distacross=\!zpt% ** 1st point goes at start of curve
+ \!intervalno=0 % ** initialize interval counter
+ \global\totalarclength=\!zpt% ** initialize distance traveled along curve
+ \ignorespaces}
+
+
+% ** \!ljoin (XCOORD,YCOORD)
+% ** Draws a straight line starting at the last point specified
+% ** by the most recent \!start, \!ljoin, or \!qjoin, and
+% ** ending at (XCOORD,YCOORD).
+\def\!ljoin (#1,#2){%
+ \advance\!intervalno by 1
+ \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit
+ \!rotateaboutpivot\!xE\!yE
+ \!xdiff=\!xE \advance \!xdiff by -\!xS%** xdiff = xE - xS
+ \!ydiff=\!yE \advance \!ydiff by -\!yS%** ydiff = yE - yS
+ \!Pythag\!xdiff\!ydiff\!arclength% ** arclength = sqrt(xdiff**2+ydiff**2)
+ \global\advance \totalarclength by \!arclength%
+ \!drawlinearsegment% ** set by dashpat to \!linearsolid or \!lineardashed
+ \!xS=\!xE \!yS=\!yE% ** shift ending points to starting points
+ \ignorespaces}
+
+
+% ** The following routine is used to draw a "solid" line between (xS,yS)
+% ** and (xE,yE). Points are spaced nearly every \plotsymbolspacing length
+% ** along the line.
+\def\!linearsolid{%
+ \!npoints=\!arclength
+ \!countA=\plotsymbolspacing
+ \divide\!npoints by \!countA% ** now #pts =. arclength/plotsymbolspacing
+ \ifnum \!npoints<1
+ \!npoints=1
+ \fi
+ \divide\!xdiff by \!npoints
+ \divide\!ydiff by \!npoints
+ \!xpos=\!xS \!ypos=\!yS
+%
+ \loop\ifnum\!npoints>-1
+ \!plotifinbounds
+ \advance \!xpos by \!xdiff
+ \advance \!ypos by \!ydiff
+ \advance \!npoints by -1
+ \repeat
+ \ignorespaces}
+
+
+% ** The following routine is used to draw a dashed line between (xS,yS)
+% ** and (xE,yE). The dash pattern continues from the previous segment.
+\def\!lineardashed{%
+% **
+ \ifdim\!distacross>\!arclength
+ \advance \!distacross by -\!arclength %nothing to plot in this interval
+%
+ \else
+%
+ \loop\ifdim\!distacross<\!arclength
+% ** plot point, interpolating linearly in x and y
+ \!divide\!distacross\!arclength\!dimenA% ** dimA = across/arclength
+ \!removept\!dimenA\!t% ** \!t holds value in dimA, without the "pt"
+ \!xpos=\!t\!xdiff \advance \!xpos by \!xS
+ \!ypos=\!t\!ydiff \advance \!ypos by \!yS
+ \!plotifinbounds
+ \advance\!distacross by \plotsymbolspacing
+ \!advancedashing
+ \repeat
+%
+ \advance \!distacross by -\!arclength% ** prepare for next interval
+ \fi
+ \ignorespaces}
+
+
+\def\!!advancedashing{%
+ \advance\!downlength by -\plotsymbolspacing
+ \ifdim \!downlength>\!zpt
+ \else
+ \advance\!distacross by \!downlength
+ \!getnextvalueof\!uplength\from\!!UDlist
+ \advance\!distacross by \!uplength
+ \!getnextvalueof\!downlength\from\!!UDlist
+ \fi}
+
+
+% ** \inboundscheckoff & \inboundscheckon: See Subsection 5.5 of the manual.
+\def\inboundscheckoff{%
+ \def\!plotifinbounds{\!plot(\!xpos,\!ypos)}%
+ \def\!initinboundscheck{\relax}\ignorespaces}
+\def\inboundscheckon{%
+ \def\!plotifinbounds{\!!plotifinbounds}%
+ \def\!initinboundscheck{\!!initinboundscheck}%
+ \!initinboundscheck\ignorespaces}
+\inboundscheckoff
+
+% ** The following code plots the current point only if it falls in the
+% ** current plotarea. It doesn't matter if the coordinate system has
+% ** changed since the plotarea was set up. However, shifts of the plot
+% ** are ignored (how the plotsymbol stands relative to its plot position is
+% ** unknown anyway).
+\def\!!plotifinbounds{%
+ \ifdim \!xpos<\!checkleft
+ \else
+ \ifdim \!xpos>\!checkright
+ \else
+ \ifdim \!ypos<\!checkbot
+ \else
+ \ifdim \!ypos>\!checktop
+ \else
+ \!plot(\!xpos,\!ypos)
+ \fi
+ \fi
+ \fi
+ \fi}
+
+
+\def\!!initinboundscheck{%
+ \!checkleft=\!arealloc \advance\!checkleft by \!xorigin
+ \!checkright=\!arearloc \advance\!checkright by \!xorigin
+ \!checkbot=\!areabloc \advance\!checkbot by \!yorigin
+ \!checktop=\!areatloc \advance\!checktop by \!yorigin}
+
+
+% *********************************
+% *** LOGTEN (Log_10 function) ***
+% *********************************
+%
+% ** \!logten{X}
+% ** Calculates log_10 of X. X and LOG10(X) are in fixed point notation.
+% ** X must be positive; it may have an optional `+' sign; any number
+% ** of digits may be specified for X. The absolute error in LOG10(X) is
+% ** less than .0001 (probably < .00006). That's about as good as you
+% ** hope for, since TEX only operates to 5 figures after the decimal
+% ** point anyway.
+
+% \!rootten=3.162278pt **** These are values are set in ALLOCATIONS
+% \!tenAe=2.543275pt (=A5)
+% \!tenAc=2.773839pt (=A3)
+% \!tenAa=8.690286pt (=A1)
+
+\def\!logten#1#2{%
+ \expandafter\!!logten#1\!nil
+ \!removept\!dimenF#2%
+ \ignorespaces}
+
+\def\!!logten#1#2\!nil{%
+ \if -#1%
+ \!dimenF=\!zpt
+ \def\!next{\ignorespaces}%
+ \else
+ \if +#1%
+ \def\!next{\!!logten#2\!nil}%
+ \else
+ \if .#1%
+ \def\!next{\!!logten0.#2\!nil}%
+ \else
+ \def\!next{\!!!logten#1#2..\!nil}%
+ \fi
+ \fi
+ \fi
+ \!next}
+
+\def\!!!logten#1#2.#3.#4\!nil{%
+ \!dimenF=1pt % ** DimF holds log10 original argument
+ \if 0#1%
+ \!!logshift#3pt % ** Argument < 1
+ \else % ** Argument >= 1
+ \!logshift#2/% ** Shift decimal pt as many places
+ \!dimenE=#1.#2#3pt % ** as there are figures in #2
+ \fi % ** Now dimE holds revised X want log10 of
+ \ifdim \!dimenE<\!rootten% ** Transform X to XX between sqrt(10)
+ \multiply \!dimenE 10 % ** and 10*sqrt(10)
+ \advance \!dimenF -1pt
+ \fi
+ \!dimenG=\!dimenE% ** dimG <- (XX + 10)
+ \advance\!dimenG 10pt
+ \advance\!dimenE -10pt % ** dimE <- (XX - 10)
+ \multiply\!dimenE 10 % ** dimE = 10*(XX-10)
+ \!divide\!dimenE\!dimenG\!dimenE% ** Now dimE=10t==10*(XX-10)/(XX+10)
+ \!removept\!dimenE\!t% ** !t=10t, with "pt" removed
+ \!dimenG=\!t\!dimenE% ** dimG=100t**2
+ \!removept\!dimenG\!tt% ** !tt=100t**2, with "pt" removed
+ \!dimenH=\!tt\!tenAe% ** dimH=10*a5*(10t)**2 /100
+ \divide\!dimenH 100
+ \advance\!dimenH \!tenAc% ** ditto + 10*a3
+ \!dimenH=\!tt\!dimenH% ** ditto * (10t)**2 /100
+ \divide\!dimenH 100
+ \advance\!dimenH \!tenAa% ** ditto + 10*a1
+ \!dimenH=\!t\!dimenH% ** ditto * 10t / 100
+ \divide\!dimenH 100 % ** Now dimH = log10(XX) - 1
+ \advance\!dimenF \!dimenH}% ** dimF = log10(X)
+
+\def\!logshift#1{%
+ \if #1/%
+ \def\!next{\ignorespaces}%
+ \else
+ \advance\!dimenF 1pt
+ \def\!next{\!logshift}%
+ \fi
+ \!next}
+
+ \def\!!logshift#1{%
+ \advance\!dimenF -1pt
+ \if 0#1%
+ \def\!next{\!!logshift}%
+ \else
+ \if p#1%
+ \!dimenF=1pt
+ \def\!next{\!dimenE=1p}%
+ \else
+ \def\!next{\!dimenE=#1.}%
+ \fi
+ \fi
+ \!next}
+
+
+% ***********************************************************
+% *** PICTURES (Basic setups for PiCtures; \put commands) ***
+% ***********************************************************
+
+% ** User Commands:
+% ** \beginpicture
+% ** \endpicture
+% ** \endpicturesave <XREG,YREG>
+% ** \setcoordinatesystem units <XUNIT,YUNIT> point at XREF YREF
+% ** \put {OBJECT} [ORIENTATION] <XSHIFT,YSHIFT> at XCOORD YCOORD
+% ** \multiput {OJBECT} [ORIENTATION] <XSHIFT,YSHIFT>) at
+% ** XCOORD YCOORD
+% ** *NUMBER_OF_TIMES DXCOORD DYCOORD /
+% ** \accountingon
+% ** \accountingoff
+% ** \stack [ORIENTATION] <LEADING> {LIST OF ITEMS}
+% ** \lines [ORIENTATION] {LINES}
+% ** \Lines [ORIENTATION] {LINES}
+% ** \setdimensionmode
+% ** \setcoordinatemode
+% ** \Xdistance
+% ** \Ydistance
+
+% ** Internal commands:
+% ** \!setputobject{OBJECT}{[ORIENTATION]<XSHIFT,YSHIFT>}
+% ** \!dimenput{OBJECT}[ORIENTATION]<XSHIFT,YSHIFT>(XDIMEN,YDIMEN)
+% ** \!setdimenmode
+% ** \!setcoordmode
+% ** \!ifdimenmode
+% ** \!ifcoordmode
+
+
+% ** \beginpicture
+% ** \endpicture
+% ** \endpicturesave <XREG,YREG>
+% ** \beginpicture ... \endpicture creates an hbox. Objects are
+% ** placed in this box using the \put command and the like (see below).
+% ** The location of an object is specified in terms of coordinate system(s)
+% ** established by \setcoordinatesystem. Each coordinate system (there
+% ** might be just one) specifies the length of 1 horizontal unit, the length
+% ** of 1 vertical unit, and the coordinates of a "reference point". The
+% ** reference points of various coordinate systems will be in the same
+% ** physical location. The macros keep track of the size of the objects
+% ** and their locations. The resulting hbox is the smallest hbox which
+% ** encloses all the objects, and whose TEK reference point is the point
+% ** on the left edge of the box closest vertically to the PICTEX reference
+% ** point. Using \endpicturesave, you can (globally) save the distance TEK's
+% ** reference point is to the right (respectively, up from) PICTEX's
+% ** reference point in the dimension register \XREG (respectively \YREG).
+% ** You can then \put the picture OBJECT into a larger picture so that its
+% ** reference point is at (XCOORD,YCOORD) with the command
+% ** \put {picture OBJECT} [Bl] <\XREG, \YREG> at XCOORD YCOORD
+
+% ** \beginpicture : See Subsection 1.1 of the manual.
+\def\beginpicture{%
+ \setbox\!picbox=\hbox\bgroup%
+ \!xleft=\maxdimen
+ \!xright=-\maxdimen
+ \!ybot=\maxdimen
+ \!ytop=-\maxdimen}
+
+% ** \endpicture : See Subsection 1.1 of the manual.
+\def\endpicture{%
+ \ifdim\!xleft=\maxdimen% ** check if nothing was put in picbox
+ \!xleft=\!zpt \!xright=\!zpt \!ybot=\!zpt \!ytop=\!zpt
+ \fi
+ \global\!Xleft=\!xleft \global\!Xright=\!xright
+ \global\!Ybot=\!ybot \global\!Ytop=\!ytop
+ \egroup%
+ \ht\!picbox=\!Ytop \dp\!picbox=-\!Ybot
+ \ifdim\!Ybot>\!zpt
+ \else
+ \ifdim\!Ytop<\!zpt
+ \!Ybot=\!Ytop
+ \else
+ \!Ybot=\!zpt
+ \fi
+ \fi
+ \hbox{\kern-\!Xleft\lower\!Ybot\box\!picbox\kern\!Xright}}
+
+% ** \endpicturesave : See Subsection 8.4 of the manual.
+\def\endpicturesave <#1,#2>{%
+ \endpicture \global #1=\!Xleft \global #2=\!Ybot \ignorespaces}
+
+
+% ** \setcoordinatesystem units <XUNIT,YUNIT>
+% ** point at XREF YREF
+% ** Each of `units <XUNIT,YUNIT>' and `point at XREF YREF'
+% ** are optional.
+% ** Unit lengths must be given in dimensions (e.g., <10pt,1in>).
+% ** Default unit lengths are 1pt, 1pt, or previous unit lengths.
+% ** Reference point is specified in current units (e.g., 3 5 ).
+% ** Default reference point is 0 0 , or previous reference point.
+% ** Unit lengths and reference points obey TEX's scoping rules.
+% ** See Subsection 1.2 of the manual.
+\def\setcoordinatesystem{%
+ \!ifnextchar{u}{\!getlengths }
+ {\!getlengths units <\!xunit,\!yunit>}}
+\def\!getlengths units <#1,#2>{%
+ \!xunit=#1\relax
+ \!yunit=#2\relax
+ \!ifcoordmode
+ \let\!SCnext=\!SCccheckforRP
+ \else
+ \let\!SCnext=\!SCdcheckforRP
+ \fi
+ \!SCnext}
+\def\!SCccheckforRP{%
+ \!ifnextchar{p}{\!cgetreference }
+ {\!cgetreference point at {\!xref} {\!yref} }}
+\def\!cgetreference point at #1 #2 {%
+ \edef\!xref{#1}\edef\!yref{#2}%
+ \!xorigin=\!xref\!xunit \!yorigin=\!yref\!yunit
+ \!initinboundscheck % ** See linear.tex
+ \ignorespaces}
+\def\!SCdcheckforRP{%
+ \!ifnextchar{p}{\!dgetreference}%
+ {\ignorespaces}}
+\def\!dgetreference point at #1 #2 {%
+ \!xorigin=#1\relax \!yorigin=#2\relax
+ \ignorespaces}
+
+
+% ** \put {OBJECT} [XY] <XDIMEN,YDIMEN> at (XCOORD,YCOORD)
+% ** `[XY]' and `<XDIMEN,YDIMEN>' are optional.
+% ** First OBJECT is placed in an hbox (the "objectbox") and then a
+% ** "reference point" is assigned to the objectbox as follows:
+% ** [1] first, the reference point is taken to be the center of the box;
+% ** [2] next, centering is overridden by the specifications
+% ** X=l -- reference point along the left edge of the objectbox
+% ** X=r -- reference point along the right edge of the objectbox
+% ** Y=b -- reference point along the bottom edge of the objectbox
+% ** Y=B -- reference point along the Baseline of the objectbox
+% ** Y=t -- reference point along the top edge of the objectbox;
+% ** [3] finally the reference point is shifted left by XDIMEN, down
+% ** by YDIMEN (both default to 0pt).
+% ** The objectbox is placed within PICBOX with its reference point at
+% ** (XCOORD,YCOORD).
+% ** If OBJECT is a saved box, say box0, you have to write
+% ** \put{\box0}... or \put{\copy0}...
+% ** The objectbox is void after the put.
+% ** See Subsection 2.1 of the manual.
+\long\def\put#1#2 at #3 #4 {%
+ \!setputobject{#1}{#2}%
+ \!xpos=\!M{#3}\!xunit \!ypos=\!M{#4}\!yunit
+ \!rotateaboutpivot\!xpos\!ypos%
+ \advance\!xpos -\!xorigin \advance\!xpos -\!xshift
+ \advance\!ypos -\!yorigin \advance\!ypos -\!yshift
+ \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos%
+ \!doaccounting\ignorespaces}
+
+% ** \multiput etc. Like \put. The objectbox is not voided until the
+% ** termininating /, and is placed repeatedly with:
+% ** XCOORD YCOORD -- the objectbox is put down with its reference point
+% ** at (XCOORD,YCOORD);
+% ** *N DXCOORD DYCOORD -- each of N times the current
+% ** (xcoord,ycoord) is incremented by (DXCOORD,DYCOORD), and the
+% ** objectbox is put down with its reference point at (xcoord,ycoord)
+% ** (This specification has to follow an XCOORD YCOORD pair)
+% ** See Subsection 2.2 of the manual.
+\long\def\multiput #1#2 at {%
+ \!setputobject{#1}{#2}%
+ \!ifnextchar"{\!putfromfile}{\!multiput}}
+\def\!putfromfile"#1"{%
+ \expandafter\!multiput \input #1 /}
+\def\!multiput{%
+ \futurelet\!nextchar\!!multiput}
+\def\!!multiput{%
+ \if *\!nextchar
+ \def\!nextput{\!alsoby}%
+ \else
+ \if /\!nextchar
+ \def\!nextput{\!finishmultiput}%
+ \else
+ \def\!nextput{\!alsoat}%
+ \fi
+ \fi
+ \!nextput}
+\def\!finishmultiput/{%
+ \setbox\!putobject=\hbox{}%
+ \ignorespaces}
+
+% ** \!alsoat XCOORD YCOORD
+% ** The objectbox is put down with reference point at XCOORD,YCOORD
+\def\!alsoat#1 #2 {%
+ \!xpos=\!M{#1}\!xunit \!ypos=\!M{#2}\!yunit
+ \!rotateaboutpivot\!xpos\!ypos%
+ \advance\!xpos -\!xorigin \advance\!xpos -\!xshift
+ \advance\!ypos -\!yorigin \advance\!ypos -\!yshift
+ \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
+ \!doaccounting
+ \!multiput}
+
+% ** \!alsoby*N DXCOORD DYCOORD
+% ** N times, the current (XCOORD,YCOORD) is advanced by (DXCOORD,DYCOORD),
+% ** and the current (shifted, oriented) OBJECT is put down.
+\def\!alsoby*#1 #2 #3 {%
+ \!dxpos=\!M{#2}\!xunit \!dypos=\!M{#3}\!yunit
+ \!rotateonly\!dxpos\!dypos
+ \!ntemp=#1%
+ \!!loop\ifnum\!ntemp>0
+ \advance\!xpos by \!dxpos \advance\!ypos by \!dypos
+ \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos%
+ \advance\!ntemp by -1
+ \repeat
+ \!doaccounting
+ \!multiput}
+
+% ** \accountingoff : Suspends PiCTeX's accounting of the aggregate
+% ** size of the picture box.
+% ** \accounting on : Reinstates accounting.
+% ** See Subsection 8.2 of the manual.
+\def\accountingon{\def\!doaccounting{\!!doaccounting}\ignorespaces}
+\def\accountingoff{\def\!doaccounting{}\ignorespaces}
+\accountingon
+\def\!!doaccounting{%
+ \!xtemp=\!xpos
+ \!ytemp=\!ypos
+ \ifdim\!xtemp<\!xleft
+ \!xleft=\!xtemp
+ \fi
+ \advance\!xtemp by \!wd
+ \ifdim\!xright<\!xtemp
+ \!xright=\!xtemp
+ \fi
+ \advance\!ytemp by -\!dp
+ \ifdim\!ytemp<\!ybot
+ \!ybot=\!ytemp
+ \fi
+ \advance\!ytemp by \!dp
+ \advance\!ytemp by \!ht
+ \ifdim\!ytemp>\!ytop
+ \!ytop=\!ytemp
+ \fi}
+
+\long\def\!setputobject#1#2{%
+ \setbox\!putobject=\hbox{#1}%
+ \!ht=\ht\!putobject \!dp=\dp\!putobject \!wd=\wd\!putobject
+ \wd\!putobject=\!zpt
+ \!xshift=.5\!wd \!yshift=.5\!ht \advance\!yshift by -.5\!dp
+ \edef\!putorientation{#2}%
+ \expandafter\!SPOreadA\!putorientation[]\!nil%
+ \expandafter\!SPOreadB\!putorientation<\!zpt,\!zpt>\!nil\ignorespaces}
+
+\def\!SPOreadA#1[#2]#3\!nil{\!etfor\!orientation:=#2\do\!SPOreviseshift}
+
+\def\!SPOreadB#1<#2,#3>#4\!nil{\advance\!xshift by -#2\advance\!yshift by -#3}
+
+\def\!SPOreviseshift{%
+ \if l\!orientation
+ \!xshift=\!zpt
+ \else
+ \if r\!orientation
+ \!xshift=\!wd
+ \else
+ \if b\!orientation
+ \!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}
+
+\font\fiverm=cmr5
+\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\!ymidpt{\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
diff --git a/graphics/pictex/addon/pictexzusatz.txt b/graphics/pictex/addon/pictexzusatz.txt new file mode 100644 index 0000000000..8aaa54b2e7 --- /dev/null +++ b/graphics/pictex/addon/pictexzusatz.txt @@ -0,0 +1,16 @@ +PICTEX.STY + Style zum Einladen von PiCTeX als LaTeX-option oder LaTeX-Package. + Incl. Einladen von PICCORR.STY und PICMORE.STY, falls vorhanden. + +PICCORR.STY + Korrektur zu PiCTeXs \betweenarrows-Befehl + +PICMORE.STY + Erweiterung zu PiCTeX f"ur Impulsdiagramme + +PICTEXWD.TEX + Gepatchtes PICTEX.TEX, das weniger Dimensionsregister benutzt. + Fehlermeldungen an Andreas.Schrell@RS.maus.de + +PICTEXWD.STY + Wie PICTEX.STY, aber es wird PICTEXWD.TEX eingeladen. diff --git a/graphics/pictex/errorbars.tex b/graphics/pictex/errorbars.tex new file mode 100644 index 0000000000..0f9271bfeb --- /dev/null +++ b/graphics/pictex/errorbars.tex @@ -0,0 +1,117 @@ +% +% TeX macros to plot error bars with the PicTeX macros. +% +% These macros are largely derived from the examples in the back +% of the PiCTeX manual. +% +% To plot with a mark at each data point, simply say +% +% \plotWith mark M at x1 y1 x2 y2 .... xN yN / +% +% where "M" is a mark character {e.g. $\bullet$} +% +% To include error bars in the plot, say: +% +% \plotWithErrorBars mark M at +% x1 y1 e1 +% x2 y2 e2 .... xN yN eN +% / +% +% The line-breaking isn't needed. Marks are placed on the graph +% at (xi, yi) for each data point. Vertical error bars are drawn +% from (xi, yi + ei) to (xi, yi - ei). +% +% The cross-bar at the top and bottom of the error bars is normally +% 5 pts, but can be changed by setting the \crossbarlength dimen. +% +% +% Dirk Grunwald Apr 20 1988 +% +% +\newdimen\dyposition +\newdimen\crossbarlength +\crossbarlength=5pt +\newdimen\lastPlotX +\newdimen\lastPlotY +\newdimen\tmpPlotX +\newdimen\tmpPlotY +% +% +\def\plotErrorBar#1 #2 #3 #4{% + \message{ Plot #4 at #1 #2 }% + \put {#4} at {#1} {#2} + \dyposition=\Ydistance{#3} + \put{% + \vbox{% + \hsize=\crossbarlength% + \hrule height \linethickness% + \vskip -.5\linethickness% + \centerline{\vrule width \linethickness height 2\dyposition}% + \nointerlineskip% + \vskip -.5\linethickness% + \hrule height \linethickness}% + } at {#1} {#2} } +% +\def\plotWithErrorBars mark #1 at #2 #3 #4 {% + \def\errorBarMark{#1}% + % + % plot first point + % + \plotErrorBar {#2} {#3} {#4} {\errorBarMark} + \lastPlotX=\Xdistance{#2}% + \lastPlotY=\Ydistance{#3}% + \futurelet\nextcharacter\plotErrorBarLoop} +% +\def\plotErrorBarLoop{% + \if/\nextcharacter% + \def\plotErrorBarAction{\plotErrorBarFinish}% + \else% + \def\plotErrorBarAction{\plotErrorBarContinued}% + \fi% + \plotErrorBarAction} +% +\def\plotErrorBarFinish/ {} +% +\def\plotErrorBarContinued#1 #2 #3 {% + \plotErrorBar {#1} {#2} {#3} {\errorBarMark}% + \tmpPlotX = \Xdistance{#1}% + \tmpPlotY = \Ydistance{#2}% + \setdimensionmode% + \plot {\lastPlotX} {\lastPlotY} {\tmpPlotX} {\tmpPlotY} / + \setcoordinatemode% + \lastPlotX = \tmpPlotX% + \lastPlotY = \tmpPlotY% + \futurelet\nextcharacter\plotErrorBarLoop} +% +\def\plotWith mark #1 at #2 #3 {% + \def\plotWithMark{#1}% + % + % plot first point + % + \message{Plot {\plotWithMark} at #2 #3}% + \put {\plotWithMark} at {#2} {#3} + \lastPlotX=\Xdistance{#2}% + \lastPlotY=\Ydistance{#3}% + \futurelet\nextcharacter\plotWithLoop} +% +\def\plotWithLoop{% + \if/\nextcharacter% + \def\plotWithAction{\plotWithFinish}% + \else% + \def\plotWithAction{\plotWithContinued}% + \fi% + \plotWithAction} +% +\def\plotWithFinish/ {} +% +\def\plotWithContinued#1 #2 {% + \message{ Plot {\plotWithMark} at #1 #2}% + \put {\plotWithMark} at {#1} {#2} + \tmpPlotX = \Xdistance{#1}% + \tmpPlotY = \Ydistance{#2}% + \setdimensionmode% + \plot {\lastPlotX} {\lastPlotY} {\tmpPlotX} {\tmpPlotY} / + \setcoordinatemode% + \lastPlotX = \tmpPlotX% + \lastPlotY = \tmpPlotY% + \futurelet\nextcharacter\plotWithLoop} diff --git a/graphics/pictex/latexpicobjs.tex b/graphics/pictex/latexpicobjs.tex new file mode 100644 index 0000000000..2b945dd5bc --- /dev/null +++ b/graphics/pictex/latexpicobjs.tex @@ -0,0 +1,482 @@ +% This is latexpicobjs.tex, Version 1.1 9/11/87 + +% This file makes the LaTeX line, vector, circle, and oval constructions +% available to PiCTeX users who are running under plain TeX. +% It is distributed with Leslie Lamport's permission. + +% Do not \input the files prepictex.tex and postpictex.tex along with +% this file. + +\catcode`@=11 \catcode`!=11 + +% Save the meaning of plain TeX's \line command +\let\!texline=\line + +% load LaTeX line and circle fonts +\font\tenln=line10 +\font\tenlnw=linew10 +\font\tencirc=circle10 +\font\tencircw=circlew10 + +% set up LaTeX hacks +\let\@tfor=\!tfor +\let\@ifnextchar=\!ifnextchar + +\def\@whilenoop#1{} +\def\@whiledim#1\do #2{\ifdim #1\relax#2\@iwhiledim{#1\relax#2}\fi} +\def\@iwhiledim#1{\ifdim #1\let\@nextwhile=\@iwhiledim + \else\let\@nextwhile=\@whilenoop\fi\@nextwhile{#1}} + +\def\@ifstar#1#2{\@ifnextchar *{\def\@tempa*{#1}\@tempa}{#2}} + +\def\@height{height} +\def\@depth{depth} +\def\@width{width} + + +% The following are slightly modified versions of the LaTeX +% \@badlinearg and \@warning commands. +\def\!@badlinearg{% + \errmessage{Bad LaTeX \string\line\space or \string\vector + \space argument. See the LaTeX manual for an explanation.}} +\def\!@warning#1{\immediate\write16{LaTeX Warning: #1.}\ignorespaces} + +% allocate registers +\newdimen\@tempdima +\newdimen\@tempdimb +\newcount\@tempcnta +\newcount\@tempcntb +\newbox\@tempboxa + +% Until further notice (near the end) what follows are +% (slightly modified versions of) LaTeX's line/vector/circle/oval macros. +% See the latex.tex macro package for commentary. +\newdimen\@wholewidth +\newdimen\@halfwidth +\newdimen\unitlength \unitlength =1pt + +\def\thinlines{% + \let\@linefnt\tenln \let\@circlefnt\tencirc + \@wholewidth\fontdimen8\tenln \@halfwidth .5\@wholewidth} +\def\thicklines{% + \let\@linefnt\tenlnw \let\@circlefnt\tencircw + \@wholewidth\fontdimen8\tenlnw \@halfwidth .5\@wholewidth} + +\newif\if@negarg + +\def\line(#1,#2)#3{% + \@xarg #1\relax + \@yarg #2\relax + \@linelen=#3\unitlength + \ifnum\@xarg =0 + \@vline + \else + \ifnum\@yarg =0 + \@hline + \else + \@sline + \fi + \fi} + +\def\@sline{% + \ifnum\@xarg< 0 + \@negargtrue + \@xarg -\@xarg + \@yyarg -\@yarg + \else + \@negargfalse + \@yyarg \@yarg + \fi + \ifnum \@yyarg >0 + \@tempcnta\@yyarg + \else + \@tempcnta -\@yyarg + \fi + \ifnum\@tempcnta>6 + \!@badlinearg + \@tempcnta0 + \fi + \ifnum\@xarg>6 + \!@badlinearg + \@xarg 1 + \fi + \setbox\@linechar\hbox{\@linefnt\@getlinechar(\@xarg,\@yyarg)}% + \ifnum \@yarg >0 + \let\@upordown\raise + \@clnht\z@ + \else + \let\@upordown\lower + \@clnht \ht\@linechar + \fi + \@clnwd=\wd\@linechar + \if@negarg + \hskip -\wd\@linechar + \def\@tempa{\hskip -2\wd\@linechar}% + \else + \let\@tempa\relax + \fi + \@whiledim \@clnwd <\@linelen \do + {\@upordown\@clnht\copy\@linechar + \@tempa + \advance\@clnht \ht\@linechar + \advance\@clnwd \wd\@linechar}% + \advance\@clnht -\ht\@linechar + \advance\@clnwd -\wd\@linechar + \@tempdima\@linelen + \advance\@tempdima -\@clnwd + \@tempdimb\@tempdima + \advance\@tempdimb -\wd\@linechar + \if@negarg + \hskip -\@tempdimb + \else + \hskip \@tempdimb + \fi + \multiply\@tempdima \@m + \@tempcnta \@tempdima + \@tempdima \wd\@linechar + \divide\@tempcnta \@tempdima + \@tempdima \ht\@linechar + \multiply\@tempdima \@tempcnta + \divide\@tempdima \@m + \advance\@clnht \@tempdima + \ifdim \@linelen <\wd\@linechar + \hskip \wd\@linechar + \else + \@upordown\@clnht\copy\@linechar + \fi} + +\def\@hline{% + \ifnum \@xarg <0 \hskip -\@linelen \fi + \vrule \@height \@halfwidth \@depth \@halfwidth \@width \@linelen + \ifnum \@xarg <0 \hskip -\@linelen \fi} + +\def\@getlinechar(#1,#2){% + \@tempcnta#1\relax + \multiply\@tempcnta 8 + \advance\@tempcnta -9 + \ifnum #2>0 + \advance\@tempcnta #2\relax + \else + \advance\@tempcnta -#2\relax + \advance\@tempcnta 64 + \fi + \char\@tempcnta} + +\def\vector(#1,#2)#3{% + \@xarg #1\relax + \@yarg #2\relax + \@tempcnta \ifnum\@xarg<0 -\@xarg\else\@xarg\fi + \ifnum\@tempcnta<5\relax + \@linelen=#3\unitlength + \ifnum\@xarg =0 + \@vvector + \else + \ifnum\@yarg =0 + \@hvector + \else + \@svector + \fi + \fi + \else + \!@badlinearg + \fi} + +\def\@hvector{% + \@hline + \hbox to 0pt{% + \@linefnt + \ifnum \@xarg <0 + \@getlarrow(1,0)\hss + \else + \hss\@getrarrow(1,0)% + \fi}} + +\def\@vvector{\ifnum \@yarg <0 \@downvector \else \@upvector \fi} + +\def\@svector{% + \@sline + \@tempcnta\@yarg + \ifnum\@tempcnta <0 + \@tempcnta=-\@tempcnta + \fi + \ifnum\@tempcnta <5 + \hskip -\wd\@linechar + \@upordown\@clnht \hbox{% + \@linefnt + \if@negarg + \@getlarrow(\@xarg,\@yyarg) + \else + \@getrarrow(\@xarg,\@yyarg) + \fi}% + \else + \!@badlinearg + \fi} + +\def\@getlarrow(#1,#2){% + \ifnum #2 =\z@ + \@tempcnta='33 + \else + \@tempcnta=#1\relax + \multiply\@tempcnta \sixt@@n + \advance\@tempcnta -9 + \@tempcntb=#2\relax + \multiply\@tempcntb \tw@ + \ifnum \@tempcntb >0 + \advance\@tempcnta \@tempcntb\relax + \else\advance\@tempcnta -\@tempcntb + \advance\@tempcnta 64 + \fi + \fi + \char\@tempcnta} + +\def\@getrarrow(#1,#2){% + \@tempcntb=#2\relax + \ifnum\@tempcntb < 0 + \@tempcntb=-\@tempcntb\relax + \fi + \ifcase \@tempcntb\relax + \@tempcnta='55 + \or + \ifnum #1<3 + \@tempcnta=#1\relax + \multiply\@tempcnta 24 + \advance\@tempcnta -6 + \else + \ifnum #1=3 + \@tempcnta=49 + \else + \@tempcnta=58 + \fi + \fi + \or + \ifnum #1<3 + \@tempcnta=#1\relax + \multiply\@tempcnta 24 + \advance\@tempcnta -3 + \else + \@tempcnta=51 + \fi + \or + \@tempcnta=#1\relax + \multiply\@tempcnta \sixt@@n + \advance\@tempcnta -\tw@ + \else + \@tempcnta=#1\relax + \multiply\@tempcnta \sixt@@n + \advance\@tempcnta 7 + \fi + \ifnum #2<0 + \advance\@tempcnta 64 + \fi + \char\@tempcnta} + +\def\@vline{% + \ifnum \@yarg <0 + \@downline + \else + \@upline + \fi} + +\def\@upline{% + \hbox to \z@{% + \hskip -\@halfwidth + \vrule \@width \@wholewidth \@height \@linelen \@depth \z@\hss}} + +\def\@downline{% + \hbox to \z@{% + \hskip -\@halfwidth + \vrule \@width \@wholewidth \@height \z@ \@depth \@linelen \hss}} + +\def\@upvector{% + \@upline + \setbox\@tempboxa\hbox{% + \@linefnt\char'66}% + \raise \@linelen \hbox to\z@{\lower \ht\@tempboxa\box\@tempboxa\hss}} + +\def\@downvector{% + \@downline + \lower \@linelen \hbox to \z@{\@linefnt\char'77\hss}} + + +\newif\if@ovt +\newif\if@ovb +\newif\if@ovl +\newif\if@ovr +\newdimen\@ovxx +\newdimen\@ovyy +\newdimen\@ovdx +\newdimen\@ovdy +\newdimen\@ovro +\newdimen\@ovri + +\def\@getcirc#1{% + \@tempdima #1\relax + \@tempcnta\@tempdima + \@tempdima 4pt\relax + \divide\@tempcnta\@tempdima + \ifnum \@tempcnta > 10\relax + \@tempcnta 10\relax + \fi + \ifnum \@tempcnta >\z@ + \advance\@tempcnta \m@ne + \else + \!@warning{Oval too small}% + \fi + \multiply\@tempcnta 4\relax + \setbox \@tempboxa \hbox{\@circlefnt \char \@tempcnta}% + \@tempdima \wd \@tempboxa} + +\def\@put#1#2#3{% + \raise #2\hbox to \z@{\hskip #1#3\hss}} + +\def\oval(#1,#2){% + \@ifnextchar[{\@oval(#1,#2)}{\@oval(#1,#2)[]}} + +\def\@oval(#1,#2)[#3]{% + \begingroup + \boxmaxdepth \maxdimen + \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue + \@tfor\@tempa :=#3\do{% + \csname @ov\@tempa false\endcsname}% + \@ovxx #1\unitlength + \@ovyy #2\unitlength + \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi + \@getcirc \@tempdimb + \@ovro \ht\@tempboxa + \@ovri \dp\@tempboxa + \@ovdx\@ovxx + \advance\@ovdx -\@tempdima + \divide\@ovdx \tw@ + \@ovdy\@ovyy + \advance\@ovdy -\@tempdima + \divide\@ovdy \tw@ + \@circlefnt + \setbox\@tempboxa \hbox{% + \if@ovr + \@ovvert32\kern -\@tempdima + \fi + \if@ovl + \kern \@ovxx + \@ovvert01\kern -\@tempdima + \kern -\@ovxx + \fi + \if@ovt + \@ovhorz \kern -\@ovxx + \fi + \if@ovb + \raise \@ovyy \@ovhorz + \fi}% + \advance\@ovdx\@ovro + \advance\@ovdy\@ovro + \ht\@tempboxa\z@ + \dp\@tempboxa\z@ + \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}% + \endgroup} + +\def\@ovvert#1#2{% + \vbox to \@ovyy{% + \if@ovb + \@tempcntb \@tempcnta + \advance \@tempcntb by #1\relax + \kern -\@ovro + \hbox{\char \@tempcntb}% + \nointerlineskip + \else + \kern \@ovri + \kern \@ovdy + \fi + \leaders\vrule width \@wholewidth\vfil + \nointerlineskip + \if@ovt + \@tempcntb \@tempcnta + \advance \@tempcntb by #2\relax + \hbox{\char \@tempcntb}% + \else + \kern \@ovdy + \kern \@ovro + \fi}} + +\def\@ovhorz{% + \hbox to \@ovxx{% + \kern \@ovro + \if@ovr + \else + \kern \@ovdx + \fi + \leaders \hrule height \@wholewidth \hfil + \if@ovl + \else + \kern \@ovdx + \fi + \kern \@ovri}} + +\def\circle{% + \@ifstar{\@dot}{\@circle}} +\def\@circle#1{% + \begingroup + \boxmaxdepth \maxdimen + \@tempdimb #1\unitlength + \ifdim \@tempdimb >15.5pt\relax + \@getcirc\@tempdimb + \@ovro\ht\@tempboxa + \setbox\@tempboxa\hbox{% + \@circlefnt + \advance\@tempcnta\tw@ + \char \@tempcnta + \advance\@tempcnta\m@ne + \char \@tempcnta + \kern -2\@tempdima + \advance\@tempcnta\tw@ + \raise \@tempdima \hbox{\char\@tempcnta}% + \raise \@tempdima \box\@tempboxa}% + \ht\@tempboxa\z@ + \dp\@tempboxa\z@ + \@put{-\@ovro}{-\@ovro}{\box\@tempboxa}% + \else + \@circ\@tempdimb{96}% + \fi + \endgroup} + +\def\@dot#1{% + \@tempdimb #1\unitlength + \@circ\@tempdimb{112}} + +\def\@circ#1#2{% + \@tempdima #1\relax + \advance\@tempdima .5pt\relax + \@tempcnta\@tempdima + \@tempdima 1pt\relax + \divide\@tempcnta\@tempdima + \ifnum\@tempcnta > 15\relax + \@tempcnta 15\relax \fi + \ifnum + \@tempcnta >\z@ + \advance\@tempcnta\m@ne + \fi + \advance\@tempcnta #2\relax + \@circlefnt + \char\@tempcnta} + +\thinlines + +\newcount\@xarg +\newcount\@yarg +\newcount\@yyarg +\newcount\@multicnt +\newdimen\@xdim +\newdimen\@ydim +\newbox\@linechar +\newdimen\@linelen +\newdimen\@clnwd +\newdimen\@clnht + +% That's the end of the definitions of lines/vectors/circles/ovals. + + +% Save LaTeX's meaning of \line +\let\!latexline=\line + +% Set variable meaning of line +\def\line{\!ifnextchar(\!latexline\!texline} + +\catcode`@=12 \catcode`!=12 diff --git a/graphics/pictex/pictex.tex b/graphics/pictex/pictex.tex new file mode 100644 index 0000000000..05624c7ad5 --- /dev/null +++ b/graphics/pictex/pictex.tex @@ -0,0 +1,3679 @@ +% This is PiCTeX, Version 1.1 9/21/87 + +% CAVEAT: The PiCTeX manual often has a more lucid explanation +% of any given topic than you will find in the internal documentation +% of the macros. + +% PiCTeX's commands can be classified into two groups: (1) public (or +% external), and (2) private (or internal). The public macros are +% discussed at length in the manual. The only discussion of the private +% macros is the internal documentation. The private macros all have +% names beginning with an exclamation point (!) of category code 11. +% Since in normal usage "!" has category code 12, these macros can't +% be accessed or modified by the general user. + +% The macros are organized into thematically related groups. For example, +% the macros dealing with dots & dashes are all in the DASHPATTERN group. +% The table below shows which macros are in which groups. The table +% covers all public macros, and many (but not all) of PiCTeX's upper level +% private macros. Following the table, the various groups are listed +% in the order in which they appear in the table. + +% *********************** TABLE OF GROUPS OF MACROS ********************** + +% HACKS: Utility macros +% \PiC +% \PiCTeX +% \placevalueinpts +% \!!loop +% \!cfor +% \!copylist +% \!ecfor +% \!etfor +% \!getnext +% \!getnextvalueof +% \!ifempty +% \!ifnextchar +% \!leftappend +% \!listaddon +% \!loop +% \!lop +% \!mlap +% \!not +% \!removept +% \!rightappend +% \!tfor +% \!vmlap +% \!wlet + +% ALLOCATION: Allocates registers + +% AREAS: Deals with plot areas +% \axis +% \grid +% \invisibleaxes +% \normalgraphs +% \plotheading +% \setplotarea +% \visibleaxes + +% ARROWS: Draws arrows +% \arrow +% \betweenarrows + +% BARS: Draws bars +% \putbar +% \setbars + +% BOXES: Draws rectangles +% \frame +% \putrectangle +% \rectangle +% \shaderectangleson +% \shaderectanglesoff + +% CURVES: Upper level plot commands +% \hshade +% \plot +% \sethistograms +% \setlinear +% \setquadratic +% \vshade + +% DASHPATTERNS: Sets up dash patterns +% \findlength +% \setdashes +% \setdashesnear +% \setdashpattern +% \setdots +% \setdotsnear +% \setsolid +% \!dashingoff +% \!dashingon + +% DIVISION: Does long division of dimension registers +% \Divide +% \!divide + +% ELLIPSES: Draws ellipses and circles +% \circulararc +% \ellipticalarc + +% RULES: Draws rules, i.e., horizontal & vertical lines +% \putrule +% \!putdashedhline +% \!putdashedvline +% \!puthline +% \!putsolidhline +% \!putsolidvline +% \!putvline + +% LINEAR ARC: Draws straight lines -- solid and dashed +% \inboundscheckoff +% \inboundscheckon +% \!advancedashing +% \!drawlinearsegment +% \!initinboundscheck +% \!linearsolid +% \!lineardashed +% \!ljoin +% \!plotifinbounds +% \!start + +% LOGTEN: Log_10 function +% \!logten + +% PICTURES: Basic setups for PiCtures; \put commands +% \accountingoff +% \accountingon +% \beginpicture +% \endpicture +% \endpicturesave +% \lines +% \multiput +% \put +% \setcoordinatemode +% \setcoordinatesystem +% \setdimensionmode +% \stack +% \Lines +% \Xdistance +% \Ydistance +% \!dimenput +% \!ifcoordmode +% \!ifdimenmode +% \!setcoordmode +% \!setdimenmode +% \!setputobject + +% PLOTTING: Things to do with plotting +% \dontsavelinesandcurves +% \replot +% \savelinesandcurves +% \setplotsymbol +% \writesavefile +% \!plot + +% PYTHAGORAS: Euclidean distance function +% \placehypotenuse +% \!Pythag + +% QUADRATIC ARC: Draws a quadratic arc +% \!qjoin + +% ROTATIONS: Handles rotations +% \startrotation +% \stoprotation +% \!rotateaboutpivot +% \!rotateonly + +% SHADING: Handles shading +% \setshadegrid +% \setshadesymbol +% \!lshade +% \!qshade +% \!starthshade +% \!startvshade + +% TICKS: Draws ticks on graphs +% \gridlines +% \loggedticks +% \nogridlines +% \ticksin +% \ticksout +% \unloggesticks + +% ***************** END OF TABLE OF GROUPS OF MACROS ******************** + + +\catcode`!=11 % ***** THIS MUST NEVER BE OMITTED +% ******************************* +% *** HACKS (Utility macros) *** +% ******************************* + +% ** User commands +% ** \PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC} +% ** \PiCTeX{\PiC\kern-.11em\TeX} +% ** \placevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE} + +% ** Internal commands +% ** \!ifnextchar{CHARACTER}{TRUE ACTION}{FALSE ACTION} +% ** \!tfor NAME := LIST \do {BODY} +% ** \!etfor NAME:= LIST \do {BODY} +% ** \!cfor NAME := LIST \do {BODY} +% ** \!ecfor NAME:= LIST \do {BODY} +% ** \!ifempty{MACRO}{TRUE ACTION}{FALSE ACTION} +% ** \!getnext\\ITEMfrom\LIST +% ** \!getnextvalueof\DIMEN\from\LIST +% ** \!copylist\LISTMACRO_A\to\LISTMACRO_B +% ** \!wlet\CONTROL_SEQUENCE_A=\CONTROL_SEQUENCE_B +% ** \!listaddon ITEM LIST +% ** \!rightappendITEM\withCS\to\LISTMACRO +% ** \!leftappendITEM\withCS\to\LISTMACRO +% ** \!lop\LISTMACRO\to\ITEM +% ** \!loop ... repeat +% ** \!!loop ... repeat +% ** \!removept{DIMENSION REGISTER}{CONTROL SEQUENCE} +% ** \!mlap{...} +% ** \!vmlap{...} +% ** \!not{TEK if-CONDITION} + +% ** First, here are the the PiCTeX logo, and the syllable PiC: +\def\PiC{P\kern-.12em\lower.5ex\hbox{I}\kern-.075emC} +\def\PiCTeX{\PiC\kern-.11em\TeX} + +% ** The following macro expands to parameter #2 or parameter #3 according to +% ** whether the next non-blank character following the macro is or is not #1. +% ** Blanks following the macro are gobbled. +\def\!ifnextchar#1#2#3{% + \let\!testchar=#1% + \def\!first{#2}% + \def\!second{#3}% + \futurelet\!nextchar\!testnext} +\def\!testnext{% + \ifx \!nextchar \!spacetoken + \let\!next=\!skipspacetestagain + \else + \ifx \!nextchar \!testchar + \let\!next=\!first + \else + \let\!next=\!second + \fi + \fi + \!next} +\def\\{\!skipspacetestagain} + \expandafter\def\\ {\futurelet\!nextchar\!testnext} +\def\\{\let\!spacetoken= } \\ % ** set \spacetoken to a space token + + +% ** Borrow the "tfor" macro from Latex: +% ** \!tfor NAME := LIST \do {BODY} +% ** if, before expansion, LIST = T1 ... Tn, where each Ti is a token +% ** or {...}, then executes BODY n times, with NAME = Ti on the +% ** i-th iteration. Works for n=0. +\def\!tfor#1:=#2\do#3{% + \edef\!fortemp{#2}% + \ifx\!fortemp\!empty + \else + \!tforloop#2\!nil\!nil\!!#1{#3}% + \fi} +\def\!tforloop#1#2\!!#3#4{% + \def#3{#1}% + \ifx #3\!nnil + \let\!nextwhile=\!fornoop + \else + #4\relax + \let\!nextwhile=\!tforloop + \fi + \!nextwhile#2\!!#3{#4}} + + +% ** \!etfor NAME:= LIST\do {BODY} +% ** This is like \!cfor, but LIST is any balanced token list whose complete +% ** expansion has the form T1 ... Tn +\def\!etfor#1:=#2\do#3{% + \def\!!tfor{\!tfor#1:=}% + \edef\!!!tfor{#2}% + \expandafter\!!tfor\!!!tfor\do{#3}} + + +% ** modify the Latex \tfor (token-for) loop to a \cfor (comma-for) loop. +% ** \!cfor NAME := LIST \do {BODY} +% ** if, before expansion, LIST = a1,a2,...an, then executes BODY n times, +% ** with NAME = ai on the i-th iteration. Works for n=0. +\def\!cfor#1:=#2\do#3{% + \edef\!fortemp{#2}% + \ifx\!fortemp\!empty + \else + \!cforloop#2,\!nil,\!nil\!!#1{#3}% + \fi} +\def\!cforloop#1,#2\!!#3#4{% + \def#3{#1}% + \ifx #3\!nnil + \let\!nextwhile=\!fornoop + \else + #4\relax + \let\!nextwhile=\!cforloop + \fi + \!nextwhile#2\!!#3{#4}} + + +% ** \!ecfor NAME:= LIST\do {BODY} +% ** This is like \!cfor, but LIST is any balanced token list whose complete +% ** expansion has the form a1,a2,...,an. +\def\!ecfor#1:=#2\do#3{% + \def\!!cfor{\!cfor#1:=}% + \edef\!!!cfor{#2}% + \expandafter\!!cfor\!!!cfor\do{#3}} + + +\def\!empty{} +\def\!nnil{\!nil} +\def\!fornoop#1\!!#2#3{} + + +% ** \!ifempty{ARG}{TRUE ACTION}{FALSE ACTION} +\def\!ifempty#1#2#3{% + \edef\!emptyarg{#1}% + \ifx\!emptyarg\!empty + #2% + \else + #3% + \fi} + +% ** \!getnext\\ITEMfrom\LIST +% ** \LIST has the form \\{item1}\\{item2}\\{item3}...\\{itemk} +% ** This routine sets \ITEM to item1, and cycles \LIST to +% ** \\{item2}\\{item3}...\\{itemk}\\{item1} +\def\!getnext#1\from#2{% + \expandafter\!gnext#2\!#1#2}% +\def\!gnext\\#1#2\!#3#4{% + \def#3{#1}% + \def#4{#2\\{#1}}% + \ignorespaces} + + +% ** \!getnextvalueof\DIMEN\from\LIST +% ** Similar to !getnext. +% ** \LIST has the form \\{dimen1}\\{dimen2}\\{dimen3} ... +% ** \DIMEN is a dimension register +% ** Works also for counts +% +\def\!getnextvalueof#1\from#2{% + \expandafter\!gnextv#2\!#1#2}% +\def\!gnextv\\#1#2\!#3#4{% + #3=#1% + \def#4{#2\\{#1}}% + \ignorespaces} + + +% ** \!copylist\LISTMACROA\to\LISTMACROB +% ** makes the replacement text of LISTMACRO B identical to that of +% ** list macro A. +\def\!copylist#1\to#2{% + \expandafter\!!copylist#1\!#2} +\def\!!copylist#1\!#2{% + \def#2{#1}\ignorespaces} + + +% ** \!wlet\CSA=\CSB +% ** lets control sequence \CSB = control sequence \CSA, and writes a +% ** message to that effect in the log file using plain TEK's \wlog +\def\!wlet#1=#2{% + \let#1=#2 + \wlog{\string#1=\string#2}} + +% ** \!listaddon ITEM LIST +% ** LIST <-- LIST \\ ITEM +\def\!listaddon#1#2{% + \expandafter\!!listaddon#2\!{#1}#2} +\def\!!listaddon#1\!#2#3{% + \def#3{#1\\#2}} + +% ** \!rightappendITEM\to\LISTMACRO +% ** \LISTMACRO --> \LISTMACRO\\{ITEM} +%\def\!rightappend#1\to#2{\expandafter\!!rightappend#2\!{#1}#2} +%\def\!!rightappend#1\!#2#3{\def#3{#1\\{#2}}} + + +% ** \!rightappendITEM\withCS\to\LISTMACRO +% ** \LISTMACRO --> \LISTMACRO||CS||{ITEM} +\def\!rightappend#1\withCS#2\to#3{\expandafter\!!rightappend#3\!#2{#1}#3} +\def\!!rightappend#1\!#2#3#4{\def#4{#1#2{#3}}} + + +% ** \!leftappendITEM\withCS\to\LISTMACRO +% ** \LISTMACRO --> CS||{ITEM}||\LISTMACRO +\def\!leftappend#1\withCS#2\to#3{\expandafter\!!leftappend#3\!#2{#1}#3} +\def\!!leftappend#1\!#2#3#4{\def#4{#2{#3}#1}} + + +% ** \!lop\LISTMACRO\to\ITEM +% ** \\{item1}\\{item2}\\{item3} ... --> \\{item2}\\{item3} ... +% ** item1 --> \ITEM +\def\!lop#1\to#2{\expandafter\!!lop#1\!#1#2} +\def\!!lop\\#1#2\!#3#4{\def#4{#1}\def#3{#2}} + + +% ** \!placeNUMBER\of\LISTMACRO\in\ITEM +% ** the NUMBERth item of \LISTMACRO --> replacement text of \ITEM +%\def\!place#1\of#2\in#3{\def#3{\outofrange}% +%{\count0=#1\def\\##1{\advance\count0-1 \ifnum\count0=0 \gdef#3{##1}\fi}#2}} + + +% ** Following code converts a commalist to a list macro, with all items +% ** fully expanded. +%\!ecfor\item:=\commalist\do{\expandafter\!rightappend\item\to\list} + + +% ** \!loop ... repeat +% ** This is exactly like TEX's \loop ... repeat. It can be used in nesting +% ** two loops, without puting the inner one inside a group. +\def\!loop#1\repeat{\def\!body{#1}\!iterate} +\def\!iterate{\!body\let\!next=\!iterate\else\let\!next=\relax\fi\!next} + +% ** \!!loop ... repeat +% ** This is exactly like TEX's \loop ... repeat. It can be used in nesting +% ** two loops, without puting the inner one inside a group. +\def\!!loop#1\repeat{\def\!!body{#1}\!!iterate} +\def\!!iterate{\!!body\let\!!next=\!!iterate\else\let\!!next=\relax\fi\!!next} +% (\multiput uses \!!loop) + +% ** \!removept{DIMENREG}{\CS} +% ** Defines the control sequence CS to be the value (in points) in the +% ** dimension register DIMENREG (but without the "pt" TEK usually adds) +% ** E.g., after \dimen0=12.3pt \!removept\dimen0\A, \A expands to 12.3 +\def\!removept#1#2{\edef#2{\expandafter\!!removePT\the#1}} +{\catcode`p=12 \catcode`t=12 \gdef\!!removePT#1pt{#1}} + +% ** \pladevalueinpts of <DIMENSION REGISTER> in {CONTROL SEQUENCE} +\def\placevalueinpts of <#1> in #2 {% + \!removept{#1}{#2}} + +% ** \!mlap{...} \!vmlap{...} +% ** Center ... in a box of width 0. +\def\!mlap#1{\hbox to 0pt{\hss#1\hss}} +\def\!vmlap#1{\vbox to 0pt{\vss#1\vss}} + +% ** \!not{TEK if-CONDITION} +% ** By a TEK if-CONDITION is meant something like +% ** \ifnum\N<0, or \ifdim\A>\B +% ** \!not produces an if-condition which is false if the original condition +% ** is true, and true if the original condition is false. +\def\!not#1{% + #1\relax + \!switchfalse + \else + \!switchtrue + \fi + \if!switch + \ignorespaces} + + +% ******************* +% *** ALLOCATIONS *** +% ******************* + +% This section allocates all the registers PiCTeX uses. Following +% each allocation is a string of the form ....N.D...L......... ; +% the various letters show which sections of PiCTeX make explicit +% reference to that register, according to the following code: + +% H Hacks +% A Areas +% W arroWs +% B Bars +% X boXes +% C Curves +% D Dashpattterns +% V diVision +% E Ellipses +% U rUles +% L Linear arc +% G loGten +% P Pictures +% O plOtting +% Y pYthagoras +% Q Quadratic arc +% R Rotations +% S Shading +% T Ticks + +% Turn off messages from TeX's allocation macros +\let\!!!wlog=\wlog % "\wlog" is defined in plain TeX +\def\wlog#1{} + +\newdimen\headingtoplotskip %.A................. +\newdimen\linethickness %.A..X....U........T +\newdimen\longticklength %.A................T +\newdimen\plotsymbolspacing %......D...L....Q... +\newdimen\shortticklength %.A................T +\newdimen\stackleading %.A..........P...... +\newdimen\tickstovaluesleading %.A................T +\newdimen\totalarclength %......D...L....Q... +\newdimen\valuestolabelleading %.A................. + +\newbox\!boxA %.AW...............T +\newbox\!boxB %..W................ +\newbox\!picbox %............P...... +\newbox\!plotsymbol %..........L..O..... +\newbox\!putobject %............PO...S. +\newbox\!shadesymbol %.................S. + +\newcount\!countA %.A....D..UL....Q.ST +\newcount\!countB %......D..U.....Q.ST +\newcount\!countC %...............Q..T +\newcount\!countD %................... +\newcount\!countE %.............O....T +\newcount\!countF %.............O....T +\newcount\!countG %..................T +\newcount\!fiftypt %.........U......... +\newcount\!intervalno %..........L....Q... +\newcount\!npoints %..........L........ +\newcount\!nsegments %.........U......... +\newcount\!ntemp %............P...... +\newcount\!parity %.................S. +\newcount\!scalefactor %..................T +\newcount\!tfs %.......V........... +\newcount\!tickcase %..................T + +\newdimen\!Xleft %............P...... +\newdimen\!Xright %............P...... +\newdimen\!Xsave %.A................T +\newdimen\!Ybot %............P...... +\newdimen\!Ysave %.A................T +\newdimen\!Ytop %............P...... +\newdimen\!angle %........E.......... +\newdimen\!arclength %..W......UL....Q... +\newdimen\!areabloc %.A........L........ +\newdimen\!arealloc %.A........L........ +\newdimen\!arearloc %.A........L........ +\newdimen\!areatloc %.A........L........ +\newdimen\!bshrinkage %.................S. +\newdimen\!checkbot %..........L........ +\newdimen\!checkleft %..........L........ +\newdimen\!checkright %..........L........ +\newdimen\!checktop %..........L........ +\newdimen\!dimenA %.AW.X.DVEUL..OYQRST +\newdimen\!dimenB %....X.DVEU...O.QRS. +\newdimen\!dimenC %..W.X.DVEU......RS. +\newdimen\!dimenD %..W.X.DVEU....Y.RS. +\newdimen\!dimenE %..W........G..YQ.S. +\newdimen\!dimenF %...........G..YQ.S. +\newdimen\!dimenG %...........G..YQ.S. +\newdimen\!dimenH %...........G..Y..S. +\newdimen\!dimenI %...BX.........Y.... +\newdimen\!distacross %..........L....Q... +\newdimen\!downlength %..........L........ +\newdimen\!dp %.A..X.......P....S. +\newdimen\!dshade %.................S. +\newdimen\!dxpos %..W......U..P....S. +\newdimen\!dxprime %...............Q... +\newdimen\!dypos %..WB.....U..P...... +\newdimen\!dyprime %...............Q... +\newdimen\!ht %.A..X.......P....S. +\newdimen\!leaderlength %......D..U......... +\newdimen\!lshrinkage %.................S. +\newdimen\!midarclength %...............Q... +\newdimen\!offset %.A................T +\newdimen\!plotheadingoffset %.A................. +\newdimen\!plotsymbolxshift %..........L..O..... +\newdimen\!plotsymbolyshift %..........L..O..... +\newdimen\!plotxorigin %..........L..O..... +\newdimen\!plotyorigin %..........L..O..... +\newdimen\!rootten %...........G....... +\newdimen\!rshrinkage %.................S. +\newdimen\!shadesymbolxshift %.................S. +\newdimen\!shadesymbolyshift %.................S. +\newdimen\!tenAa %...........G....... +\newdimen\!tenAc %...........G....... +\newdimen\!tenAe %...........G....... +\newdimen\!tshrinkage %.................S. +\newdimen\!uplength %..........L........ +\newdimen\!wd %....X.......P....S. +\newdimen\!wmax %...............Q... +\newdimen\!wmin %...............Q... +\newdimen\!xB %...............Q... +\newdimen\!xC %...............Q... +\newdimen\!xE %..W.....E.L....Q.S. +\newdimen\!xM %..W.....E......Q.S. +\newdimen\!xS %..W.....E.L....Q.S. +\newdimen\!xaxislength %.A................T +\newdimen\!xdiff %..........L........ +\newdimen\!xleft %............P...... +\newdimen\!xloc %..WB.....U.......S. +\newdimen\!xorigin %.A........L.P....S. +\newdimen\!xpivot %................R.. +\newdimen\!xpos %..........L.P..Q.ST +\newdimen\!xprime %...............Q... +\newdimen\!xright %............P...... +\newdimen\!xshade %.................S. +\newdimen\!xshift %..W.........PO...S. +\newdimen\!xtemp %............P...... +\newdimen\!xunit %.AWBX...EUL.P..QRS. +\newdimen\!xxE %........E.......... +\newdimen\!xxM %........E.......... +\newdimen\!xxS %........E.......... +\newdimen\!xxloc %..WB....EU......... +\newdimen\!yB %...............Q... +\newdimen\!yC %...............Q... +\newdimen\!yE %..W.....E.L....Q... +\newdimen\!yM %..W.....E......Q... +\newdimen\!yS %..W.....E.L....Q... +\newdimen\!yaxislength %.A................T +\newdimen\!ybot %............P...... +\newdimen\!ydiff %..........L........ +\newdimen\!yloc %..WB.....U.......S. +\newdimen\!yorigin %.A........L.P....S. +\newdimen\!ypivot %................R.. +\newdimen\!ypos %..........L.P..Q.ST +\newdimen\!yprime %...............Q... +\newdimen\!yshade %.................S. +\newdimen\!yshift %..W.........PO...S. +\newdimen\!ytemp %............P...... +\newdimen\!ytop %............P...... +\newdimen\!yunit %.AWBX...EUL.P..QRS. +\newdimen\!yyE %........E.......... +\newdimen\!yyM %........E.......... +\newdimen\!yyS %........E.......... +\newdimen\!yyloc %..WB....EU......... +\newdimen\!zpt %.AWBX.DVEULGP.YQ.ST + +\newif\if!axisvisible %.A................. +\newif\if!gridlinestoo %..................T +\newif\if!keepPO %................... +\newif\if!placeaxislabel %.A................. +\newif\if!switch %H.................. +\newif\if!xswitch %.A................T + +\newtoks\!axisLaBeL %.A................. +\newtoks\!keywordtoks %.A................. + +\newwrite\!replotfile %.............O..... + +\newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. +Replace NEW KEYWORD in the indicated response by the keyword that +should have been specified.} %.A................. + +% The following commands assign alternate names to some of the +% above registers. "\!wlet" is defined in Hacks. +\!wlet\!!origin=\!xM %.A................T +\!wlet\!!unit=\!uplength %.A................T +\!wlet\!Lresiduallength=\!dimenG %.........U......... +\!wlet\!Rresiduallength=\!dimenF %.........U......... +\!wlet\!axisLength=\!distacross %.A................T +\!wlet\!axisend=\!ydiff %.A................T +\!wlet\!axisstart=\!xdiff %.A................T +\!wlet\!axisxlevel=\!arclength %.A................T +\!wlet\!axisylevel=\!downlength %.A................T +\!wlet\!beta=\!dimenE %...............Q... +\!wlet\!gamma=\!dimenF %...............Q... +\!wlet\!shadexorigin=\!plotxorigin %.................S. +\!wlet\!shadeyorigin=\!plotyorigin %.................S. +\!wlet\!ticklength=\!xS %..................T +\!wlet\!ticklocation=\!xE %..................T +\!wlet\!ticklocationincr=\!yE %..................T +\!wlet\!tickwidth=\!yS %..................T +\!wlet\!totalleaderlength=\!dimenE %.........U......... +\!wlet\!xone=\!xprime %....X.............. +\!wlet\!xtwo=\!dxprime %....X.............. +\!wlet\!ySsave=\!yM %................... +\!wlet\!ybB=\!yB %.................S. +\!wlet\!ybC=\!yC %.................S. +\!wlet\!ybE=\!yE %.................S. +\!wlet\!ybM=\!yM %.................S. +\!wlet\!ybS=\!yS %.................S. +\!wlet\!ybpos=\!yyloc %.................S. +\!wlet\!yone=\!yprime %....X.............. +\!wlet\!ytB=\!xB %.................S. +\!wlet\!ytC=\!xC %.................S. +\!wlet\!ytE=\!downlength %.................S. +\!wlet\!ytM=\!arclength %.................S. +\!wlet\!ytS=\!distacross %.................S. +\!wlet\!ytpos=\!xxloc %.................S. +\!wlet\!ytwo=\!dyprime %....X.............. + + +% Initial values for registers +\!zpt=0pt % static +\!xunit=1pt +\!yunit=1pt +\!arearloc=\!xunit +\!areatloc=\!yunit +\!dshade=5pt +\!leaderlength=24in +\!tfs=256 % static +\!wmax=5.3pt % static +\!wmin=2.7pt % static +\!xaxislength=\!xunit +\!xpivot=\!zpt +\!yaxislength=\!yunit +\!ypivot=\!zpt +\plotsymbolspacing=.4pt + \!dimenA=50pt \!fiftypt=\!dimenA % static + +\!rootten=3.162278pt % static +\!tenAa=8.690286pt % static (A5) +\!tenAc=2.773839pt % static (A3) +\!tenAe=2.543275pt % static (A1) + +% Initial values for control sequences +\def\!cosrotationangle{1} %................R.. +\def\!sinrotationangle{0} %................R.. +\def\!xpivotcoord{0} %................R.. +\def\!xref{0} %............P...... +\def\!xshadesave{0} %.................S. +\def\!ypivotcoord{0} %................R.. +\def\!yref{0} %............P...... +\def\!yshadesave{0} %.................S. +\def\!zero{0} %..................T + +% Reset TeX to report allocations +\let\wlog=\!!!wlog +% ************************************* +% *** AREAS: Deals with plot areas *** +% ************************************* +% +% ** User commands +% ** \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD +% ** to TOP YCOORD +% ** \axis BOTTOM-LEFT-TOP-RIGHT [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE] +% ** [LABEL {label}] [TICKS] / +% ** \visibleaxes +% ** \invisibleaxes +% ** \plotheading {HEADING} +% ** \grid {# of columns} {# of rows} +% ** \normalgraphs + +% ** \normalgraphs +% ** Sets defaults for graph setup. See Subsection 3.4 of manual. +\def\normalgraphs{% + \longticklength=.4\baselineskip + \shortticklength=.25\baselineskip + \tickstovaluesleading=.25\baselineskip + \valuestolabelleading=.8\baselineskip + \linethickness=.4pt + \stackleading=.17\baselineskip + \headingtoplotskip=1.5\baselineskip + \visibleaxes + \ticksout + \nogridlines + \unloggedticks} +% +% ** \setplotarea x from LEFT XCOORD to RIGTH XCOORD, y from BOTTOM YCOORD +% ** to TOP YCOORD +% ** Reserves space in PICBOX for a rectangular box with the indicated +% ** coordinates. Must be specified before calls to \axis, +% ** \grid, \plotheading. +% ** See Subsection 3.1 of the manual. +\def\setplotarea x from #1 to #2, y from #3 to #4 {% + \!arealloc=\!M{#1}\!xunit \advance \!arealloc -\!xorigin + \!areabloc=\!M{#3}\!yunit \advance \!areabloc -\!yorigin + \!arearloc=\!M{#2}\!xunit \advance \!arearloc -\!xorigin + \!areatloc=\!M{#4}\!yunit \advance \!areatloc -\!yorigin + \!initinboundscheck + \!xaxislength=\!arearloc \advance\!xaxislength -\!arealloc + \!yaxislength=\!areatloc \advance\!yaxislength -\!areabloc + \!plotheadingoffset=\!zpt + \!dimenput {{\setbox0=\hbox{}\wd0=\!xaxislength\ht0=\!yaxislength\box0}} + [bl] (\!arealloc,\!areabloc)} +% +% ** \visibleaxes, \invisibleaxes +% ** Switches for setting visibility of subsequent axes. +% ** See Subsection 3.2 of the manual. +\def\visibleaxes{% + \def\!axisvisibility{\!axisvisibletrue}} +\def\invisibleaxes{% + \def\!axisvisibility{\!axisvisiblefalse}} +% +% ** The next few macros enable the user to fix up an erroneous keyword +% ** in the \axis command. +% \newhelp is in ALLOCATIONS +% \newhelp\!keywordhelp{The keyword mentioned in the error message in unknown. +% Replace NEW KEYWORD in the indicated response by the keyword that +% should have been specified.} + +\def\!fixkeyword#1{% + \errhelp=\!keywordhelp + \errmessage{Unrecognized keyword `#1': \the\!keywordtoks{NEW KEYWORD}'}} + +% \newtoks\!keywordtoks In ALLOCATIONS. +\!keywordtoks={enter `i\fixkeyword} + +\def\fixkeyword#1{% + \!nextkeyword#1 } + +% ** \axis BOTTOM-LEFT-TOP-RIGHT [SHIFTEDTO xy=COORD] [VISIBLE-INVISIBLE] +% ** [LABEL {label}] [TICKS] / +% ** Exactly one of the keywords BOTTOM, LEFT, TOP, RIGHT must be +% ** specified. Axis is drawn along the indicated edge of the current +% ** plot area, shifted if the SHIFTEDTO option is used, visible or +% ** invisible according the selected option, with an optional LABEL, +% ** and optional TICKS (see ticks.tex for the options avialabel with +% ** TICKS). The TICKS option must be the last one specified. The \axis +% ** MUST be terminated with a / followed by a space. +% ** See Subsection 3.2 of the manual for more information. + +% ** The various options of the \axis command are processed by the +% ** \!nextkeyword macro defined below. For example, +% ** `\!nextkeyword shiftedto ' expands to `\!axisshiftedto'. +\def\axis {% + \def\!nextkeyword##1 {% + \expandafter\ifx\csname !axis##1\endcsname \relax + \def\!next{\!fixkeyword{##1}}% + \else + \def\!next{\csname !axis##1\endcsname}% + \fi + \!next}% + \!offset=\!zpt + \!axisvisibility + \!placeaxislabelfalse + \!nextkeyword} + +% ** This and the various macros that follow handle the keyword +% ** specifications on the \axis command +% ** See Subsection 3.2 of the manual. +\def\!axisbottom{% + \!axisylevel=\!areabloc + \def\!tickxsign{0}% + \def\!tickysign{-}% + \def\!axissetup{\!axisxsetup}% + \def\!axislabeltbrl{t}% + \!nextkeyword} + +\def\!axistop{% + \!axisylevel=\!areatloc + \def\!tickxsign{0}% + \def\!tickysign{+}% + \def\!axissetup{\!axisxsetup}% + \def\!axislabeltbrl{b}% + \!nextkeyword} + +\def\!axisleft{% + \!axisxlevel=\!arealloc + \def\!tickxsign{-}% + \def\!tickysign{0}% + \def\!axissetup{\!axisysetup}% + \def\!axislabeltbrl{r}% + \!nextkeyword} + +\def\!axisright{% + \!axisxlevel=\!arearloc + \def\!tickxsign{+}% + \def\!tickysign{0}% + \def\!axissetup{\!axisysetup}% + \def\!axislabeltbrl{l}% + \!nextkeyword} + +\def\!axisshiftedto#1=#2 {% + \if 0\!tickxsign + \!axisylevel=\!M{#2}\!yunit + \advance\!axisylevel -\!yorigin + \else + \!axisxlevel=\!M{#2}\!xunit + \advance\!axisxlevel -\!xorigin + \fi + \!nextkeyword} + +\def\!axisvisible{% + \!axisvisibletrue + \!nextkeyword} + +\def\!axisinvisible{% + \!axisvisiblefalse + \!nextkeyword} + +\def\!axislabel#1 {% + \!axisLaBeL={#1}% + \!placeaxislabeltrue + \!nextkeyword} + +\expandafter\def\csname !axis/\endcsname{% + \!axissetup % This could done already by "ticks"; if so, now \relax + \if!placeaxislabel + \!placeaxislabel + \fi + \if +\!tickysign % ** (A "top" axis) + \!dimenA=\!axisylevel + \advance\!dimenA \!offset % ** dimA = top of the axis structure + \advance\!dimenA -\!areatloc % ** dimA = excess over the plot area + \ifdim \!dimenA>\!plotheadingoffset + \!plotheadingoffset=\!dimenA % ** Greatest excess over the plot area + \fi + \fi} + +% ** \grid {c} {r} +% ** Partitions the plot area into c columns and r rows; see Subsection 3.3 +% ** of the manual. +% ** (Other grid patterns can be drawn with the TICKS option of the \axis +% ** command. +\def\grid #1 #2 {% + \!countA=#1\advance\!countA 1 + \axis bottom invisible ticks length <\!zpt> andacross quantity {\!countA} / + \!countA=#2\advance\!countA 1 + \axis left invisible ticks length <\!zpt> andacross quantity {\!countA} / } + +% ** \plotheading{HEADING} +% ** Places HEADING centered above the top of the plotarea (and above +% ** any top axis ticks marks, tick labels, and axis label); see +% ** Subsection 3.3 of the manual. +\def\plotheading#1 {% + \advance\!plotheadingoffset \headingtoplotskip + \!dimenput {#1} [B] <.5\!xaxislength,\!plotheadingoffset> + (\!arealloc,\!areatloc)} + +% ** From here on, the routines are internal. +\def\!axisxsetup{% + \!axisxlevel=\!arealloc + \!axisstart=\!arealloc + \!axisend=\!arearloc + \!axisLength=\!xaxislength + \!!origin=\!xorigin + \!!unit=\!xunit + \!xswitchtrue + \if!axisvisible + \!makeaxis + \fi} + +\def\!axisysetup{% + \!axisylevel=\!areabloc + \!axisstart=\!areabloc + \!axisend=\!areatloc + \!axisLength=\!yaxislength + \!!origin=\!yorigin + \!!unit=\!yunit + \!xswitchfalse + \if!axisvisible + \!makeaxis + \fi} + +\def\!makeaxis{% + \setbox\!boxA=\hbox{% (Make a pseudo-y[x] tick for an x[y]-axis) + \beginpicture + \!setdimenmode + \setcoordinatesystem point at {\!zpt} {\!zpt} + \putrule from {\!zpt} {\!zpt} to + {\!tickysign\!tickysign\!axisLength} + {\!tickxsign\!tickxsign\!axisLength} + \endpicturesave <\!Xsave,\!Ysave>}% + \wd\!boxA=\!zpt + \!placetick\!axisstart} + +\def\!placeaxislabel{% + \advance\!offset \valuestolabelleading + \if!xswitch + \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl] + <.5\!axisLength,\!tickysign\!offset> (\!axisxlevel,\!axisylevel) + \advance\!offset \!dp % ** advance offset by the "tallness" + \advance\!offset \!ht % ** of the label + \else + \!dimenput {\the\!axisLaBeL} [\!axislabeltbrl] + <\!tickxsign\!offset,.5\!axisLength> (\!axisxlevel,\!axisylevel) + \fi + \!axisLaBeL={}} + + +% ******************************* +% *** ARROWS (Draws arrows) *** +% ******************************* +% +% ** User commands +% ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION] +% ** [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO +% ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO + +% ** \arrow <ARROW HEAD LENGTH> [MID FRACTION, BASE FRACTION] +% ** [<XSHIFT,YSHIFT>] from XFROM YFROM to XTO YTO +% ** Draws an arrow from (XFROM,YFROM) to (XTO,YTO). The arrow head +% ** is constructed two quadratic arcs, which extend back a distance +% ** ARROW HEAD LENGTH (a dimension) on both sides of the arrow shaft. +% ** All the way back the arcs are a distance BASE FRACTION*ARROW HEAD +% ** LENGTH apart, while half-way back they are a distance MID FRACTION* +% ** ARROW HEAD LENGTH apart. <XSHIFT,YSHIFT> is optional, and has +% ** its usual interpreation. See Subsection 5.4 of the manual. + +\def\arrow <#1> [#2,#3]{% + \!ifnextchar<{\!arrow{#1}{#2}{#3}}{\!arrow{#1}{#2}{#3}<\!zpt,\!zpt> }} + +\def\!arrow#1#2#3<#4,#5> from #6 #7 to #8 #9 {% +% +% ** convert to dimensions + \!xloc=\!M{#8}\!xunit + \!yloc=\!M{#9}\!yunit + \!dxpos=\!xloc \!dimenA=\!M{#6}\!xunit \advance \!dxpos -\!dimenA + \!dypos=\!yloc \!dimenA=\!M{#7}\!yunit \advance \!dypos -\!dimenA + \let\!MAH=\!M% ** save current c/d mode + \!setdimenmode% ** go into dimension mode +% + \!xshift=#4\relax \!yshift=#5\relax% ** pick up shift + \!reverserotateonly\!xshift\!yshift% ** back rotate shift + \advance\!xshift\!xloc \advance\!yshift\!yloc +% +% ** draw shaft of arrow + \!xS=-\!dxpos \advance\!xS\!xshift + \!yS=-\!dypos \advance\!yS\!yshift + \!start (\!xS,\!yS) + \!ljoin (\!xshift,\!yshift) +% +% ** find 32*cosine and 32*sine of angle of rotation + \!Pythag\!dxpos\!dypos\!arclength + \!divide\!dxpos\!arclength\!dxpos + \!dxpos=32\!dxpos \!removept\!dxpos\!!cos + \!divide\!dypos\!arclength\!dypos + \!dypos=32\!dypos \!removept\!dypos\!!sin +% +% ** construct arrowhead + \!halfhead{#1}{#2}{#3}% ** draw half of arrow head + \!halfhead{#1}{-#2}{-#3}% ** draw other half +% + \let\!M=\!MAH% ** restore old c/d mode + \ignorespaces} +% +% ** draw half of arrow head + \def\!halfhead#1#2#3{% + \!dimenC=-#1% + \divide \!dimenC 2 % ** half way back + \!dimenD=#2\!dimenC% ** half the mid width + \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xM,\!yM) + \!dimenC=-#1% ** all the way back + \!dimenD=#3\!dimenC + \!dimenD=.5\!dimenD% ** half the full width + \!rotate(\!dimenC,\!dimenD)by(\!!cos,\!!sin)to(\!xE,\!yE) + \!start (\!xshift,\!yshift) + \advance\!xM\!xshift \advance\!yM\!yshift + \advance\!xE\!xshift \advance\!yE\!yshift + \!qjoin (\!xM,\!yM) (\!xE,\!yE) + \ignorespaces} + + +% ** \betweenarrows {TEXT} [orientation & shift] from XFROM YFROM to XTO YTO +% ** Makes things like <--- text --->, using arrow heads from TeX's fonts. +% ** See Subsection 5.4 of the manual. +\def\betweenarrows #1#2 from #3 #4 to #5 #6 {% + \!xloc=\!M{#3}\!xunit \!xxloc=\!M{#5}\!xunit% + \!yloc=\!M{#4}\!yunit \!yyloc=\!M{#6}\!yunit% + \!dxpos=\!xxloc \advance\!dxpos by -\!xloc + \!dypos=\!yyloc \advance\!dypos by -\!yloc + \advance\!xloc .5\!dxpos + \advance\!yloc .5\!dypos +% + \let\!MBA=\!M% ** save current coord\dimen mode + \!setdimenmode% ** express locations in dimens + \ifdim\!dypos=\!zpt + \ifdim\!dxpos<\!zpt \!dxpos=-\!dxpos \fi + \put {\!lrarrows{\!dxpos}{#1}}#2{} at {\!xloc} {\!yloc} + \else + \ifdim\!dxpos=\!zpt + \ifdim\!dypos<\!zpt \!dypos=-\!zpt \fi + \put {\!udarrows{\!dypos}{#1}}#2{} at {\!xloc} {\!yloc} + \fi + \fi + \let\!M=\!MBA% ** restore previous c/d mode + \ignorespaces} + +% ** Subroutine for left-right between arrows +\def\!lrarrows#1#2{% #1=width, #2=text + {\setbox\!boxA=\hbox{$\mkern-2mu\mathord-\mkern-2mu$}% + \setbox\!boxB=\hbox{$\leftarrow$}\!dimenE=\ht\!boxB + \setbox\!boxB=\hbox{}\ht\!boxB=2\!dimenE + \hbox to #1{$\mathord\leftarrow\mkern-6mu + \cleaders\copy\!boxA\hfil + \mkern-6mu\mathord-$% + \kern.4em $\vcenter{\box\!boxB}$$\vcenter{\hbox{#2}}$\kern.4em + $\mathord-\mkern-6mu + \cleaders\copy\!boxA\hfil + \mkern-6mu\mathord\rightarrow$}}} + +% ** Subroutine for up-down between arrows +\def\!udarrows#1#2{% #1=width, #2=text + {\setbox\!boxB=\hbox{#2}% + \setbox\!boxA=\hbox to \wd\!boxB{\hss$\vert$\hss}% + \!dimenE=\ht\!boxA \advance\!dimenE \dp\!boxA \divide\!dimenE 2 + \vbox to #1{\offinterlineskip + \vskip .05556\!dimenE + \hbox to \wd\!boxB{\hss$\mkern.4mu\uparrow$\hss}\vskip-\!dimenE + \cleaders\copy\!boxA\vfil + \vskip-\!dimenE\copy\!boxA + \vskip\!dimenE\copy\!boxB\vskip.4em + \copy\!boxA\vskip-\!dimenE + \cleaders\copy\!boxA\vfil + \vskip-\!dimenE \hbox to \wd\!boxB{\hss$\mkern.4mu\downarrow$\hss} + \vskip .05556\!dimenE}}} + + +% *************************** +% *** BARS (Draws bars) *** +% *************************** +% +% ** User commands: +% ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART +% ** to XEND YEND +% ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD +% ** [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)] +% ** [endlabels ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)] + + +% ** \putbar [<XSHIFT,YSHIFT>] breadth <BREADTH> from XSTART YSTART +% ** to XEND YEND +% ** Either XSTART=XEND or YSTART=YEND. Draws a rectangle between +% ** (XSTART,YSTART) & (XEND,YEND). The "depth" of the rectangle +% ** is determined by those two plot positions; its other +% ** dimension "breadth" is specified by the dimension BREADTH. +% ** See Subsection 4.2 of the manual. +\def\putbar#1breadth <#2> from #3 #4 to #5 #6 {% + \!xloc=\!M{#3}\!xunit \!xxloc=\!M{#5}\!xunit% + \!yloc=\!M{#4}\!yunit \!yyloc=\!M{#6}\!yunit% + \!dypos=\!yyloc \advance\!dypos by -\!yloc + \!dimenI=#2 +% + \ifdim \!dimenI=\!zpt % ** If 0 breadth + \putrule#1from {#3} {#4} to {#5} {#6} % ** Then draw line + \else % ** Else, put in a rectangle + \let\!MBar=\!M% ** save current c/d mode + \!setdimenmode % ** go into dimension mode + \divide\!dimenI 2 + \ifdim \!dypos=\!zpt + \advance \!yloc -\!dimenI % ** Equal y coordinates + \advance \!yyloc \!dimenI + \else + \advance \!xloc -\!dimenI % ** Equal x coordinates + \advance \!xxloc \!dimenI + \fi + \putrectangle#1corners at {\!xloc} {\!yloc} and {\!xxloc} {\!yyloc} + \let\!M=\!MBar % ** restore c/d mode + \fi + \ignorespaces} + + +% ** \setbars [<XSHIFT,YSHIFT>] breadth <BREADTH> baseline at XY = COORD +% ** [baselabels ([B_ORIENTATION_x,B_ORIENTATION_y] <B_XSHIFT,B_YSHIFT>)] +% ** [endlabels ([E_ORIENTATION_x,E_ORIENTATION_y] <E_XSHIFT,E_YSHIFT>)] +% ** This command puts PiCTeX into the bar graph drawing mode described +% ** in Subsection 4.4 of the manual. +\def\setbars#1breadth <#2> baseline at #3 = #4 {% + \edef\!barshift{#1}% + \edef\!barbreadth{#2}% + \edef\!barorientation{#3}% + \edef\!barbaseline{#4}% + \def\!bardobaselabel{\!bardoendlabel}% + \def\!bardoendlabel{\!barfinish}% + \let\!drawcurve=\!barcurve + \!setbars} +\def\!setbars{% + \futurelet\!nextchar\!!setbars} +\def\!!setbars{% + \if b\!nextchar + \def\!!!setbars{\!setbarsbget}% + \else + \if e\!nextchar + \def\!!!setbars{\!setbarseget}% + \else + \def\!!!setbars{\relax}% + \fi + \fi + \!!!setbars} +\def\!setbarsbget baselabels (#1) {% + \def\!barbaselabelorientation{#1}% + \def\!bardobaselabel{\!!bardobaselabel}% + \!setbars} +\def\!setbarseget endlabels (#1) {% + \edef\!barendlabelorientation{#1}% + \def\!bardoendlabel{\!!bardoendlabel}% + \!setbars} + +% ** \!barcurve +% ** Draws a bargraph with preset values of barshift, barbreadth, +% ** barorientation (x or y) and barbaseline (coordinate) +\def\!barcurve #1 #2 {% + \if y\!barorientation + \def\!basexarg{#1}% + \def\!baseyarg{\!barbaseline}% + \else + \def\!basexarg{\!barbaseline}% + \def\!baseyarg{#2}% + \fi + \expandafter\putbar\!barshift breadth <\!barbreadth> from {\!basexarg} + {\!baseyarg} to {#1} {#2} + \def\!endxarg{#1}% + \def\!endyarg{#2}% + \!bardobaselabel} + +\def\!!bardobaselabel "#1" {% + \put {#1}\!barbaselabelorientation{} at {\!basexarg} {\!baseyarg} + \!bardoendlabel} + +\def\!!bardoendlabel "#1" {% + \put {#1}\!barendlabelorientation{} at {\!endxarg} {\!endyarg} + \!barfinish} + +\def\!barfinish{% + \!ifnextchar/{\!finish}{\!barcurve}} + + +% ******************************** +% *** BOXES (Draws rectangles) *** +% ******************************** +% +% ** User commands: +% ** \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1 +% ** and XCOORD2 YCOORD2 +% ** \shaderectangleson +% ** \shaderectanglesoff +% ** \frame [<SEPARATION>] {TEXT} +% ** \rectangle <WIDTH> <HEIGHT> +% +% +% ** \putrectangle [<XSHIFT,YSHIFT>] corners at XCOORD1 YCOORD1 +% ** and XCOORD2 YCOORD2 +% ** Draws a rectangle with corners at (X1,Y1), (X2,Y1), (X1,Y2), (X2,Y2) +% ** Lines have thickness \linethickness, and overlap at the corners. +% ** The optional field <XSHIFT,YSHIFT> functions as with a \put command. +% ** See Subsection 4.2 of the manual. +\def\putrectangle{% + \!ifnextchar<{\!putrectangle}{\!putrectangle<\!zpt,\!zpt> }} +\def\!putrectangle<#1,#2> corners at #3 #4 and #5 #6 {% +% +% ** get locations + \!xone=\!M{#3}\!xunit \!xtwo=\!M{#5}\!xunit% + \!yone=\!M{#4}\!yunit \!ytwo=\!M{#6}\!yunit% + \ifdim \!xtwo<\!xone + \!dimenI=\!xone \!xone=\!xtwo \!xtwo=\!dimenI + \fi + \ifdim \!ytwo<\!yone + \!dimenI=\!yone \!yone=\!ytwo \!ytwo=\!dimenI + \fi + \!dimenI=#1\relax \advance\!xone\!dimenI \advance\!xtwo\!dimenI + \!dimenI=#2\relax \advance\!yone\!dimenI \advance\!ytwo\!dimenI + \let\!MRect=\!M% ** save current coord/dimen mode + \!setdimenmode +% +% ** shade rectangle if appropriate + \!shaderectangle +% +% ** draw horizontal edges + \!dimenI=.5\linethickness + \advance \!xone -\!dimenI% ** adjust x-location to overlap corners + \advance \!xtwo \!dimenI% ** ditto + \putrule from {\!xone} {\!yone} to {\!xtwo} {\!yone} + \putrule from {\!xone} {\!ytwo} to {\!xtwo} {\!ytwo} +% +% ** draw vertical edges + \advance \!xone \!dimenI% ** restore original x-values + \advance \!xtwo -\!dimenI% + \advance \!yone -\!dimenI% ** adjust y-location to overlap corners + \advance \!ytwo \!dimenI% ** ditto + \putrule from {\!xone} {\!yone} to {\!xone} {\!ytwo} + \putrule from {\!xtwo} {\!yone} to {\!xtwo} {\!ytwo} +% + \let\!M=\!MRect% ** restore coord/dimen mode + \ignorespaces} + +% ** \shaderectangleson +% ** Subsequent rectangles will be shaded according to +% ** the current shading pattern. Affects \putrectangle, \putbar, +% ** \frame, \sethistograms, and \setbars. See Subsection 7.5 of the manual. +\def\shaderectangleson{% + \def\!shaderectangle{\!!shaderectangle}% + \ignorespaces} +% ** \shaderectanglesoff +% ** Suppresses \shaderectangleson. The default. +\def\shaderectanglesoff{% + \def\!shaderectangle{}% + \ignorespaces} + +\shaderectanglesoff + +% ** The following internal routine shades the current rectangle, when +% ** \!shaderectangle = \!!shaderectangle . +\def\!!shaderectangle{% + \!dimenA=\!xtwo \advance \!dimenA -\!xone + \!dimenB=\!ytwo \advance \!dimenB -\!yone + \ifdim \!dimenA<\!dimenB + \!startvshade (\!xone,\!yone,\!ytwo) + \!lshade (\!xtwo,\!yone,\!ytwo) + \else + \!starthshade (\!yone,\!xone,\!xtwo) + \!lshade (\!ytwo,\!xone,\!xtwo) + \fi + \ignorespaces} + +% ** \frame [<SEPARATION>] {TEXT} +% ** Draws a frame of thickness linethickness about the box enclosing +% ** TEXT; the frame is separated from the box by a distance of +% ** SEPARATION. The result is an hbox with the same baseline as TEXT. +% ** If <SEPARATION> is omitted, you get the effect of <0pt>. +% ** See Subsection 4.2 of the manual. +\def\frame{% + \!ifnextchar<{\!frame}{\!frame<\!zpt> }} +\long\def\!frame<#1> #2{% + \beginpicture + \setcoordinatesystem units <1pt,1pt> point at 0 0 + \put {#2} [Bl] at 0 0 + \!dimenA=#1\relax + \!dimenB=\!wd \advance \!dimenB \!dimenA + \!dimenC=\!ht \advance \!dimenC \!dimenA + \!dimenD=\!dp \advance \!dimenD \!dimenA + \let\!MFr=\!M + \!setdimenmode + \putrectangle corners at {-\!dimenA} {-\!dimenD} and {\!dimenB} {\!dimenC} + \!setcoordmode + \let\!M=\!MFr + \endpicture + \ignorespaces} + +% ** \rectangle <WIDTH> <HEIGHT> +% ** Constructs a rectangle of width WIDTH and heigth HEIGHT. +% ** See Subsection 4.2 of the manual. +\def\rectangle <#1> <#2> {% + \setbox0=\hbox{}\wd0=#1\ht0=#2\frame {\box0}} + + +% ********************************************* +% *** CURVES (Upper level \plot commands) *** +% ********************************************* +% +% ** User commands +% ** \plot DATA / +% ** \plot "FILE NAME" +% ** \setquadratic +% ** \setlinear +% ** \sethistograms +% ** \vshade ... +% ** \hshade ... + +% \plot: multi-purpose command. Draws histograms, bar graphs, piecewise-linear +% or piecewise quadratic curves, depending on the setting of \!drawcurve. +% See Subsections 4.3-4.5, 5.1, 5.2 of the manual. +\def\plot{% + \!ifnextchar"{\!plotfromfile}{\!drawcurve}} +\def\!plotfromfile"#1"{% + \expandafter\!drawcurve \input #1 /} + +% Command to set piecewise quadratic mode +% See Subsections 5.1, 7.3, and 7.4 of the manual. +\def\setquadratic{% + \let\!drawcurve=\!qcurve + \let\!!Shade=\!!qShade + \let\!!!Shade=\!!!qShade} + +% Command to set piecewise linear mode +% See Subsections 5.1, 7.3, and 7.4 of the manual. +\def\setlinear{% + \let\!drawcurve=\!lcurve + \let\!!Shade=\!!lShade + \let\!!!Shade=\!!!lShade} + +% Command to set histogram mode +% See Subsection 4.3 of the manual. +\def\sethistograms{% + \let\!drawcurve=\!hcurve} + +% Commands to cycle through list of coordinates in piecewise quadratic +% interpolation mode +\def\!qcurve #1 #2 {% + \!start (#1,#2) + \!Qjoin} +\def\!Qjoin#1 #2 #3 #4 {% + \!qjoin (#1,#2) (#3,#4) % \!qjoin is defined in QUADRATIC + \!ifnextchar/{\!finish}{\!Qjoin}} + +% Commands to cycle through list of coordinates in piecewise linear +% interpolation mode +\def\!lcurve #1 #2 {% + \!start (#1,#2) + \!Ljoin} +\def\!Ljoin#1 #2 {% + \!ljoin (#1,#2) % \!ljoin is defined in LINEAR + \!ifnextchar/{\!finish}{\!Ljoin}} + +\def\!finish/{\ignorespaces} + +% Command to cycle through list of coordinates in histogram mode +\def\!hcurve #1 #2 {% + \edef\!hxS{#1}% + \edef\!hyS{#2}% + \!hjoin} +\def\!hjoin#1 #2 {% + \putrectangle corners at {\!hxS} {\!hyS} and {#1} {#2} + \edef\!hxS{#1}% + \!ifnextchar/{\!finish}{\!hjoin}} + + +% \vshade: See Subsection 7.3 of the manual. +\def\vshade #1 #2 #3 {% + \!startvshade (#1,#2,#3) + \!Shadewhat} + +% \hshade: See Subsection 7.4 of the manual. +\def\hshade #1 #2 #3 {% + \!starthshade (#1,#2,#3) + \!Shadewhat} + +% Commands to cycle through coordinates and optional "edge effect" +% fields while shading. +\def\!Shadewhat{% + \futurelet\!nextchar\!Shade} +\def\!Shade{% + \if <\!nextchar + \def\!nextShade{\!!Shade}% + \else + \if /\!nextchar + \def\!nextShade{\!finish}% + \else + \def\!nextShade{\!!!Shade}% + \fi + \fi + \!nextShade} +\def\!!lShade<#1> #2 #3 #4 {% + \!lshade <#1> (#2,#3,#4) % \!lshade is defined in SHADING + \!Shadewhat} +\def\!!!lShade#1 #2 #3 {% + \!lshade (#1,#2,#3) + \!Shadewhat} +\def\!!qShade<#1> #2 #3 #4 #5 #6 #7 {% + \!qshade <#1> (#2,#3,#4) (#5,#6,#7) % \!qshade is defined in SHADING + \!Shadewhat} +\def\!!!qShade#1 #2 #3 #4 #5 #6 {% + \!qshade (#1,#2,#3) (#4,#5,#6) + \!Shadewhat} + +% ** Set default interpolation mode +\setlinear + + +% ******************************************** +% *** DASHPATTERNS (Sets up dash patterns) *** +% ******************************************** + +% ** User commands: +% ** \setdashpattern <DIMEN1,DIMEN2,DIMEN3,...> +% ** \setdots <INTRADOT_DISTANCE> +% ** \setdotsnear <INTRADOT_DISTANCE> for <ARC LENGTH> +% ** \setdashes <DASH/SKIP_DISTANCE> +% ** \setdashesnear <DASH/SKIP_DISTANCE> for <ARC LENGTH> +% ** \setsolid +% ** \findlength {CURVE CMDS} + +% ** Internal commands: +% ** \!dashingon +% ** \!dashingoff + +% ** Dash patterns are specified by a balanced token list whose complete +% ** expansion has the form: DIMEN1,DIMEN2,DIMEN3,DIMEN4,... ; this produces +% ** an arc of length DIMEN1, a skip of length DIMEN2, an arc of length +% ** DIMEN3, a skip of length DIMEN4, ... . Any number of DIMEN values may +% ** be given. The pattern is repeated as many times (perhaps fractional) +% ** as necessary to draw the curve. +% ** A dash pattern remains in effect until it is overridden by a call to +% ** \setdashpattern, or to \setdots, \setdotsnear ... , \setdashes, +% ** \setdashesnear ... , or \setsolid. +% ** Solid lines are the default. + + +% ** \def\setdashpattern <DIMEN1,DIMEN2,DIMEN3,...> +% ** The following routine converts a balanced list of tokens whose +% ** complete expansion has the form DIMEN1,DIMEN2, ... , DIMENk into +% ** three list macros that are used in drawing dashed rules and curves: +% ** !Flist: \!Rule{DIMEN1}\!Skip{DIMEN2}\!Rule{DIMEN3}\!Skip{DIMEN4} ... +% ** !Blist: ...\!Skip{DIMEN4}\!Rule{DIMEN3}\!Skip{DIMEN2}\!Rule{DIMEN1} +% ** !UDlist: \\{DIMEN1}\\{DIMEN2}\\{DIMEN3}\\{DIMEN4} ...; +% ** calculates \!leaderlength := DIMEN1 + ... + DIMENk; and +% ** sets the curve drawing routines to dash mode. +% ** Those lists are used by the curve drawing routines. +% ** Dimenj ... may be given as an explicit dimension (e.g., 5pt), or +% ** as an expression involving a dimension register (e.g., -2.5\dimen0). +% ** See Subsection 6.2 of the manual +\def\setdashpattern <#1>{% + \def\!Flist{}\def\!Blist{}\def\!UDlist{}% + \!countA=0 + \!ecfor\!item:=#1\do{% + \!dimenA=\!item\relax + \expandafter\!rightappend\the\!dimenA\withCS{\\}\to\!UDlist% + \advance\!countA 1 + \ifodd\!countA + \expandafter\!rightappend\the\!dimenA\withCS{\!Rule}\to\!Flist% + \expandafter\!leftappend\the\!dimenA\withCS{\!Rule}\to\!Blist% + \else + \expandafter\!rightappend\the\!dimenA\withCS{\!Skip}\to\!Flist% + \expandafter\!leftappend\the\!dimenA\withCS{\!Skip}\to\!Blist% + \fi}% + \!leaderlength=\!zpt + \def\!Rule##1{\advance\!leaderlength ##1}% + \def\!Skip##1{\advance\!leaderlength ##1}% + \!Flist% + \ifdim\!leaderlength>\!zpt + \else + \def\!Flist{\!Skip{24in}}\def\!Blist{\!Skip{24in}}\ignorespaces + \def\!UDlist{\\{\!zpt}\\{24in}}\ignorespaces + \!leaderlength=24in + \fi + \!dashingon} + + +% ** \!dashingon -- puts the curve drawing routines into dash mode +% ** \!dashingoff -- puts the curve drawing routines into solid mode +% ** These are internal commands, invoked by \setdashpattern and \setsolid +\def\!dashingon{% + \def\!advancedashing{\!!advancedashing}% + \def\!drawlinearsegment{\!lineardashed}% + \def\!puthline{\!putdashedhline}% + \def\!putvline{\!putdashedvline}% +% \def\!putsline{\!putdashedsline}% + \ignorespaces}% +\def\!dashingoff{% + \def\!advancedashing{\relax}% + \def\!drawlinearsegment{\!linearsolid}% + \def\!puthline{\!putsolidhline}% + \def\!putvline{\!putsolidvline}% +% \def\!putsline{\!putsolidsline}% + \ignorespaces} + + +% ** \setdots <LENGTH> -- sets up a dot/skip pattern where dot (actually +% ** the current plotsymbol) is plunked down once for every LENGTH +% ** traveled along the curve. LENGTH defaults to 5pt. +% ** See Subsection 6.1 of the manual. +\def\setdots{% + \!ifnextchar<{\!setdots}{\!setdots<5pt>}} +\def\!setdots<#1>{% + \!dimenB=#1\advance\!dimenB -\plotsymbolspacing + \ifdim\!dimenB<\!zpt + \!dimenB=\!zpt + \fi +\setdashpattern <\plotsymbolspacing,\!dimenB>} + +% ** \setdotsnear <LENGTH> for <ARC LENGTH> +% ** sets up a dot pattern where the dots are approximately LENGTH apart, +% ** the total length of the pattern is ARC LENGTH, and the pattern +% ** begins and ends with a dot. See Subsection 6.3 of the manual. +\def\setdotsnear <#1> for <#2>{% + \!dimenB=#2\relax \advance\!dimenB -.05pt + \!dimenC=#1\relax \!countA=\!dimenC + \!dimenD=\!dimenB \advance\!dimenD .5\!dimenC \!countB=\!dimenD + \divide \!countB \!countA + \ifnum 1>\!countB + \!countB=1 + \fi + \divide\!dimenB \!countB + \setdots <\!dimenB>} + +% ** \setdashes <LENGTH> -- sets up a dash/skip pattern where the dash +% ** and the skip are each of length LENGTH (the dash is formed by +% ** plunking down the current plotsymbol over an arc of length LENGTH +% ** and so may actually be longer than LENGTH. LENGTH defaults to 5pt. +% ** See Subsection 6.1 of the manual. +\def\setdashes{% + \!ifnextchar<{\!setdashes}{\!setdashes<5pt>}} +\def\!setdashes<#1>{\setdashpattern <#1,#1>} + +% ** \setdashesnear ... +% ** Like \setdotsnear; the pattern begins and ends with a dash. +% ** See Subsection 6.3 of the manual. +\def\setdashesnear <#1> for <#2>{% + \!dimenB=#2\relax + \!dimenC=#1\relax \!countA=\!dimenC + \!dimenD=\!dimenB \advance\!dimenD .5\!dimenC \!countB=\!dimenD + \divide \!countB \!countA + \ifodd \!countB + \else + \advance \!countB 1 + \fi + \divide\!dimenB \!countB + \setdashes <\!dimenB>} + +% ** \setsolid -- puts the curve drawing routines in "solid line" mode, +% ** the default mode. See Subsection 6.1 of the manual. +\def\setsolid{% + \def\!Flist{\!Rule{24in}}\def\!Blist{\!Rule{24in}}% + \def\!UDlist{\\{24in}\\{\!zpt}}% + \!dashingoff} +\setsolid + +% ** \findlength {CURVE CMDS} +% ** PiCTeX executes the \start, \ljoin, and \qjoin cmds comprising +% ** CURVE CMDS without plotting anything, but stashes the length +% ** of the phantom curve away in \totalarclength. +% ** See Subsection 6.3 of the manual. +\def\findlength#1{% + \begingroup + \setdashpattern <0pt, \maxdimen> + \setplotsymbol ({}) + \dontsavelinesandcurves + #1% + \endgroup + \ignorespaces} + + +% ************************************************************* +% *** DIVISION (Does long division of dimension registers) *** +% ************************************************************* + +% ** User command: +% ** \Divide {DIVIDEND} by {DIVISOR} forming {RESULT} + +% ** Internal command +% ** \!divide{DIVIDEND}{DIVISOR}{RESULT} + +% ** \!divide DIVIDEND [by] DIVISOR [to get] ANSWER +% ** Divides the dimension DIVIDEND by the dimension DIVISOR, placing the +% ** quotient in the dimension register ANSWER. Values are understood to +% ** be in points. E.g. 12.5pt/1.4pt=8.92857pt. +% ** Quotient is accurate to 1/65536pt=2**[-16]pt +% ** |DIVISOR| should be < 2048pt (about 28 inches). +\def\!divide#1#2#3{% + \!dimenB=#1% ** dimB holds current remainder (r) + \!dimenC=#2% ** dimC holds divisor (d) + \!dimenD=\!dimenB% ** dimD holds quotient q=r/d for this + \divide \!dimenD \!dimenC% ** step, in units of scaled pts + \!dimenA=\!dimenD% ** dimA eventually holds answer (a) + \multiply\!dimenD \!dimenC% ** r <-- r - dq + \advance\!dimenB -\!dimenD% ** First step complete. Have integer part +% ** of a, and corresponding remainder. + \!dimenD=\!dimenC% ** Temporarily use dimD to hold |d| + \ifdim\!dimenD<\!zpt \!dimenD=-\!dimenD + \fi + \ifdim\!dimenD<64pt% ** Branch on the magnitude of |d| + \!divstep[\!tfs]\!divstep[\!tfs]% + \else + \!!divide + \fi + #3=\!dimenA\ignorespaces} + +% ** The following code handles divisors d with +% ** (1) .88in = 64pt <= d < 256pt = 3.54in +% ** (2) 3.54in = 256pt <= d < 2048pt = 28.34in +% ** Anything bigger than that may result in an overflow condition. +% ** For our purposes, we should never even see case (2). +\def\!!divide{% + \ifdim\!dimenD<256pt + \!divstep[64]\!divstep[32]\!divstep[32]% + \else + \!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]\!divstep[8]% + \!dimenA=2\!dimenA + \fi} + + +% ** The following macro does the real long division work. +\def\!divstep[#1]{% ** #1 = "B" + \!dimenB=#1\!dimenB% ** r <-- B*r + \!dimenD=\!dimenB% ** dimD holds quotient q=r/d for this + \divide \!dimenD by \!dimenC% ** step, in units of scaled pts + \!dimenA=#1\!dimenA% ** a <-- B*a + q + \advance\!dimenA by \!dimenD% + \multiply\!dimenD by \!dimenC% ** r <-- r - dq + \advance\!dimenB by -\!dimenD} + +% ** \Divide: See Subsection 9.3 of the manual. +\def\Divide <#1> by <#2> forming <#3> {% + \!divide{#1}{#2}{#3}} + + +% ********************************************* +% *** ELLIPSES (Draws ellipses and circles) *** +% ********************************************* + +% ** User commands +% ** \ellipticalarc axes ratio A:B DEGREES degrees from XSTART YSTART +% ** center at XCENTER YCENTER +% ** \circulararc DEGREES degrees from XSTART YSTART +% ** center at XCENTER YCENTER + +% ** Internal command +% ** \!sinandcos{32*ANGLE in radians}{32*SIN}{32*COS} + + +% ** \ellipticalarc axes ratio A:B DEGREES degrees from XSTART YSTART +% ** center at XCENTER YCENTER +% ** Draws a elliptical arc starting at the coordinate point (XSTART,YSTART). +% ** The center of the ellipse of which the arc is a segment is at +% ** (XCENTER,YCENTER). +% ** The arc extends through an angle of DEGREES degrees (may be + or -). +% ** A:B is the ratio of the length of the xaxis to the length of +% ** the yaxis of the ellipse +% ** Sqrt{[(XSTART-XCENTER)/A]**2 + [(YSTART-YCENTER)/B]**2} +% ** must be < 512pt (about 7in). +% ** Doesn't modify the dimensions (ht, dp, wd) of the PiCture under +% ** construction. + +% ** \circulararc -- See Subsection 5.3 of the manual. +\def\circulararc{% + \ellipticalarc axes ratio 1:1 } + +% ** \ellipticalarc -- See Subsection 5.3 of the manual. +\def\ellipticalarc axes ratio #1:#2 #3 degrees from #4 #5 center at #6 #7 {% + \!angle=#3pt\relax% ** get angle + \ifdim\!angle>\!zpt + \def\!sign{}% ** counterclockwise + \else + \def\!sign{-}\!angle=-\!angle% ** clockwise + \fi + \!xxloc=\!M{#6}\!xunit% ** convert CENTER to dimension + \!yyloc=\!M{#7}\!yunit + \!xxS=\!M{#4}\!xunit% ** get STARTing point on rim of ellipse + \!yyS=\!M{#5}\!yunit + \advance\!xxS -\!xxloc% ** make center of ellipse (0,0) + \advance\!yyS -\!yyloc + \!divide\!xxS{#1pt}\!xxS % ** scale point on ellipse to point on + \!divide\!yyS{#2pt}\!yyS % corresponding circle +% + \let\!MC=\!M% ** save current c/d mode + \!setdimenmode% ** go into dimension mode +% + \!xS=#1\!xxS \advance\!xS\!xxloc + \!yS=#2\!yyS \advance\!yS\!yyloc + \!start (\!xS,\!yS)% + \!loop\ifdim\!angle>14.9999pt% ** draw in major portion of ellipse + \!rotate(\!xxS,\!yyS)by(\!cos,\!sign\!sin)to(\!xxM,\!yyM) + \!rotate(\!xxM,\!yyM)by(\!cos,\!sign\!sin)to(\!xxE,\!yyE) + \!xM=#1\!xxM \advance\!xM\!xxloc \!yM=#2\!yyM \advance\!yM\!yyloc + \!xE=#1\!xxE \advance\!xE\!xxloc \!yE=#2\!yyE \advance\!yE\!yyloc + \!qjoin (\!xM,\!yM) (\!xE,\!yE) + \!xxS=\!xxE \!yyS=\!yyE + \advance \!angle -15pt + \repeat + \ifdim\!angle>\!zpt% ** complete remaining arc, if any + \!angle=100.53096\!angle% ** convert angle to radians, divide + \divide \!angle 360 % ** by 2, and multiply by 32 + \!sinandcos\!angle\!!sin\!!cos% ** get 32*sin & 32*cos + \!rotate(\!xxS,\!yyS)by(\!!cos,\!sign\!!sin)to(\!xxM,\!yyM) + \!rotate(\!xxM,\!yyM)by(\!!cos,\!sign\!!sin)to(\!xxE,\!yyE) + \!xM=#1\!xxM \advance\!xM\!xxloc \!yM=#2\!yyM \advance\!yM\!yyloc + \!xE=#1\!xxE \advance\!xE\!xxloc \!yE=#2\!yyE \advance\!yE\!yyloc + \!qjoin (\!xM,\!yM) (\!xE,\!yE) + \fi +% + \let\!M=\!MC% ** restore c/d mode + \ignorespaces}% ** if appropriate + + +% ** \!rotate(XREG,YREG)by(32cos,32sin)to(XXREG,YYREG) +% ** rotates (XREG,YREG) by angle with specfied scaled cos & sin to +% ** (XXREG,YYREG). Uses \!dimenA & \!dimenB as scratch registers. +\def\!rotate(#1,#2)by(#3,#4)to(#5,#6){% + \!dimenA=#3#1\advance \!dimenA -#4#2% ** Rcos(x+t)=Rcosx*cost - Rsinx*sint + \!dimenB=#3#2\advance \!dimenB #4#1% ** Rsin(x+t)=Rsinx*cost + Rcosx*sint + \divide \!dimenA 32 \divide \!dimenB 32 + #5=\!dimenA #6=\!dimenB + \ignorespaces} +\def\!sin{4.17684}% ** 32*sin(pi/24) (pi/24=7.5deg) +\def\!cos{31.72624}% ** 32*cos(pi/24) + + +% ** \!sinandcos{32*ANGLE in radians}{\SINCS}{\COSCS} +% ** Computes the 32*sine and 32*cosine of a small ANGLE expressed in +% ** radians/32 and puts these values in the replacement texts of +% ** \SINCS and \COSCS +\def\!sinandcos#1#2#3{% + \!dimenD=#1% ** angle is expressed in radians/32: 1pt = 1/32rad + \!dimenA=\!dimenD% ** dimA will eventually contain 32sin(angle)in pts + \!dimenB=32pt% ** dimB will eventually contain 32cos(angle)in pts + \!removept\!dimenD\!value% ** get value of 32*angle, without "pt" + \!dimenC=\!dimenD% ** holds 32*angle**i/i! in pts + \!dimenC=\!value\!dimenC \divide\!dimenC by 64 % ** now 32*angle**2/2 + \advance\!dimenB by -\!dimenC% ** 32-32*angle**2/2 + \!dimenC=\!value\!dimenC \divide\!dimenC by 96 % ** now 32*angle**3/3! + \advance\!dimenA by -\!dimenC% ** now 32*(angle-angle**3/6) + \!dimenC=\!value\!dimenC \divide\!dimenC by 128 % ** now 32*angle**4/4! + \advance\!dimenB by \!dimenC% + \!removept\!dimenA#2% ** set 32*sin(angle) + \!removept\!dimenB#3% ** set 32*cos(angle) + \ignorespaces} + + +% ***************************************************************** +% *** RULES (Draws rules, i.e., horizontal & vertical lines) *** +% ***************************************************************** + +% ** User command: +% ** \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1 +% ** to XCOORD2 YCOORD2 + +% ** Internal commands: +% ** \!puthline [<XDIMEN,YDIMEN>] (h = horizontal) +% ** Set by dashpat to either: \!putsolidhline or \!putdashedhline +% ** \!putvline [<XDIMEN,YDIMEN>] (v = vertical) +% ** Either: \!putsolidvline or \!putdashedvline + + +% ** \putrule [<XDIMEN,YDIMEN>] from XCOORD1 YCOORD1 +% ** to XCOORD2 YCOORD2 +% ** Draws a rule -- dashed or solid depending on the current dash pattern -- +% ** from (X1,Y1) to (X2,Y2). Uses TEK's \hrule & \vrule & \leaders +% ** constructions to handle horizontal & vertical lines efficiently both +% ** in terms of execution time and space in the DVI file. +% ** See Subsection 4.1 of the manual. +\def\putrule#1from #2 #3 to #4 #5 {% + \!xloc=\!M{#2}\!xunit \!xxloc=\!M{#4}\!xunit% + \!yloc=\!M{#3}\!yunit \!yyloc=\!M{#5}\!yunit% + \!dxpos=\!xxloc \advance\!dxpos by -\!xloc + \!dypos=\!yyloc \advance\!dypos by -\!yloc +% + \ifdim\!dypos=\!zpt + \def\!!Line{\!puthline{#1}}\ignorespaces + \else + \ifdim\!dxpos=\!zpt + \def\!!Line{\!putvline{#1}}\ignorespaces + \else + \def\!!Line{} + \fi + \fi + \let\!ML=\!M% ** save current coord\dimen mode + \!setdimenmode% ** express locations in dimens + \!!Line% + \let\!M=\!ML% ** restore previous c/d mode + \ignorespaces} + + +% ** \!putsolidhline [<XDIMEN,YDIMEN>] +% ** Place horizontal solid line +\def\!putsolidhline#1{% + \ifdim\!dxpos>\!zpt + \put{\!hline\!dxpos}#1[l] at {\!xloc} {\!yloc} + \else + \put{\!hline{-\!dxpos}}#1[l] at {\!xxloc} {\!yyloc} + \fi + \ignorespaces} + +% ** \!putsolidvline [shifted <XDIMEN,YDIMEN>] +% ** Place vertical solid line +\def\!putsolidvline#1{% + \ifdim\!dypos>\!zpt + \put{\!vline\!dypos}#1[b] at {\!xloc} {\!yloc} + \else + \put{\!vline{-\!dypos}}#1[b] at {\!xxloc} {\!yyloc} + \fi + \ignorespaces} + +\def\!hline#1{\hbox to #1{\leaders \hrule height\linethickness\hfill}} +\def\!vline#1{\vbox to #1{\leaders \vrule width\linethickness\vfill}} + + +% ** \!putdashedhline [<XDIMEN,YDIMEN>] +% ** Place dashed horizontal line +\def\!putdashedhline#1{% + \ifdim\!dxpos>\!zpt + \!DLsetup\!Flist\!dxpos + \put{\hbox to \!totalleaderlength{\!hleaders}\!hpartialpattern\!Rtrunc} + #1[l] at {\!xloc} {\!yloc} + \else + \!DLsetup\!Blist{-\!dxpos} + \put{\!hpartialpattern\!Ltrunc\hbox to \!totalleaderlength{\!hleaders}} + #1[r] at {\!xloc} {\!yloc} + \fi + \ignorespaces} + +% ** \!putdashedhline [<XDIMEN,YDIMEN>] +% ** Place dashed vertical line +\def\!putdashedvline#1{% + \!dypos=-\!dypos% ** vertical leaders go from top to bottom + \ifdim\!dypos>\!zpt + \!DLsetup\!Flist\!dypos + \put{\vbox{\vbox to \!totalleaderlength{\!vleaders} + \!vpartialpattern\!Rtrunc}}#1[t] at {\!xloc} {\!yloc} + \else + \!DLsetup\!Blist{-\!dypos} + \put{\vbox{\!vpartialpattern\!Ltrunc + \vbox to \!totalleaderlength{\!vleaders}}}#1[b] at {\!xloc} {\!yloc} + \fi + \ignorespaces} + + +% ** The rest of the macros in this section are subroutines used by +% ** \!putdashedhline and \!putdashedvline. +\def\!DLsetup#1#2{% ** Dashed-Line set up + \let\!RSlist=#1% ** set !Rule-Skip list + \!countB=#2% ** convert rule length to integer (number of sps) + \!countA=\!leaderlength% ** ditto, leaderlength + \divide\!countB by \!countA% ** number of complete leader units + \!totalleaderlength=\!countB\!leaderlength + \!Rresiduallength=#2% + \advance \!Rresiduallength by -\!totalleaderlength% \** excess length + \!Lresiduallength=\!leaderlength + \advance \!Lresiduallength by -\!Rresiduallength + \ignorespaces} + +\def\!hleaders{% + \def\!Rule##1{\vrule height\linethickness width##1}% + \def\!Skip##1{\hskip##1}% + \leaders\hbox{\!RSlist}\hfill} + +\def\!hpartialpattern#1{% + \!dimenA=\!zpt \!dimenB=\!zpt + \def\!Rule##1{#1{##1}\vrule height\linethickness width\!dimenD}% + \def\!Skip##1{#1{##1}\hskip\!dimenD}% + \!RSlist} + +\def\!vleaders{% + \def\!Rule##1{\hrule width\linethickness height##1}% + \def\!Skip##1{\vskip##1}% + \leaders\vbox{\!RSlist}\vfill} + +\def\!vpartialpattern#1{% + \!dimenA=\!zpt \!dimenB=\!zpt + \def\!Rule##1{#1{##1}\hrule width\linethickness height\!dimenD}% + \def\!Skip##1{#1{##1}\vskip\!dimenD}% + \!RSlist} + +\def\!Rtrunc#1{\!trunc{#1}>\!Rresiduallength} +\def\!Ltrunc#1{\!trunc{#1}<\!Lresiduallength} + +\def\!trunc#1#2#3{% + \!dimenA=\!dimenB + \advance\!dimenB by #1% + \!dimenD=\!dimenB \ifdim\!dimenD#2#3\!dimenD=#3\fi + \!dimenC=\!dimenA \ifdim\!dimenC#2#3\!dimenC=#3\fi + \advance \!dimenD by -\!dimenC} + + +% **************************************************************** +% *** LINEAR ARC (Draws straight lines -- solid and dashed) *** +% **************************************************************** + +% ** User commands +% ** \inboundscheckoff +% ** \inboundscheckon + +% ** Internal commands +% ** \!start (XCOORD,YCOORD) +% ** \!ljoin (XCOORD,YCOORD) +% ** \!drawlinearsegment -- set by \dashpat to either +% ** \!linearsolid or \!lineardashed +% ** \!advancedashing -- set by \dashpat to either +% ** \relax or \!!advancedashing +% ** \!plotifinbounds -- set by \inboundscheck off/on to either +% ** \!plot or \!!plotifinbounds +% ** \!initinboundscheck -- set by \inboundscheck off/on to either +% ** \relax or \!!initinboundscheck + + +% \plotsymbolspacing ** distance between consecutive plot positions +% \!xS ** starting x +% \!yS ** starting y +% \!xE ** ending x +% \!yE ** ending y +% \!xdiff ** x_end - x_start +% \!ydiff ** y_end - y_start +% \!distacross ** how far along curve next point to be plotted is +% \!arclength ** approximate length of arc for current interval +% \!downlength ** remaining length for "pen" to be down +% \!uplength ** length for "pen" to be down +% \!intervalno ** counts segments to curve +% \totalarclength ** cumulative distance along curve +% \!npoints ** approximately (arc length / plotsymbolspacing) + +% ** Calls -- \!Pythag, \!divide, \!plot + + +% ** \!start (XCOORD,YCOORD) +% ** Sets initial point for linearly (or quadratically) interpolated curve +\def\!start (#1,#2){% + \!plotxorigin=\!xorigin \advance \!plotxorigin by \!plotsymbolxshift + \!plotyorigin=\!yorigin \advance \!plotyorigin by \!plotsymbolyshift + \!xS=\!M{#1}\!xunit \!yS=\!M{#2}\!yunit + \!rotateaboutpivot\!xS\!yS + \!copylist\!UDlist\to\!!UDlist% **\!UDlist has the form \\{dimen1}\\{dimen2}.. +% ** Routine will draw dashed line with pen +% ** down for dimen1, up for dimen2, ... + \!getnextvalueof\!downlength\from\!!UDlist + \!distacross=\!zpt% ** 1st point goes at start of curve + \!intervalno=0 % ** initialize interval counter + \global\totalarclength=\!zpt% ** initialize distance traveled along curve + \ignorespaces} + + +% ** \!ljoin (XCOORD,YCOORD) +% ** Draws a straight line starting at the last point specified +% ** by the most recent \!start, \!ljoin, or \!qjoin, and +% ** ending at (XCOORD,YCOORD). +\def\!ljoin (#1,#2){% + \advance\!intervalno by 1 + \!xE=\!M{#1}\!xunit \!yE=\!M{#2}\!yunit + \!rotateaboutpivot\!xE\!yE + \!xdiff=\!xE \advance \!xdiff by -\!xS%** xdiff = xE - xS + \!ydiff=\!yE \advance \!ydiff by -\!yS%** ydiff = yE - yS + \!Pythag\!xdiff\!ydiff\!arclength% ** arclength = sqrt(xdiff**2+ydiff**2) + \global\advance \totalarclength by \!arclength% + \!drawlinearsegment% ** set by dashpat to \!linearsolid or \!lineardashed + \!xS=\!xE \!yS=\!yE% ** shift ending points to starting points + \ignorespaces} + + +% ** The following routine is used to draw a "solid" line between (xS,yS) +% ** and (xE,yE). Points are spaced nearly every \plotsymbolspacing length +% ** along the line. +\def\!linearsolid{% + \!npoints=\!arclength + \!countA=\plotsymbolspacing + \divide\!npoints by \!countA% ** now #pts =. arclength/plotsymbolspacing + \ifnum \!npoints<1 + \!npoints=1 + \fi + \divide\!xdiff by \!npoints + \divide\!ydiff by \!npoints + \!xpos=\!xS \!ypos=\!yS +% + \loop\ifnum\!npoints>-1 + \!plotifinbounds + \advance \!xpos by \!xdiff + \advance \!ypos by \!ydiff + \advance \!npoints by -1 + \repeat + \ignorespaces} + + +% ** The following routine is used to draw a dashed line between (xS,yS) +% ** and (xE,yE). The dash pattern continues from the previous segment. +\def\!lineardashed{% +% ** + \ifdim\!distacross>\!arclength + \advance \!distacross by -\!arclength %nothing to plot in this interval +% + \else +% + \loop\ifdim\!distacross<\!arclength +% ** plot point, interpolating linearly in x and y + \!divide\!distacross\!arclength\!dimenA% ** dimA = across/arclength + \!removept\!dimenA\!t% ** \!t holds value in dimA, without the "pt" + \!xpos=\!t\!xdiff \advance \!xpos by \!xS + \!ypos=\!t\!ydiff \advance \!ypos by \!yS + \!plotifinbounds + \advance\!distacross by \plotsymbolspacing + \!advancedashing + \repeat +% + \advance \!distacross by -\!arclength% ** prepare for next interval + \fi + \ignorespaces} + + +\def\!!advancedashing{% + \advance\!downlength by -\plotsymbolspacing + \ifdim \!downlength>\!zpt + \else + \advance\!distacross by \!downlength + \!getnextvalueof\!uplength\from\!!UDlist + \advance\!distacross by \!uplength + \!getnextvalueof\!downlength\from\!!UDlist + \fi} + + +% ** \inboundscheckoff & \inboundscheckon: See Subsection 5.5 of the manual. +\def\inboundscheckoff{% + \def\!plotifinbounds{\!plot(\!xpos,\!ypos)}% + \def\!initinboundscheck{\relax}\ignorespaces} +\def\inboundscheckon{% + \def\!plotifinbounds{\!!plotifinbounds}% + \def\!initinboundscheck{\!!initinboundscheck}% + \!initinboundscheck\ignorespaces} +\inboundscheckoff + +% ** The following code plots the current point only if it falls in the +% ** current plotarea. It doesn't matter if the coordinate system has +% ** changed since the plotarea was set up. However, shifts of the plot +% ** are ignored (how the plotsymbol stands relative to its plot position is +% ** unknown anyway). +\def\!!plotifinbounds{% + \ifdim \!xpos<\!checkleft + \else + \ifdim \!xpos>\!checkright + \else + \ifdim \!ypos<\!checkbot + \else + \ifdim \!ypos>\!checktop + \else + \!plot(\!xpos,\!ypos) + \fi + \fi + \fi + \fi} + + +\def\!!initinboundscheck{% + \!checkleft=\!arealloc \advance\!checkleft by \!xorigin + \!checkright=\!arearloc \advance\!checkright by \!xorigin + \!checkbot=\!areabloc \advance\!checkbot by \!yorigin + \!checktop=\!areatloc \advance\!checktop by \!yorigin} + + +% ********************************* +% *** LOGTEN (Log_10 function) *** +% ********************************* +% +% ** \!logten{X} +% ** Calculates log_10 of X. X and LOG10(X) are in fixed point notation. +% ** X must be positive; it may have an optional `+' sign; any number +% ** of digits may be specified for X. The absolute error in LOG10(X) is +% ** less than .0001 (probably < .00006). That's about as good as you +% ** hope for, since TEX only operates to 5 figures after the decimal +% ** point anyway. + +% \!rootten=3.162278pt **** These are values are set in ALLOCATIONS +% \!tenAe=2.543275pt (=A5) +% \!tenAc=2.773839pt (=A3) +% \!tenAa=8.690286pt (=A1) + +\def\!logten#1#2{% + \expandafter\!!logten#1\!nil + \!removept\!dimenF#2% + \ignorespaces} + +\def\!!logten#1#2\!nil{% + \if -#1% + \!dimenF=\!zpt + \def\!next{\ignorespaces}% + \else + \if +#1% + \def\!next{\!!logten#2\!nil}% + \else + \if .#1% + \def\!next{\!!logten0.#2\!nil}% + \else + \def\!next{\!!!logten#1#2..\!nil}% + \fi + \fi + \fi + \!next} + +\def\!!!logten#1#2.#3.#4\!nil{% + \!dimenF=1pt % ** DimF holds log10 original argument + \if 0#1% + \!!logshift#3pt % ** Argument < 1 + \else % ** Argument >= 1 + \!logshift#2/% ** Shift decimal pt as many places + \!dimenE=#1.#2#3pt % ** as there are figures in #2 + \fi % ** Now dimE holds revised X want log10 of + \ifdim \!dimenE<\!rootten% ** Transform X to XX between sqrt(10) + \multiply \!dimenE 10 % ** and 10*sqrt(10) + \advance \!dimenF -1pt + \fi + \!dimenG=\!dimenE% ** dimG <- (XX + 10) + \advance\!dimenG 10pt + \advance\!dimenE -10pt % ** dimE <- (XX - 10) + \multiply\!dimenE 10 % ** dimE = 10*(XX-10) + \!divide\!dimenE\!dimenG\!dimenE% ** Now dimE=10t==10*(XX-10)/(XX+10) + \!removept\!dimenE\!t% ** !t=10t, with "pt" removed + \!dimenG=\!t\!dimenE% ** dimG=100t**2 + \!removept\!dimenG\!tt% ** !tt=100t**2, with "pt" removed + \!dimenH=\!tt\!tenAe% ** dimH=10*a5*(10t)**2 /100 + \divide\!dimenH 100 + \advance\!dimenH \!tenAc% ** ditto + 10*a3 + \!dimenH=\!tt\!dimenH% ** ditto * (10t)**2 /100 + \divide\!dimenH 100 + \advance\!dimenH \!tenAa% ** ditto + 10*a1 + \!dimenH=\!t\!dimenH% ** ditto * 10t / 100 + \divide\!dimenH 100 % ** Now dimH = log10(XX) - 1 + \advance\!dimenF \!dimenH}% ** dimF = log10(X) + +\def\!logshift#1{% + \if #1/% + \def\!next{\ignorespaces}% + \else + \advance\!dimenF 1pt + \def\!next{\!logshift}% + \fi + \!next} + + \def\!!logshift#1{% + \advance\!dimenF -1pt + \if 0#1% + \def\!next{\!!logshift}% + \else + \if p#1% + \!dimenF=1pt + \def\!next{\!dimenE=1p}% + \else + \def\!next{\!dimenE=#1.}% + \fi + \fi + \!next} + + +% *********************************************************** +% *** PICTURES (Basic setups for PiCtures; \put commands) *** +% *********************************************************** + +% ** User Commands: +% ** \beginpicture +% ** \endpicture +% ** \endpicturesave <XREG,YREG> +% ** \setcoordinatesystem units <XUNIT,YUNIT> point at XREF YREF +% ** \put {OBJECT} [ORIENTATION] <XSHIFT,YSHIFT> at XCOORD YCOORD +% ** \multiput {OJBECT} [ORIENTATION] <XSHIFT,YSHIFT>) at +% ** XCOORD YCOORD +% ** *NUMBER_OF_TIMES DXCOORD DYCOORD / +% ** \accountingon +% ** \accountingoff +% ** \stack [ORIENTATION] <LEADING> {LIST OF ITEMS} +% ** \lines [ORIENTATION] {LINES} +% ** \Lines [ORIENTATION] {LINES} +% ** \setdimensionmode +% ** \setcoordinatemode +% ** \Xdistance +% ** \Ydistance + +% ** Internal commands: +% ** \!setputobject{OBJECT}{[ORIENTATION]<XSHIFT,YSHIFT>} +% ** \!dimenput{OBJECT}[ORIENTATION]<XSHIFT,YSHIFT>(XDIMEN,YDIMEN) +% ** \!setdimenmode +% ** \!setcoordmode +% ** \!ifdimenmode +% ** \!ifcoordmode + + +% ** \beginpicture +% ** \endpicture +% ** \endpicturesave <XREG,YREG> +% ** \beginpicture ... \endpicture creates an hbox. Objects are +% ** placed in this box using the \put command and the like (see below). +% ** The location of an object is specified in terms of coordinate system(s) +% ** established by \setcoordinatesystem. Each coordinate system (there +% ** might be just one) specifies the length of 1 horizontal unit, the length +% ** of 1 vertical unit, and the coordinates of a "reference point". The +% ** reference points of various coordinate systems will be in the same +% ** physical location. The macros keep track of the size of the objects +% ** and their locations. The resulting hbox is the smallest hbox which +% ** encloses all the objects, and whose TEK reference point is the point +% ** on the left edge of the box closest vertically to the PICTEX reference +% ** point. Using \endpicturesave, you can (globally) save the distance TEK's +% ** reference point is to the right (respectively, up from) PICTEX's +% ** reference point in the dimension register \XREG (respectively \YREG). +% ** You can then \put the picture OBJECT into a larger picture so that its +% ** reference point is at (XCOORD,YCOORD) with the command +% ** \put {picture OBJECT} [Bl] <\XREG, \YREG> at XCOORD YCOORD + +% ** \beginpicture : See Subsection 1.1 of the manual. +\def\beginpicture{% + \setbox\!picbox=\hbox\bgroup% + \!xleft=\maxdimen + \!xright=-\maxdimen + \!ybot=\maxdimen + \!ytop=-\maxdimen} + +% ** \endpicture : See Subsection 1.1 of the manual. +\def\endpicture{% + \ifdim\!xleft=\maxdimen% ** check if nothing was put in picbox + \!xleft=\!zpt \!xright=\!zpt \!ybot=\!zpt \!ytop=\!zpt + \fi + \global\!Xleft=\!xleft \global\!Xright=\!xright + \global\!Ybot=\!ybot \global\!Ytop=\!ytop + \egroup% + \ht\!picbox=\!Ytop \dp\!picbox=-\!Ybot + \ifdim\!Ybot>\!zpt + \else + \ifdim\!Ytop<\!zpt + \!Ybot=\!Ytop + \else + \!Ybot=\!zpt + \fi + \fi + \hbox{\kern-\!Xleft\lower\!Ybot\box\!picbox\kern\!Xright}} + +% ** \endpicturesave : See Subsection 8.4 of the manual. +\def\endpicturesave <#1,#2>{% + \endpicture \global #1=\!Xleft \global #2=\!Ybot \ignorespaces} + + +% ** \setcoordinatesystem units <XUNIT,YUNIT> +% ** point at XREF YREF +% ** Each of `units <XUNIT,YUNIT>' and `point at XREF YREF' +% ** are optional. +% ** Unit lengths must be given in dimensions (e.g., <10pt,1in>). +% ** Default unit lengths are 1pt, 1pt, or previous unit lengths. +% ** Reference point is specified in current units (e.g., 3 5 ). +% ** Default reference point is 0 0 , or previous reference point. +% ** Unit lengths and reference points obey TEX's scoping rules. +% ** See Subsection 1.2 of the manual. +\def\setcoordinatesystem{% + \!ifnextchar{u}{\!getlengths } + {\!getlengths units <\!xunit,\!yunit>}} +\def\!getlengths units <#1,#2>{% + \!xunit=#1\relax + \!yunit=#2\relax + \!ifcoordmode + \let\!SCnext=\!SCccheckforRP + \else + \let\!SCnext=\!SCdcheckforRP + \fi + \!SCnext} +\def\!SCccheckforRP{% + \!ifnextchar{p}{\!cgetreference } + {\!cgetreference point at {\!xref} {\!yref} }} +\def\!cgetreference point at #1 #2 {% + \edef\!xref{#1}\edef\!yref{#2}% + \!xorigin=\!xref\!xunit \!yorigin=\!yref\!yunit + \!initinboundscheck % ** See linear.tex + \ignorespaces} +\def\!SCdcheckforRP{% + \!ifnextchar{p}{\!dgetreference}% + {\ignorespaces}} +\def\!dgetreference point at #1 #2 {% + \!xorigin=#1\relax \!yorigin=#2\relax + \ignorespaces} + + +% ** \put {OBJECT} [XY] <XDIMEN,YDIMEN> at (XCOORD,YCOORD) +% ** `[XY]' and `<XDIMEN,YDIMEN>' are optional. +% ** First OBJECT is placed in an hbox (the "objectbox") and then a +% ** "reference point" is assigned to the objectbox as follows: +% ** [1] first, the reference point is taken to be the center of the box; +% ** [2] next, centering is overridden by the specifications +% ** X=l -- reference point along the left edge of the objectbox +% ** X=r -- reference point along the right edge of the objectbox +% ** Y=b -- reference point along the bottom edge of the objectbox +% ** Y=B -- reference point along the Baseline of the objectbox +% ** Y=t -- reference point along the top edge of the objectbox; +% ** [3] finally the reference point is shifted left by XDIMEN, down +% ** by YDIMEN (both default to 0pt). +% ** The objectbox is placed within PICBOX with its reference point at +% ** (XCOORD,YCOORD). +% ** If OBJECT is a saved box, say box0, you have to write +% ** \put{\box0}... or \put{\copy0}... +% ** The objectbox is void after the put. +% ** See Subsection 2.1 of the manual. +\long\def\put#1#2 at #3 #4 {% + \!setputobject{#1}{#2}% + \!xpos=\!M{#3}\!xunit \!ypos=\!M{#4}\!yunit + \!rotateaboutpivot\!xpos\!ypos% + \advance\!xpos -\!xorigin \advance\!xpos -\!xshift + \advance\!ypos -\!yorigin \advance\!ypos -\!yshift + \kern\!xpos\raise\!ypos\box\!putobject\kern-\!xpos% + \!doaccounting\ignorespaces} + +% ** \multiput etc. Like \put. The objectbox is not voided until the +% ** termininating /, and is placed repeatedly with: +% ** XCOORD YCOORD -- the objectbox is put down with its reference point +% ** at (XCOORD,YCOORD); +% ** *N DXCOORD DYCOORD -- each of N times the current +% ** (xcoord,ycoord) is incremented by (DXCOORD,DYCOORD), and the +% ** objectbox is put down with its reference point at (xcoord,ycoord) +% ** (This specification has to follow an XCOORD YCOORD pair) +% ** See Subsection 2.2 of the manual. +\long\def\multiput #1#2 at {% + \!setputobject{#1}{#2}% + \!ifnextchar"{\!putfromfile}{\!multiput}} +\def\!putfromfile"#1"{% + \expandafter\!multiput \input #1 /} +\def\!multiput{% + \futurelet\!nextchar\!!multiput} +\def\!!multiput{% + \if *\!nextchar + \def\!nextput{\!alsoby}% + \else + \if /\!nextchar + \def\!nextput{\!finishmultiput}% + \else + \def\!nextput{\!alsoat}% + \fi + \fi + \!nextput} +\def\!finishmultiput/{% + \setbox\!putobject=\hbox{}% + \ignorespaces} + +% ** \!alsoat XCOORD YCOORD +% ** The objectbox is put down with reference point at XCOORD,YCOORD +\def\!alsoat#1 #2 {% + \!xpos=\!M{#1}\!xunit \!ypos=\!M{#2}\!yunit + \!rotateaboutpivot\!xpos\!ypos% + \advance\!xpos -\!xorigin \advance\!xpos -\!xshift + \advance\!ypos -\!yorigin \advance\!ypos -\!yshift + \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos% + \!doaccounting + \!multiput} + +% ** \!alsoby*N DXCOORD DYCOORD +% ** N times, the current (XCOORD,YCOORD) is advanced by (DXCOORD,DYCOORD), +% ** and the current (shifted, oriented) OBJECT is put down. +\def\!alsoby*#1 #2 #3 {% + \!dxpos=\!M{#2}\!xunit \!dypos=\!M{#3}\!yunit + \!rotateonly\!dxpos\!dypos + \!ntemp=#1% + \!!loop\ifnum\!ntemp>0 + \advance\!xpos by \!dxpos \advance\!ypos by \!dypos + \kern\!xpos\raise\!ypos\copy\!putobject\kern-\!xpos% + \advance\!ntemp by -1 + \repeat + \!doaccounting + \!multiput} + +% ** \accountingoff : Suspends PiCTeX's accounting of the aggregate +% ** size of the picture box. +% ** \accounting on : Reinstates accounting. +% ** See Subsection 8.2 of the manual. +\def\accountingon{\def\!doaccounting{\!!doaccounting}\ignorespaces} +\def\accountingoff{\def\!doaccounting{}\ignorespaces} +\accountingon +\def\!!doaccounting{% + \!xtemp=\!xpos + \!ytemp=\!ypos + \ifdim\!xtemp<\!xleft + \!xleft=\!xtemp + \fi + \advance\!xtemp by \!wd + \ifdim\!xright<\!xtemp + \!xright=\!xtemp + \fi + \advance\!ytemp by -\!dp + \ifdim\!ytemp<\!ybot + \!ybot=\!ytemp + \fi + \advance\!ytemp by \!dp + \advance\!ytemp by \!ht + \ifdim\!ytemp>\!ytop + \!ytop=\!ytemp + \fi} + +\long\def\!setputobject#1#2{% + \setbox\!putobject=\hbox{#1}% + \!ht=\ht\!putobject \!dp=\dp\!putobject \!wd=\wd\!putobject + \wd\!putobject=\!zpt + \!xshift=.5\!wd \!yshift=.5\!ht \advance\!yshift by -.5\!dp + \edef\!putorientation{#2}% + \expandafter\!SPOreadA\!putorientation[]\!nil% + \expandafter\!SPOreadB\!putorientation<\!zpt,\!zpt>\!nil\ignorespaces} + +\def\!SPOreadA#1[#2]#3\!nil{\!etfor\!orientation:=#2\do\!SPOreviseshift} + +\def\!SPOreadB#1<#2,#3>#4\!nil{\advance\!xshift by -#2\advance\!yshift by -#3} + +\def\!SPOreviseshift{% + \if l\!orientation + \!xshift=\!zpt + \else + \if r\!orientation + \!xshift=\!wd + \else + \if b\!orientation + \!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 diff --git a/graphics/pictex/pointers.tex b/graphics/pictex/pointers.tex new file mode 100644 index 0000000000..5c2204478a --- /dev/null +++ b/graphics/pictex/pointers.tex @@ -0,0 +1,53 @@ +% +% Pointing at things +% +% Each macro points in a different direction. The arrow is at the +% logical corner, e.g. if I \pointUpRight, the arrow is in the upper +% right corner. +% +% \pointRight{..text..} +% \pointLeft{..text..} +% \pointDown{..text..} +% \pointUp{..text..} +% +% \pointUpRight{..text..} +% \pointUpLeft{..text..} +% \pointDownRight{..text..} +% \pointDownLeft{..text..} +% +% No global boxes are used. Each macro is grouped and uses box0. +% +% Dirk Grunwald Apr 20 1988 +% +\def\pointRight#1{{#1$\rightarrow$}} +\def\pointLeft#1{{$\leftarrow$#1}} +% +\def\pointUpRight#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{#1}% +\vbox{\hbox{\hskip\wd0$\nearrow$}\copy0}\endgroup} +% +\def\pointUpLeft#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{$\nwarrow$}% +\vbox{\copy0\hbox{\hskip\wd0{}#1}}\endgroup} +% +\def\pointDownRight#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{#1}% +\vbox{\copy0\hbox{\hskip\wd0$\searrow$}}\endgroup} +% +\def\pointDownLeft#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{$\swarrow$}% +\vbox{\hbox{\hskip\wd0{}#1}\copy0}\endgroup} +% +\def\pointDown#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{#1}% +\vbox{\copy0\hbox to \wd0{\hfill$\downarrow$\hfill}}\endgroup} +% +\def\pointUp#1{% +\begingroup\offinterlineskip% +\setbox0=\hbox{#1}% +\vbox{\hbox to \wd0{\hfill$\uparrow$\hfill}\copy0}\endgroup} diff --git a/graphics/pictex/postpictex.tex b/graphics/pictex/postpictex.tex new file mode 100644 index 0000000000..d46612a862 --- /dev/null +++ b/graphics/pictex/postpictex.tex @@ -0,0 +1,44 @@ +% 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 diff --git a/graphics/pictex/prepictex.tex b/graphics/pictex/prepictex.tex new file mode 100644 index 0000000000..cd7f92e2fe --- /dev/null +++ b/graphics/pictex/prepictex.tex @@ -0,0 +1,33 @@ +% 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 diff --git a/graphics/pictex/readme.errorbars b/graphics/pictex/readme.errorbars new file mode 100644 index 0000000000..a415f3349e --- /dev/null +++ b/graphics/pictex/readme.errorbars @@ -0,0 +1,33 @@ + +Date: Wed, 29 Jun 88 09:50:04 cdt +Subject: PiCTeX macros +From: grunwald@m.cs.uiuc.edu (Dirk Grunwald) + +In TeXHaX V88 #59, David Huenemoerder asks about macros to plot error bars +in PiCTeX. + +Attached, find two macros files. The file, errorbars.tex implements plots +with and without error bars. Each point in the plot is ``marked'', e.g. +with a $\bullet$, or whatever. + +The second file, ``pointers.tex'', contains macros useful for pointing +at things in a PiCTeX graph. E.g., if you've got data like: + +\put {\pointLeft{\Full}} [l] at 0.520833 42.4616 +\plot +0 6. +0.0416667 6.36401 + .... +0.520833 42.4616 +/ + +you'll get an arrow pointing left with the tip of the arrow at the endpoint +of your data plot. + +The PiCTeX manual can be ordered for $15 from: + Michael J. Wichura + Department of Statistics + University of Chicago + 5734 University Avenue + Chicago, IL. 60637-4931 + diff --git a/graphics/pictex/texpictex.tex b/graphics/pictex/texpictex.tex new file mode 100644 index 0000000000..a8763cfd3c --- /dev/null +++ b/graphics/pictex/texpictex.tex @@ -0,0 +1,244 @@ +%NAME: texpictex.tex +% texpictex.tex -- The following macros over-ride certain definitions in the +% PiCTeX macro package. The net effect is that line-drawing is done using +% the \special's used by texpic (tpic). Several DVI printers understand +% and handle these specials. +% +% Currently, only straight lines are translated. Recently, I added a +% clipping routine to clip to the bounding box. +% +% If people extend this to included elliptic circles and quadratics, +% please forward the extensions to me (quads are used in the \arrow +% macro, making them very slow). +% +% Dirk Grunwald +% Univ. of Illinois +% grunwald@m.cs.uiuc.edu +% +\def\makebangletter{\catcode`\!=11\relax} +\def\makebangother{\catcode`\!=12\relax} +% +\makebangletter +% +% The units that texpic deals in. You should define it this way instead +% of simply saying ``0.001in'' because the difference in resolution +% actually makes a big difference +% +\newdimen\!tpu +\!tpu=1in +\divide\!tpu by 1000 +%%% +%% \!maptpus -- map a PiCTeX dimension to a TeXPiC dimension +%% using the \!tpu conversion factor. +%% +%% uses: dimen0 +%% +\def\!maptpus#1#2 {\dimen0=#1\divide \dimen0 by \!tpu #2=\dimen0} +% +% ** \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 +% +% Additions: compute size of dot, convert to TPUs and issue a pensize +% + \!dimenB=\wd\!plotsymbol + \!dimenC=\ht\!plotsymbol + \advance\!dimenC by \dp\!plotsymbol + \ifdim\!dimenB<\!dimenC \!dimenF=\!dimenC \else \!dimenF=\!dimenB\fi + \!maptpus{\!dimenF}{\!countC} + \special{pn \the\!countC} + \ignorespaces} + +\setplotsymbol({\fiverm .})% ** initialize plotsymbol + +% ** The following routine is used to draw a "solid" line between (xS,yS) +% ** and (xE,yE). Points are spaced nearly every \plotsymbolspacing length +% ** along the line. +% +% Note: this is a replacement for PicTeX \!linearsolid. +% If line clipping is enabled, the line to be drawn is +% clipped using \!clipline. If there's anything left +% to draw after clipping, it's drawn. If clipping is off, +% the line is simply drawn. In either case, line drawing +% is done by \!texpicline. +% +\def\!linearsolid{% + \let\!nextLinearAct=\!texpicline + \expandafter\ifx \!initinboundscheck \relax + \else \!clipline \if!InBounds \else \let\!nextLinearAct=\relax \fi \fi% + \!nextLinearAct% +} +% +% Texpic has increasing origin in the upper left corner, while +% pictex has origin in bottom left corner. Ergo, we flip the signs +% for y-coordinates. +% +\def\!texpicline{% +\advance\!xS by -\!xorigin +\advance\!xE by -\!xorigin +\advance\!yS by -\!yorigin +\advance\!yE by -\!yorigin +\!maptpus{\!xS}{\!countC} \!maptpus{\!yS}{\!countD} \!countD=-\!countD% +\special{pa \the\!countC \space \the\!countD}% +\!maptpus{\!xE}{\!countC} \!maptpus{\!yE}{\!countD} \!countD=-\!countD% +\special{pa \the\!countC \space \the\!countD}\special{fp}% +\ignorespaces} +% +%%% +% Code to support line clipping +% +% Line clipping routine. Clips to bounding box specified +% by (!checkleft, !checkbot) and (!checkright, !checktop). +% Note that this box is only defined if \initboundscheckon +% has been called. +% +% The clipping algorithm was published in ACM TOG Vol 3 No 1 +% by people at Berkeley, but I've forgotten the complete reference. +% This was translated from a version I wrote in C. +% +%% +% After calling \!cliplines, !InBounds tells you if the line contains +% any points within the clipping window. +% +\newif\if!InBounds +% +%% +% \!clipt -- this corresponds to the routine by the same name +% in the published algorithm. +% +% Dimens used are descibed below. All are grouped and know that +% PiCTeX doesn't use dimen0..9. Variable names are taken from +% the TOG article. The junk on the r.h.s. is indenting information +% +% Globals: dimen8 corresponds to t0 +% dimen9 corresponds to t1 +% +% clipt dimen0 corresponds to p +% dimen1 corresponds to q +% dimen2 corresponds to r +% +% !fastclip Uses bounding boxes +% +% !clipline passes dimen3 to clipt as p +% passes dimen4 to clipt as q +% uses dimen0, dimen2 +% +% +\def\!clipt#1#2{% + \dimen0=#1 \relax \dimen1=#2 \relax + \ifdim \dimen0 < \!zpt% >0 + \!divide{\dimen1}{\dimen0}{\dimen2}% + \ifdim \dimen2 > \dimen9% >1 + \global\!InBoundsfalse + \else% =1 + \ifdim \dimen2 > \dimen8 \dimen8=\dimen2 \fi + \fi% <1 + \else \ifdim \dimen0 > \!zpt% =0>1 + \!divide{\dimen1}{\dimen0}{\dimen2}% + \ifdim \dimen2 < \dimen8% >2 + \global\!InBoundsfalse + \else% =2 + \ifdim \dimen2 < \dimen9 \dimen9=\dimen2 \fi + \fi% <2 + \else% =1 + \ifdim \dimen1 < \!zpt \global\!InBoundsfalse \fi + \fi% <1 + \fi% <0 +} +% +% fastclipcheck +% +\def\!fastclip#1#2{% + \ifdim #1<\!checkleft \global\!InBoundsfalse \else + \ifdim #1>\!checkright \global\!InBoundsfalse \else + \ifdim #2<\!checkbot \global\!InBoundsfalse \else + \ifdim #2>\!checktop \global\!InBoundsfalse \else + \fi + \fi + \fi + \fi} +% +% clipline - clip a line to the current bounding box. +% assumes line is in (!xS, !yS) and extends to (!xE,!yE) and that +% \!xdiff and \!ydiff has been set up. This is normally done +% in \!lstart. +% +% \!clipline first checks to see if the start & end points are +% conainted in the clipping box. If the simple compare works, +% then no clipping is done, else \!doclip is called to +% do the actually clipping computations. +% +\def\!clipline{% + \!!initinboundscheck + \!InBoundstrue + \!fastclip{\!xS}{\!yS}% + \!fastclip{\!xE}{\!yE}% + \if!InBounds\else\!doclip\fi} +% +\def\!doclip{% +\begingroup% + \global\!InBoundstrue% + \dimen8=0pt + \dimen9=1pt + % + \dimen3=-\!xdiff + \dimen4=\!xS \advance\dimen4 by -\!checkleft% fromX-minX + \!clipt{\dimen3}{\dimen4}% +% + \if!InBounds% 0 + \dimen3=\!xdiff + \dimen4=\!checkright \advance\dimen4 by -\!xS% maxX - fromX + \!clipt{\dimen3}{\dimen4}% +% + \if!InBounds% 1 +% + \dimen3=-\!ydiff + \dimen4=\!yS \advance\dimen4 by -\!checkbot% fromY-minY + \!clipt{\dimen3}{\dimen4}% +% + \if!InBounds% 2 +% + \dimen3=\!ydiff + \dimen4=\!checktop \advance\dimen4 by -\!yS% maxY-fromY + \!clipt{\dimen3}{\dimen4}% +% + \if!InBounds% 3 + \dimen0=1pt +% +% The following \if's truncate the line based on the solution +% to the parametric solution to the bounding box. +% +% Note that we don't have a \!multiply, the equivilent to \!divide. +% The code below compute X * Y as (x / ( 1/ Y)), which is far +% from optimal. +% + \ifdim\dimen9 < \dimen0% 4 + \!divide{\dimen0}{\dimen9}{\dimen2}% +% + \dimen3=\!xdiff \!divide{\dimen3}{\dimen2}{\dimen4}% + \global\!xE=\dimen4 \global\advance\!xE by \!xS +% + \dimen3=\!ydiff \!divide{\dimen3}{\dimen2}{\dimen4}% + \global\!yE=\dimen4 \global\advance\!yE by \!yS + \fi% 4 + \ifdim\dimen8 > \!zpt% 4 + \!divide{\dimen0}{\dimen8}{\dimen2}% +% + \dimen3=\!xdiff \!divide{\dimen3}{\dimen2}{\dimen4}% + \global\advance\!xS by \dimen4 +% + \dimen3=\!ydiff \!divide{\dimen3}{\dimen2}{\dimen4}% + \global\advance\!yS by \dimen4 + \fi% 4 + \fi% 3 + \fi% 2 + \fi% 1 + \fi% 0 +\endgroup} +% +\makebangother diff --git a/graphics/pictex/tree.sty b/graphics/pictex/tree.sty new file mode 100644 index 0000000000..6e91652a0e --- /dev/null +++ b/graphics/pictex/tree.sty @@ -0,0 +1,353 @@ +% Binary tree drawing in LaTeX using the PiCTeX macros. +% +% Edward M. Reingold (reingold@cs.uiuc.edu) +% Nachum Dershowitz (nachum@cs.uiuc.edu) +% +\typeout{Binary Tree Macros. Released 18 Jan 1991; modified 2 Apr 1992.} +% +% These macros are in the public domain. You may use them and copy them at +% will, provided you retain the authorship information. +% +% +% USAGE: \tree[optional root symbol]{left subtree}{right subtree} +% +% For example, +% +% \tree[X] +% {\setdots\tree[Z] +% {\setsolid\tree[Y]{a}{}} +% {\setsolid\tree{c}{d}}} +% {\tree +% {\tree{}{f}} +% {\tree{g}{h}}} +% +% The root symbol and leaves can be anything you can construct in LaTeX +% or PiCTeX. The trees constructed can be used in any context in LaTeX +% or PiCTeX. That is, you can have, say, tables of trees of equations. +% +% +% WARNING: Do not use the tilde (~) as the first character in any subtree! +% +% +% PARAMETERS: Feel free to change the following tree drawing parameters; +% these parameters can be reset even in the middle of a tree. +% +\newdimen\subtreesep \subtreesep=10pt % Distance between nonempty subtrees +\newdimen\levelsep \levelsep=30pt % Distance between successive levels +\def\nodesymbol{$\bullet$} % Default symbol for an internal node +% Tree edges connecting to the default node symbol +% will go to it's center. Other tree edges will be +% chopped off at a node's bounding box. +% +% +% Here's an example that changes the parameters in the middle of the tree: +% +% \subtreesep=15pt\levelsep=40pt +% \tree[\fbox{\subtreesep=5pt\levelsep=13pt\tree[o]{a}{a}}] +% {b}{b} +% +% +% You can get triangular subtrees by using \triangle which has the format +% +% \triangle[optional apex label]{width}{height} +% +% For example, +% +% \tree{\triangle[A]{2\subtreesep}{2\levelsep}} +% {\tree{\triangle{\subtreesep}{\levelsep}} +% {\tree{\fbox{}} +% {\fbox{}}}} +% +% +% Don't fiddle with the stuff that follows; it's fairly delicate. +% +% Working variables +% +\catcode`@=11% +\newdimen\halfsubtreesep % half the subtree separation +% +\newdimen\leftwd % width of left subtree +\newdimen\rightwd % width of right subtree +% +\newcount\rootbullet % flag indicating if root is the default bullet +\newdimen\rootwd % width of root +\newdimen\rootht % height of root +\newdimen\rootdp % depth of root +% +\newcount\leftrootbullet % flag indicating if left root is the default bullet +\newdimen\leftrootht % height of left subtree's root +\newdimen\leftrootwd % width of left subtree's root +\newcount\rightrootbullet% flag indicating if right root is the default bullet +\newdimen\rightrootht % height of right subtree's root +\newdimen\rightrootwd % width of right subtree's root +% +\newdimen\@@root % distance of root midpointfrom left edge of tree +\newdimen\leftroot % distance of root midpoint of left subtree + % from left edge of tree +\newdimen\rightroot % distance of root midpoint of right subtree + % from left edge of tree +% +\newcount\leafnode % flag indicating if subtree just placed is a leaf +% +\newdimen\rootxpos % x-cooordinate of the root midpoint +\newdimen\leftrootpos % position of the root of the left subtree +\newdimen\rightrootpos % position of the root of the right subtree +\newdimen\leftpos % position of the NE corner of the left subtree +\newdimen\rightpos % position of the NW corner of the right subtree +% +\newbox\rootnode % the root node, as placed +\newbox\leftsubtree % the left subtree, as placed +\newbox\rightsubtree % the right subtree, as placed +% +\newdimen\xa % (\xa,\ya) = coordinates of the point on the root +\newdimen\ya % node at which to connect the line to a child +\newdimen\xb % (\xb,\yb) = coordinates of the point on the child +\newdimen\yb % at which to connect the line to the parent +% +\let\ifnextchar=\@ifnextchar% +\def\tree{\ignorespaces% +\def\tree{\ifnextchar[{\treey}{\treex}}% +% +\setdimensionmode% +\setlinear% +% +\@ifnextchar[{\treey}{\treex}% +}% +% +\long\def\treex#1#2{\itree{#1}{#2}{\nodesymbol}} % use default node symbol +\long\def\treey[#1]#2#3{\itree{#2}{#3}{#1}} % use specified node symbol +% +\long\def\itree#1#2#3{\ignorespaces % #1=left, #2=right, #3=root +% +\halfsubtreesep=\subtreesep % Do this calculation for each node so its... +\divide\halfsubtreesep by 2 % ...value can vary throughout the tree +% +\ignorespaces% +% +% Recursively draw nonempty left subtree +% +\ifx ~#1~\ignorespaces% + \else% + \leafnode=1 % Assume left subtree is a leaf + \setbox\leftsubtree=\hbox{#1}\ignorespaces + \leftwd=\wd\leftsubtree% + \leftroot=\@@root% + \leftrootbullet=\rootbullet% + \leftrootht=\rootht% + \leftrootwd=\rootwd% + \ifnum \leafnode=1% + \leftroot=\leftwd% + \divide\leftroot by 2% + \leftrootbullet=0% + \leftrootht=\ht\leftsubtree% + \advance\leftrootht by \dp\leftsubtree% + \leftrootwd=\leftwd% + \fi% +\fi% +% +% Recursively draw nonempty right subtree +% +\ifx ~#2~\ignorespaces% + \else% + \leafnode=1 % Assume right subtree is a leaf + \setbox\rightsubtree=\hbox{#2}\ignorespaces% + \rightwd=\wd\rightsubtree% + \rightroot=\@@root% + \rightrootbullet=\rootbullet% + \rightrootht=\rootht% + \rightrootwd=\rootwd% + \ifnum \leafnode=1% + \rightroot=\rightwd% + \divide\rightroot by 2% + \rightrootbullet=0% + \rightrootht=\ht\rightsubtree% + \advance\rightrootht by \dp\rightsubtree% + \rightrootwd=\rightwd% + \fi% +\fi% +% +% In the case of empty subtrees, give artificial values for those empty +% trees so that the later calculations are done properly. +% +\ifx ~#1#2~\ignorespaces % Both subtrees empty + \rightroot=0pt% + \leftroot=-\halfsubtreesep% + \leftwd=-\halfsubtreesep% +\else\ifx ~#1~\ignorespaces % Left subtree empty, right subtree not empty + \leftroot=\rightroot% + \advance\leftroot by -\subtreesep% + \leftwd=-\subtreesep% +\else\ifx ~#2~\ignorespaces % Right subtree empty, left subtree not empty + \rightroot=\leftroot% + \advance\rightroot by -\leftwd% +\fi\fi\fi% +% +% With the subtrees done, now do the root node +% +\setbox\rootnode=\hbox{\setcoordinatemode #3}\ignorespaces% +\global\rootwd=\wd\rootnode% +\global\rootht=\ht\rootnode% +\global\advance\rootht by \dp\rootnode% +\ifx \nodesymbol#3\ignorespaces% + \global\rootbullet=1% + \else\ignorespaces% + \global\rootbullet=0% +\fi% +% +% Find distance of the root midpoint from left edge of the tree +% +\global\@@root=\leftroot% +\global\advance\@@root by \rightroot% +\global\advance\@@root by \leftwd% +\global\advance\@@root by \subtreesep% +\ifdim \@@root<\rootwd \global\@@root=\rootwd \fi% +\global\divide\@@root by 2% +% +% Indicate this root and all its ancestors are not a leaves +% +\global\leafnode=0% +% +% Find positions of the root and those of the roots of the subtrees +% +\leftrootpos=\leftroot% +\advance\leftrootpos by -\leftwd% +\advance\leftrootpos by -\halfsubtreesep% +% +\rightrootpos=\rightroot% +\advance\rightrootpos by \halfsubtreesep% +% +\rootxpos=\leftrootpos% +\advance\rootxpos by \rightrootpos% +\divide\rootxpos by 2% +% +\leftpos=0pt% +\advance\leftpos by \leftrootht% +\divide\leftpos by 2% +% +\rightpos=0pt% +\advance\rightpos by \rightrootht% +\divide\rightpos by 2% +% +% Now the root is a box of width \rootwd and total height \rootht, centered +% at (\rootxpos,\levelsep); the root of the left subtree is a box of +% width \leftrootwd and total height \leftrootht, centered at +% (\leftrootpos,0); the root of the right subtree is a box of width +% \rightrootwd and total height \rightrootht, centered at (\rightrootpos,0). +% +% +\beginpicture +% +\put {\box\rootnode} at {\rootxpos} {\levelsep} % Draw the root +% +\ifx ~#1~\else % Draw the left subtree + \put {\box\leftsubtree} [rt] at {-\halfsubtreesep} {\leftpos} + \xa=\rootxpos% + \ya=\levelsep% + \ifnum\rootbullet=0% + \chop{\rootxpos}{\levelsep}{-\rootwd}{\rootht}{\leftrootpos}{0}% + {\xa}{\ya}% + \fi% + \xb=\leftrootpos% + \yb=0pt% + \ifnum\leftrootbullet=0% + \chop{\leftrootpos}{0}{\leftrootwd}{-\leftrootht}{\rootxpos}{\levelsep}% + {\xb}{\yb}% + \fi% + \plot {\xa} {\ya} {\xb} {\yb} /% +\fi% +% +\ifx ~#2~\else % Draw the right subtree + \put {\box\rightsubtree} [lt] at {\halfsubtreesep} {\rightpos} + \xa=\rootxpos% + \ya=\levelsep% + \ifnum\rootbullet=0% + \chop{\rootxpos}{\levelsep}{\rootwd}{\rootht}{\rightrootpos}{0}% + {\xa}{\ya}% + \fi% + \xb=\rightrootpos% + \yb=0pt% + \ifnum\rightrootbullet=0% + \chop{\rightrootpos}{0}{-\rightrootwd}{-\rightrootht}{\rootxpos}% + {\levelsep}{\xb}{\yb}% + \fi + \plot {\xa} {\ya} {\xb} {\yb} /% +\fi% +% +% Draw the bottom of the triangle, when appropriate. +% +\ifx#1. \ifx#2. \plot {\leftrootpos} {0pt} {\rightrootpos} {0pt} / \fi\fi% +% +\endpicture% +}% +% +\long\def\triangle{\ifnextchar[{\triangley}{\trianglex}}% +\long\def\trianglex#1#2{\itriangle{#1}{#2}{}} % use empty apex symbol +\long\def\triangley[#1]#2#3{\itriangle{#2}{#3}{#1}} % use specified apex symbol +\long\def\itriangle#1#2#3{% A triangle #1 wide and #2 high, #3 at apex + \subtreesep=#1% + \levelsep=#2% + \tree[#3]{.}{.}% +}% +% +\newcount\@@x% Scratch counters used in the computations of \chop +\newcount\@@y% to find the location on the border of a node's bounding +\newcount\@@a% box at which to attach a line aimed at a target point +\newcount\@@b% from the center of the box. +\newcount\@@c% +\newcount\@@d% It would be better to do all these calculation in dimen's +\newcount\@@e% instead of counters, but so many dimen's are used above +\newcount\@@f% that to do so would make running out of dimen's very probable. +\newcount\@@g% +\newcount\@@h% Forgive us for not explaining the following computations; +\newcount\@@l% they're based on elementary analytical geometry. +% +\def\chop#1#2#3#4#5#6#7#8{\ignorespaces% + % (#1,#2) = coordinates of center of bounding box + % #3 x #4 = width x height of bounding box + % (#5,#6) = coordinates of target point + % (#7,#8) = coordinates of computed intersection + % point +% +\@@a=#1\divide \@@a by 10000% Scale down to prevent arithmetic overflow. +\@@b=#2\divide \@@b by 10000% +\@@c=#3\divide \@@c by 10000% +\@@d=#4\divide \@@d by 10000% +\@@e=#5\divide \@@e by 10000% +\@@f=#6\divide \@@f by 10000% +% +\@@l=-\@@f\advance\@@l by \@@b% +%% +\@@y=-\@@d% +\divide \@@y by 2% +\advance\@@y by \@@b% +%% +\@@g=\@@c% +\divide \@@g by 2% +\advance\@@g by \@@a% +%% +\@@x=-\@@a% +\advance\@@x by \@@e% +\multiply\@@x by \@@d% +\divide\@@x by \@@l% +\divide\@@x by 2% +\advance \@@x by \@@a% +%% +\count255=-\@@a% +\advance\count255 by \@@e% +\multiply\count255 by 2% +\@@h=-\@@c% +\multiply \@@h by \@@l% +\divide \@@h by \count255% +\advance \@@h by \@@b% +% +\ifnum #5>#1% + \ifnum\@@x>\@@g\else\@@g=\@@x\@@h=\@@y\fi% +\else% + \ifnum\@@x<\@@g\else\@@g=\@@x\@@h=\@@y\fi% +\fi% +\multiply\@@g by 10000% Scale back up +\multiply\@@h by 10000% +\global#7=\@@g sp% +\global#8=\@@h sp% +}% +\catcode`@=12% |