% smallgrf.sty
% 15-apr-92 ... birth: some rude grafics functions to design diagrams

\newif\ifsmallgrfverbose \smallgrfverbosefalse

% \point#1(#2)#3
%   #1 ... point's name
%   #2 ... coordinate: dimen,dimen
%   #3 ... point's label
%   defines point and sets label centered on the point
% \point#1#2(#3)#4
%   #1 ... point's name
%   #2 ... base point's name
%   #3 ... relative coordinate: dimen,dimen
%   #4 ... point's label
%   defines point and sets label centered on the point
% \shift(#1,#2)
%   #1,#2 ... x,y-shift
%   defines shift for the next command (applies to \link,\arrow,\notarrow)
% \link#1#2
% \arrow#1#2
% \notarrow#1#2
%   #1 ... start point's name (of a prev. \point ...)
%   #2 ... end point's name (...)
%   draws a line, arrow, negated_arrow resp. from start to end point
% \midput(#1,#2)#3
%   #1,#2 ... x,y-shift (optional)
%   sets #3 at latest coordinate center + x,y-shift
% \pointsep
%   a dimen which determines amount of extra free space around
%   point labels
% \cbox{#1}
%   #1 ... contents
%   creates a box of width, height and depth 0 with contents centered
%
\def\cbox#1{\hbox to 0pt{\hss\vbox to 0pt{\vss\hbox{#1}\vss}\hss}}
\newcount\xa \newcount\xb \newcount\xd
\newcount\ya \newcount\yb \newcount\yd
\newcount\vl
\let\a\@tempcnta%\newcount\a 
\let\b\@tempcntb%\newcount\b 
\let\c\count@%\newcount\c
\newcount\ndx \newcount\dx% next and current value
\newcount\ndy \newcount\dy
\def\setcoord#1#2{%
    \edef\latestcoord{\csname #1\endcsname\csname #2\endcsname}
    \expandafter\verify\latestcoord0(,)[,](,)[,]1*}
\def\getshift{\dx\ndx \dy\ndy \ndx\z@ \ndy\z@}
% ( BM
\def\verify#1,#2)[#3,#4](#5,#6)[#7]#8#9*{%
    \def\@tempa{#8}\def\@tempb{0}\ifx\@tempa\@tempb
    \else
    \let\@tempa\latestcoord
    \def\latestcoord{(0,0)[0pt,0pt](0,0)[0pt,0pt]}
    \errhlp{I suppose both points are zero, so we may proceed.^^J%
            You may type `I\setcoord{...}{...}' to retry.^^J%
            You may want to type `I\def\latestcoord{...}'^^J%
            but I won't verify what you'll give me then.}
    \errmsg{\string\latestcoord was `\@tempa'.^^J%
            Probably, you used an undefined point.}
    \fi}
\def\calcfine{\expandafter\c@lcfine\latestcoord}
\def\c@lcfine(#1,#2)[#3,#4](#5,#6)[#7,#8]{%
    \xa=#1\relax \advance\xa\dx
    \ya=#2\relax \advance\ya\dy
    \xb=#5\relax \advance\xb\dx
    \yb=#6\relax \advance\yb\dy
    \ifsmallgrfverbose\typeout{In : (\the\xa,\the\ya)[#3,#4]
                - (\the\xb,\the\yb)[#7,#8]}\fi
    \advance\xb-\xa
    \advance\yb-\ya
    \a\xb \ifnum\a<0 \a=-\a \fi
    \b\yb \ifnum\b<0 \b=-\b \fi
    \ifnum\a<\b \c\b \else \c\a \fi
    \ifnum\c=0
        \typeout{No line drawn between two equal points!}
    \else
% (\xa,\ya) += { \sizex/\xb | \sizey/\yb }* (\xb,\yb)
        \@tempdima#4 \multiply\@tempdima\a
        \@tempdimb#3 \multiply\@tempdimb\b
        \ifnum\@tempdima>\@tempdimb
            \c\a \dimen@#3 \divide\dimen@\unitlength\relax
        \else
            \c\b \dimen@#4 \divide\dimen@\unitlength\relax
        \fi% \c = eine Lnge
        \xd\xb \multiply\xd\dimen@ \divide\xd\c \advance\xa\xd
        \yd\yb \multiply\yd\dimen@ \divide\yd\c \advance\ya\yd
        \@tempdima#8 \multiply\@tempdima\a
        \@tempdimb#7 \multiply\@tempdimb\b
        \ifnum\@tempdima>\@tempdimb
            \c\a \dimen@#7 \divide\dimen@\unitlength\relax
        \else
            \c\b \dimen@#8 \divide\dimen@\unitlength\relax
        \fi% \c = eine Lnge
        \vl\xb \multiply\vl\dimen@ \divide\vl\c \advance\xd\vl
        \vl\yb \multiply\vl\dimen@ \divide\vl\c \advance\yd\vl
        \ifnum\xd<0\xd=-\xd\fi
        \ifnum\yd<0\yd=-\yd\fi
        \ifnum\a=0
            \vl\b \advance\vl-\yd
            \ifnum\yb>0 \yb\@ne \else \yb\m@ne \fi
        \else
            \vl\a \advance\vl-\xd
            \ifnum\b=0
                \ifnum\xb>0 \xb\@ne \else \xb\m@ne \fi
            \else
                \loop
                    \ifnum\a<\b     \c\a \a\b \b\c
                    \else           \advance\a-\b
                    \fi
                \ifnum\a>0
                \repeat
                \ifnum\b>1 \divide\xb\b \divide\yb\b \fi
            \fi
        \fi
    \fi
    \ifsmallgrfverbose
      \typeout{Out: (\the\xa,\the\ya)+\the\vl(\the\xb,\the\yb)}%
    \fi
    }
\def\calcmid{\expandafter\c@lcmid\latestcoord}
\def\c@lcmid(#1,#2)[#3](#4,#5)[#6]{%
    \xa=#1\relax \advance\xa\dx
    \ya=#2\relax \advance\ya\dy
    \xb=#4\relax \advance\xb\dx
    \yb=#5\relax \advance\yb\dy
    \advance\xa\xb \divide\xa\tw@
    \advance\ya\yb \divide\ya\tw@}
\def\point#1{\@ifnextchar({\p@int{#1}}{\p@intrel{#1}}}% ) BM
\def\p@intrel#1#2(#3){\edef\@tempa{\csname #2\endcsname}%
    \expandafter\p@intrela\@tempa(#3){#1}}
\def\p@intrela(#1,#2)(#3,#4){%
    \xa#1 \advance\xa#3\relax
    \ya#2 \advance\ya#4\relax
    \edef\@tempa{(\the\xa,\the\ya)}%
    \expandafter\p@intrelb\@tempa}
\def\p@intrelb(#1)#2{\p@int{#2}(#1)}
\def\p@int#1(#2)#3{%
    \setbox0\hbox{#3}%
    \@tempdima.5\wd0           
    \@tempdimb.5\dp0\advance\@tempdimb.5\ht0 
    \advance\@tempdima\pointsep
    \advance\@tempdimb\pointsep
    \expandafter\edef\csname #1\endcsname
        {(#2)[\the\@tempdima,\the\@tempdimb]}%
    \ifsmallgrfverbose\typeout{#1=\csname #1\endcsname}\fi
    \put(#2){\cbox{\box0}}}
\def\shift(#1,#2){\ndx#1\relax \ndy#2\relax}
\def\link#1#2{%
    \setcoord{#1}{#2}\getshift
    \calcfine\put(\xa,\ya){\line(\xb,\yb){\vl}}}
\def\arrow#1#2{%
    \setcoord{#1}{#2}\getshift
    \calcfine\put(\xa,\ya){\vector(\xb,\yb){\vl}}}
\def\notarrow#1#2{%
    \setcoord{#1}{#2}\getshift
    \calcfine\put(\xa,\ya){\vector(\xb,\yb){\vl}}%
    \calcmid {\thinlines\advance\xa-10\advance\ya-10
                \put(\xa,\ya){\line(1,1){20}}}}%
\def\midput{\@ifnextchar({\m@dput}{\m@dput(0,0)}}% ) BM
\def\m@dput(#1,#2){%
    \calcmid \advance\xa #1\relax \advance\ya #2\relax
    \ifsmallgrfverbose\typeout{mid: (\the\xa,\the\ya)}\fi
    \put(\xa,\ya)}

\newdimen\pointsep \pointsep.5em

\endinput

% -------------------  an example follows -----------------
% From: nuesken@lie.mathe.uni-konstanz.de (Michael N"usken)
% Subject: smallgrf.sty
% Date: 8 Oct 1993 09:20:29 GMT
%
\documentstyle[smallgrf]{article}
\author{Michael N\"usken (nuesken@lie.mathe.uni-konstanz.de)}
\title{smallgrf.sty}
\date{8 Oct 1993 09:20:29 GMT}
\begin{document}
\maketitle

This is an extension to the \LaTeX{} picture environment.

In order to produce small diagrams with certain labels
joined by arrows or lines now you can go this like:

You only need to define your `point's:
\begin{verbatim}
   \point{NAME}(X,Y){Label}
\end{verbatim}
and then ask for lines/arrows between your points:
\begin{verbatim}
   \arrow{NAME1}{NAME2}% draws an arrow from point NAME1 to NAME2
                       % without drawing through the labels!
\end{verbatim}
and possibly attach labels to the arrow (this is not
entirely automatic yet):
\begin{verbatim}
   \midput(DX,DY){\cbox{LABEL}}%
                       % adds a label at the mid of the latest
                       % drawn arrow/line with offset DX,DY
\end{verbatim}
Some other features might be read of directly.
[The style is totally commented, as usual.  :$-$) ]

One example:
$$
\begin{picture}(130,70)(-5,-35)
  \point{H0}(  0,  0){$X$}
  \point{H1}( 30, 30){$A$}
  \point{H2}( 30,-30){$B$}
  \arrow{H0}{H1} \midput( -5,  5){\cbox{$\alpha$}}
  \arrow{H0}{H2} \midput( -5, -5){\cbox{$\beta$}}
  \point{L} ( 60,  0){$L$}
  \arrow{H1}{L}  %\midput(  5,  5){\cbox{$\lambda_1$}}
  \arrow{H0}{L}  %\midput(  0,  5){$\lambda_0$}
  \arrow{H2}{L}  %\midput(  5, -5){\cbox{$\lambda_2$}}
  \point{G} (120,  0){$G$}
  \arrow{H1}{G}  \midput(  5,  5){\cbox{$\gamma_1$}}
  \arrow{H2}{G}  \midput(  5, -5){\cbox{$\gamma_2$}}
  \thicklines
  \arrow{L}{G}   \midput(-10,  5)%
              {\hbox to0pt{\hss$\exists^!\; \phi$\hss}}
\end{picture}
$$
is given by
\begin{verbatim}
$$
\begin{picture}(130,70)(-5,-35)
  \point{H0}(  0,  0){$X$}
  \point{H1}( 30, 30){$A$}
  \point{H2}( 30,-30){$B$}
  \arrow{H0}{H1} \midput( -5,  5){\cbox{$\alpha$}}
  \arrow{H0}{H2} \midput( -5, -5){\cbox{$\beta$}}
  \point{L} ( 60,  0){$L$}
  \arrow{H1}{L}  %\midput(  5,  5){\cbox{$\lambda_1$}}
  \arrow{H0}{L}  %\midput(  0,  5){$\lambda_0$}
  \arrow{H2}{L}  %\midput(  5, -5){\cbox{$\lambda_2$}}
  \point{G} (120,  0){$G$}
  \arrow{H1}{G}  \midput(  5,  5){\cbox{$\gamma_1$}}
  \arrow{H2}{G}  \midput(  5, -5){\cbox{$\gamma_2$}}
  \thicklines
  \arrow{L}{G}   \midput(-10,  5)%
              {\hbox to0pt{\hss$\exists^!\; \phi$\hss}}
\end{picture}
$$
\end{verbatim}

\begin{description}
\item[! Be careful:] the style tries to find the best approximation
  for the ratio of the line. As LaTeX allows only numerators and
  denumerators from 0 to 4 resp. 6 for arrows resp. lines,
  the lines may point somewhat away from the desired direction.
  Solution: use only integer of a given value ...

\item[!] The style is no final solution, but one which was not
  changed for more than a year; in spite of: I was using
  it some times.
\end{description}

\end{document}

% Enjoy, |\/|
%        | \|
