\ProvidesPackage{pgfnodes}[2003/07/18 ver 0.1]

% Copyright 2003 by Till Tantau <tantau@cs.tu-berlin.de>.
%
% This program can be redistributed and/or modified under the terms
% of the LaTeX Project Public License Distributed from CTAN
% archives in directory macros/latex/base/lppl.txt.

\RequirePackage{pgf}

\ProcessOptions


% Defines a circle node of name #1 at position #3 of radius #4.
%
% #1 = a name
% #2 = ``stroke'' or ``fill'' or ``fillstroke'' or ``virtual'' (= draw
%      nothing)
% #3 = a point
% #4 = a radius
%
% Example:
%
% \pgfnodecircle{mynode}[stroke]{\pgfxy(1,1)}{2cm}

\def\pgfnodecircle#1[#2]#3#4{%
  \pgf@process{#3}%
  \expandafter\def\csname pgfno@#1\endcsname{\pgf@backoffcircle{#4}}%
  \expandafter\def\csname pgfnob@#1\endcsname{\pgf@anglecircle{#4}}%
  \expandafter\edef\csname pgfnom@#1\endcsname{\noexpand\pgf@x=\pgfget
    xpt\noexpand\pgf@y=\pgfget ypt}% 
  \expandafter\ifx\csname pgf@@#2\endcsname\pgf@@virtual%
  \else%
  \pgfcircle[#2]{\csname pgfnom@#1\endcsname}{#4}%
  \fi\ignorespaces}

\def\pgf@@virtual{}


% Defines a rectangular node of name #1 with center at position #3 and
% width/height vector #4
%
% #1 = a name
% #2 = ``stroke'' or ``fill'' or ``fillstroke'' or ``virtual'' (= draw
%      nothing)
% #3 = a center
% #4 = width/height vector
%
% Example:
%
% \pgfnoderect{mynode}[stroke]{\pgfxy(1,1)}{\pgfxy(2,2)}

\def\pgfnoderect#1[#2]#3#4{%
  \pgf@process{#3}%
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \pgf@process{#4}%
  \pgf@x=.5\pgf@x%
  \pgf@y=.5\pgf@y%  
  \expandafter\edef\csname pgfno@#1\endcsname{\noexpand\pgf@backoffrect%
    {\pgfget{x}pt}{\pgfget{y}pt}}%
  \expandafter\edef\csname pgfnob@#1\endcsname{\noexpand\pgf@anglerect%
    {\pgfget{x}pt}{\pgfget{y}pt}}%
  \expandafter\edef\csname
  pgfnom@#1\endcsname{\noexpand\pgf@x=\pgfget{xa}pt\noexpand\pgf@y=\pgfget{ya}pt}% 
  \expandafter\ifx\csname pgf@@#2\endcsname\pgf@@virtual%
  \else%
  \advance\pgf@xa by-\pgf@x%
  \advance\pgf@ya by-\pgf@y%
  \edef\pgf@temp{\noexpand\pgf@x=\pgfget{xa}pt\noexpand\pgf@y=\pgfget{ya}pt}%
  \pgfrect[#2]{\pgf@temp}{#4}%
  \fi\ignorespaces}


% Defines a rectangular node of name #1 with center at position #3 
% contaning a box #4
%
% #1 = a name
% #2 = ``stroke'' or ``fill'' or ``fillstroke'' or ``virtual'' (= draw
%      nothing)
% #3 = a center
% #4 = TeX text that will be boxed
% #5 = a horizontal border offset
% #6 = a vertical border offset
%
% Example:
%
% \pgfnodebox{mynode}[stroke]{\pgfxy(1,1)}{start}{2pt}{2pt}

\def\pgfnodebox#1[#2]#3#4#5#6{%
  \setbox\pgf@hbox=\hbox{\selectfont#4}%
  \pgf@x=\wd\pgf@hbox%
  \pgf@y=\ht\pgf@hbox%
  \advance\pgf@x by #5\relax%
  \advance\pgf@x by #5\relax%
  \advance\pgf@y by #6\relax%
  \advance\pgf@y by #6\relax%
  \edef\pgf@boxsize{\noexpand\pgf@x=\the\pgf@x\noexpand\pgf@y=\the\pgf@y}%
  \csname pgf@haligncenter\endcsname%
  \csname pgf@valigncenter\endcsname%
  \wd\pgf@hbox=0pt%
  \pgfputat{#3}{%
  \pgfsys@starthbox%
  \box\pgf@hbox%
  \pgfsys@endhbox}%
  \pgfnoderect{#1}[#2]{#3}{\pgf@boxsize}\ignorespaces}




% Retrieves the center of #1.
%
% #1 = a node name
%
% Example:
%
% \pgfmoveto{\pgfnodecenter{mynode}}

\def\pgfnodecenter#1{%
  \expandafter\ifx\csname pgfnom@#1\endcsname\relax%
  \GenericError{\space\space\space\@spaces\@spaces\@spaces}%
  {PGF Error: Node "#1" undefined.}{}{\@ehc}%
  \pgfpoint{0pt}{0pt}%
  \else\csname pgfnom@#1\endcsname\fi\ignorespaces}



% Returns a position relative to the center of #1.
%
% #1 = a node name
% #2 = a direction (see \pgfdirection)
% #3 = a distance
%
% Example:
%
% \pgfmoveto{\pgfnoderelative{mynode}[north]{1cm}}

\def\pgfnoderelative#1[#2]#3{%
  \pgfrelative{\pgfnodecenter{#1}}{\pgfpolar{\pgfdirection{#2}}{#3}}\ignorespaces}



% Retrieves a border point of #1 at angle #2 and distance #3 from
% border. 
%
% #1 = a node name
% #2 = an angle
% #3 = a distance from the border
%
% Example:
%
% \pgfmoveto{\pgfnodeborder{first}{30}{0pt}}
% \pgflineto{\pgfnodeborder{second}{180}{2pt}}
% \pgfstroke

\def\pgfnodeborder#1#2#3{%
  \csname pgfnob@#1\endcsname{#3}{#2}{\pgfnodecenter{#1}}\ignorespaces}



% Gives the beginning of a connection of #2 and #3, taking a
% separation distance of #1 into account.
%
% #1 = a separation distance
% #2 = a node name
% #3 = a second node name
%
% Example:
%
% \pgfmoveto{\pgfnodeconnstart{first}{second}}
% \pgflineto{\pgfnodeconnstart{second}{first}}

\def\pgfnodeconnstart[#1]#2#3{%
  \csname pgfno@#2\endcsname[#1]{\pgfnodecenter{#2}}{\pgfnodecenter{#3}}%
  \ignorespaces}



\newdimen\pgf@nodesepstart
\newdimen\pgf@nodesepend

% Sets the node separation for starts of lines.
%
% #1 = a distance
%
% Example:
%
% \pgfnodesetsepstart{2pt}

\def\pgfnodesetsepstart#1{\pgf@nodesepstart=#1\ignorespaces}

\pgfnodesetsepstart{0pt}


% Sets the node separation for end of lines.
%
% #1 = a distance
%
% Example:
%
% \pgfnodesetsepend{2pt}

\def\pgfnodesetsepend#1{\pgf@nodesepend=#1\ignorespaces}

\pgfnodesetsepend{0pt}




% Draws a line from #1 to #2.
%
% #1 = a node name
% #2 = a second node name
%
% Example:
%
% \pgfnodeconnline{first}{second}

\def\pgfnodeconnline#1#2{%
  \pgfmoveto{\pgfnodeconnstart[\pgf@nodesepstart]{#1}{#2}}%
  \pgflineto{\pgfnodeconnstart[\pgf@nodesepend]{#2}{#1}}%
  \pgfstroke%
  \ignorespaces}



% Draws a curve from #1 to #2. The starting angle at #1 is #3 and the
% length to the first support point is #5. The starting angle at #2
% is #4 and the length to the second support point is #6. 
%
% #1 = a node name
% #2 = a second node name
% #3 = angle at first node
% #4 = angle at second node
% #5 = distance to support point at first node
% #6 = distance to support point at second node
%
% Example:
%
% \pgfnodeconncurve{first}{second}{10}{-10}{1cm}{1cm}

\def\pgfnodeconncurve#1#2#3#4#5#6{%
  \pgfmoveto{\pgfnodeborder{#1}{#3}{\pgf@nodesepstart}}%
  \pgfbezier{\pgfnodeborder{#1}{#3}{#5}}{\pgfnodeborder{#2}{#4}{#6}}%
           {\pgfnodeborder{#2}{#4}{\pgf@nodesepend}}%
  \pgfstroke\ignorespaces}




% Put a label on a line from #1 to #2.
%
% #1 = a node name
% #2 = a second node name
% #3 = fraction of way from #1 to #2
% #4 = vertical offset
% #5 = label
%
% Example:
%
% \pgfnodelabel{first}{second}[.5][2pt]{\pgfbox[center,base]{owns}}

\def\pgfnodelabel#1#2[#3][#4]#5{%
  \pgfputat{\pgflabel%
    {#3}%
    {\pgfnodeconnstart[\pgf@nodesepstart]{#1}{#2}}%
    {\pgfnodeconnstart[\pgf@nodesepend]{#2}{#1}}%
    {#4}}%
  {#5}\ignorespaces}


% Put a rotated label on a line from #1 to #2.
%
% #1 = a node name
% #2 = a second node name
% #3 = fraction of way from #1 to #2
% #4 = vertical offset
% #5 = label
%
% Example:
%
% \pgfnodelabelrotated{first}{second}[.5][2pt]{\pgfbox[center,base]{owns}}

\def\pgfnodelabelrotated#1#2[#3][#4]#5{%
  \pgfputlabelrotated%
  {#3}%
  {\pgfnodeconnstart[\pgf@nodesepstart]{#1}{#2}}%
  {\pgfnodeconnstart[\pgf@nodesepend]{#2}{#1}}%
  {#4}%
  {#5}\ignorespaces}



% Internals

\def\pgf@backoffcircle#1[#2]#3#4{%
  % Calculate backoff for a circle of radius
  % #1 and offset separation #2. #3 is the center of the circle, #4
  % is the target point.
  \pgf@x=#1\relax%
  \advance\pgf@x by#2\relax%
  \edef\pgf@temp{{\pgfget x pt}}%
  \expandafter\pgfbackoff\pgf@temp{#3}{#4}\ignorespaces}

\def\pgf@anglecircle#1#2#3#4{%
  % Calculate border point. #1 is radius, #2 is additional backoff, #3
  % is an angle, #4 is the center of the circle.
  \pgfsincos{#3}%
  \pgf@xa=#1\relax%
  \advance\pgf@xa by#2\relax%
  \pgf@ya=\pgf@xa\relax%
  \pgf@mult{\pgf@xa}{\pgfget x}{\pgf@xa}%
  \pgf@mult{\pgf@ya}{\pgfget y}{\pgf@ya}%
  \pgf@process{#4}%
  \advance\pgf@y by\pgf@xa\relax%
  \advance\pgf@x by\pgf@ya\ignorespaces}

\def\pgf@backoffrect#1#2[#3]#4#5{%
  % Calculate backoff for a rect with half width #1,
  % half height #2, offset separation #3. #4 is the center of the rect, #5
  % is the target point.
  \pgfdiff{#4}{#5}%
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \pgf@xb=#1\relax%
  \pgf@yb=#2\relax%
  \advance\pgf@xb by #3\relax%
  \advance\pgf@yb by #3\relax%  
  \ifnum\pgf@xa<0\relax% move into first quadrant
    \pgf@x=-\pgf@x%
  \fi%
  \ifnum\pgf@ya<0\relax%
    \pgf@y=-\pgf@y%
  \fi%
  \pgf@counta=\pgf@x%
  \pgf@countb=\pgf@y%
  \divide\pgf@counta by 256\relax%
  \divide\pgf@countb by 256\relax%
  \ifnum\pgf@countb<\pgf@counta%
    \ifnum\pgf@counta<1\relax%
      \pgf@y=\pgf@yb\relax%
      \pgf@x=0pt\relax%
    \else%
      \pgf@y=16\pgf@y%
      \divide\pgf@y by \pgf@counta%
      \pgf@y=16\pgf@y%
      \pgf@mult{\pgf@y}{\pgfget{xb}}{\pgf@y}%
      \ifnum\pgf@y<\pgf@yb%
        \pgf@x=\pgf@xb%
      \else% rats, calculate intersection on upper side
        \ifnum\pgf@countb<1\relax%
          \pgf@x=\pgf@xb\relax%
          \pgf@y=0pt\relax%
        \else%
          \pgf@x=16\pgf@x%
          \divide\pgf@x by \pgf@countb%
          \pgf@x=16\pgf@x%
          \pgf@mult{\pgf@x}{\pgfget{yb}}{\pgf@x}%
          \pgf@y=\pgf@yb%
        \fi%
      \fi%  
    \fi%
  \else%
    \ifnum\pgf@countb<1\relax%
      \pgf@x=\pgf@xb\relax%
      \pgf@y=0pt\relax%
    \else%
      \pgf@x=16\pgf@x%
      \divide\pgf@x by \pgf@countb%
      \pgf@x=16\pgf@x%
      \pgf@mult{\pgf@x}{\pgfget{yb}}{\pgf@x}%
      \ifnum\pgf@x<\pgf@xb%
        \pgf@y=\pgf@yb%
      \else%
        \ifnum\pgf@counta<1\relax%
          \pgf@y=\pgf@yb\relax%
          \pgf@x=0pt\relax%
        \else%
          \pgf@y=16\pgf@y%
          \divide\pgf@y by \pgf@counta%
          \pgf@y=16\pgf@y%
          \pgf@mult{\pgf@y}{\pgfget{xb}}{\pgf@y}%
          \pgf@x=\pgf@xb%
        \fi%
      \fi%  
    \fi%
  \fi%  
  \ifnum\pgf@xa<0\relax\pgf@x=-\pgf@x\fi%
  \ifnum\pgf@ya<0\relax\pgf@y=-\pgf@y\fi%    
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \pgf@process{#4}%
  \advance\pgf@x by\pgf@xa%
  \advance\pgf@y by\pgf@ya\ignorespaces}

\def\pgf@anglerect#1#2#3#4#5{%
  % Calculate border point. #1/#2 is half width/height, #3 is additional backoff, #4
  % is an angle, #5 is the center of the rect.
  \pgfsincos{#4}%
  \pgf@xa=100\pgf@x%
  \pgf@ya=100\pgf@y%
  \pgf@process{#5}%
  \advance\pgf@x by\pgf@ya%
  \advance\pgf@y by\pgf@xa%
  \edef\pgf@temp{{\noexpand\pgf@x=\the\pgf@x\noexpand\pgf@y=\the\pgf@y}}%
  \expandafter\pgf@caller\pgf@temp{#1}{#2}{#3}{#5}\ignorespaces}

\def\pgf@caller#1#2#3#4#5{\pgf@backoffrect{#2}{#3}[#4]{#5}{#1}}

\endinput
