% $Id: pst-node.tex 918 2024-07-10 17:41:55Z herbert $
%%
%% BEGIN pst-node.tex
%%
%% Nodes with PSTricks.
%% This uses the header file `pst-node.pro'.
%%
%% COPYRIGHT 1993, 1994, 1999 by Timothy Van Zandt, tvz@nwu.edu.
%% COPYRIGHT 2009- by Herbert Voss, hvoss@tug.org.
%%
%% 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.
%%
%
\csname PSTnodesLoaded\endcsname
\let\PSTnodesLoaded\endinput
\ifx\PSTricksLoaded\endinput\else\input pstricks.tex \fi\relax
\ifx\PSTXKeyLoaded\endinput\else \input pst-xkey \fi
%
\def\fileversion{1.45}
\def\filedate{2024/07/10}
\message{ v\fileversion, \filedate}
%
\edef\TheAtCode{\the\catcode`\@}
\catcode`\@=11
%
\pstheader{pst-node.pro}
\pst@addfams{pst-node}
%
\SpecialCoor
%
%%%%%%%%%% compatibility stuff
\define@boolkey[psset]{pst-node}[Pst@]{trueAngle}[true]{}
\psset[pst-node]{trueAngle=false}
%%%%%%%%%% compatibility stuff
\define@boolkey[psset]{pst-node}[Pst@]{storeNodeInfo}[true]{}
\psset[pst-node]{storeNodeInfo=false}
%
\def\pst@nodedict{tx@NodeDict begin }
\def\pst@zapspace#1 #2{%
#1%
\ifx#2\@empty\else\expandafter\pst@zapspace\fi
#2}
%
\def\pst@getnode#1#2{\pst@expandafter\pst@@getnode{#1},,\@nil#2}
\def\pst@@getnode#1,#2,#3\@nil#4{%
  \ifx\@empty#3\@empty
    \edef#4{/N@\pst@zapspace#1 \@empty\space}%
  \else
    \pst@cntg=#1\relax
    \pst@cnth=#2\relax
    \edef#4{/N@M-\ifnum\psmatrixcnt=\z@ 1\else\the\psmatrixcnt\fi
    -\the\pst@cntg-\the\pst@cnth\space}%
  \fi}
%
% bug fix for xelatex, dvipdfmx uses the wrong scaling
\def\tx@NewNode{/NodeScale {\ifx\pstnodescale\@undefined  \else\pstnodescale \fi} def NewNode }
%
\def\psopenNodeFile{%
  \pst@Verb{ %globaldict begin
%  tx@NodeDict begin 
    (\jobname.nodes) (w) file /NodeFile exch def 
%    end 
  }}
 %
\def\pscloseNodeFile{\pstVerb{ tx@NodeDict begin NodeFile closefile end }}
%
\define@boolkey[psset]{pst-node}[Pst@]{showNode}[true]{\ifPst@showNode\psopenNodeFile\fi}% write coors into the logfile
\define@boolkey[psset]{pst-node}[Pst@]{markNode}[true]{}% makr the node with its name
\define@boolkey[psset]{pst-node}[Pst@]{saveNodeCoors}[true]{}
\define@key[psset]{pst-node}{NodeCoorPrefix}[]{\def\psk@NodeCoorPrefix{#1}}% if empty it is N-<Name>.x|y
\psset[pst-node]{saveNodeCoors=false,showNode=false,markNode=false,NodeCoorPrefix=}% <NodeCoorPrefix<Name>x|y>
%
\def\pst@newnode#1#2#3#4{%  name type coors initcode
\pst@killglue
\leavevmode
\pst@getnode{#1}\pst@thenode
\pst@Verb{
  \ifPst@saveNodeCoors
    \ifx\relax#3\relax 0 0 \else gsave \pst@dict STV CP T end #3 \tx@UserCoor grestore \fi 
    \if$\psk@NodeCoorPrefix$
      /N-#1.y exch def
      /N-#1.x exch def
    \else
      /\psk@NodeCoorPrefix#1y exch def
      /\psk@NodeCoorPrefix#1x exch def
    \fi
  \fi
  \pst@nodedict
  {#3}
  \ifx\psk@name\relax false \else \psk@name true \fi
  \pst@thenode
  #2
  {#4}
  \ifPst@showNode 
  exch dup /NodeType ED 
  exch
   NodeType 10 eq {  % pnode type
    5 copy 
    cvlit aload pop
    20 string cvs (; )   6 2 roll % InitPnode
    20 string cvs (; )   7 2 roll % type
    20 string cvs (; )   8 2 roll %/N@Name
    20 string cvs (; )   9 2 roll % true/false
    cvlit dup length 2 eq 
      { aload pop exch 
        20 string cvs (; ) 11 2 roll 
        20 string cvs (, ) 12 2 roll  % x,y
        (\string\n)                   % add newline
        13 array astore concatstringarray 
      }
      { 255 string cvs (; ) 10 2 roll 
        (\string\n)                   % add newline
        11 array astore concatstringarray 
      } ifelse 
    NodeFile exch writestring 
  } if
  NodeType 14 eq {  % dotnode
    5 copy 
    /@@temp ED 
%    gsave  
    @@temp  % to get X Y
    4 -1 roll cvlit pop
    ( OvalNodePos ) (; )  5 2 roll
    20 string cvs (; )   6 2 roll % type
    20 string cvs (; )   7 2 roll %/N@Name
    20 string cvs (; )   8 2 roll % true/false
    Y 20 string cvs (; ) 10 2 roll
    X 20 string cvs (, ) 12 2 roll
    (\string\n)                   % add newline
    13 array astore concatstringarray 
%    grestore
    tx@NodeDict begin NodeFile exch writestring end
  } if
  \fi
  \tx@NewNode
  end 
}%
%
\global\let\psk@name\relax%
\pstree@nodehook%
\global\let\pstree@nodehook\relax}
%
\let\pstree@nodehook\relax
\define@boolkey[psset]{pst-node}[Pst@]{nodealign}[true]{}
\psset[pst-node]{nodealign=false}

\def\pst@nodealign{%
\pst@dimg=\ht\pst@hbox
\advance\pst@dimg by -\dp\pst@hbox
\divide\pst@dimg by \tw@
\lower\pst@dimg}
%
\def\tx@InitPnode{InitPnode }
\def\pnode{\@ifnextchar[{\pnode@i}{\pnode@iii}}
\def\pnode@i[#1]{\@ifnextchar({\pnode@ii[#1]}{\pnode@ii[#1](0,0)}}
\def\pnode@ii[#1](#2)#3{%
  \pst@getcoor{#1}\pst@tempA%
  \pst@getcoor{#2}\pst@tempB%
  \pst@newnode{#3}{10}{\pst@tempA \pst@tempB 3 -1 roll add 3 1 roll add exch }{\tx@InitPnode}%
  \ifPst@showNode\psdot(#3)\uput[\ifx\psk@rot\@empty0\else\psk@rot\fi]{0}(#3){#3}\fi
  \ignorespaces}
%
\def\pnode@iii{\@ifnextchar({\pnode@}{\pnode@(0,0)}}
\def\pnode@(#1)#2{%
  \pst@@getcoor{#1}%
  \pst@newnode{#2}{10}{\pst@coor}{\tx@InitPnode}%
  \ifPst@showNode\psdot(#2)\uput[\ifx\psk@rot\@empty0\else\psk@rot\fi]{0}(#2){#2}\fi
  \ignorespaces}
%
\def\pnodes{\@ifnextchar[{\pnodes@i}{\pnodes@i[0,0]}}
\def\pnodes@i[#1]{\@ifnextchar({\psnodes@ii[#1]}{\pnodes@ii}}
\def\psnodes@ii[#1](#2)#3{%
  \pnode[#1](#2){#3}%
  \@ifnextchar({\psnodes@ii[#1]}{}%
}
%
\def\tx@InitCnode{InitCnode }
%
\def\cnode{\pst@object{cnode}}
\def\cnode@i{\@ifnextchar({\cnode@ii}{\cnode@ii(0,0)}}
\def\cnode@ii(#1)#2#3{%
  \leavevmode
  \hbox{%
    \use@par
    \pst@@getcoor{#1}%
    \pssetlength\pst@dimc{#2}%
    \pst@dimg=\psk@dimen\pslinewidth
    \advance\pst@dimc-\pst@dimg
    \advance\pst@dimc.5\pslinewidth
    \ifPst@nodealign
      \kern\pst@dimc
      \vrule width\z@ height \pst@dimc depth \pst@dimc
    \fi
    \pscircle@do(#1){#2}%
    \pst@newnode{#3}{11}{\pst@coor \pst@number\pst@dimc}{\tx@InitCnode}%
    \ifPst@nodealign\kern\pst@dimc\fi%
  }%
  \ignorespaces}
%
\def\Cnode{\pst@object{Cnode}}
\def\Cnode@i{\@ifnextchar({\Cnode@ii}{\Cnode@ii(0,0)}}
\def\Cnode@ii(#1)#2{\cnode@ii(#1){\psk@radius}{#2}}%
%
\def\cnodeput{\pst@object{cnodeput}}
\def\cnodeput@i{\@ifnextchar({\cnodeput@iii}{\cnodeput@ii}}
\def\cnodeput@ii#1{%
  \addto@par{rot={#1}}%
  \@ifnextchar({\cnodeput@iii}{\cnodeput@iii(\z@,\z@)}%
}
\def\cnodeput@iii(#1)#2{%
  \pst@killglue
  \@fixedradiusfalse
  \def\pst@nodehook{\cnodeput@iv{#2}}%
  \pst@makebox{\cput@v{#1}}%
}
\def\cnodeput@iv#1{%
  \pst@newnode{#1}{11}{\pscirclebox@iv \pst@number\pslinewidth add}{\tx@InitCnode}%
  \global\let\pst@nodehook\relax
  \ignorespaces
}
\def\Cnodeput{\pst@object{Cnodeput}}
\def\Cnodeput@i{\@ifnextchar({\Cnodeput@iii}{\Cnodeput@ii}}
\def\Cnodeput@ii#1{%
  \addto@par{rot={#1}}%
  \@ifnextchar({\Cnodeput@iii}{\Cnodeput@iii(\z@,\z@)}}
\def\Cnodeput@iii(#1)#2{%
  \pst@killglue
  \@fixedradiustrue
  \def\pst@nodehook{\Cnodeput@iv{#2}}%
  \pst@makebox{\cput@v{#1}}%
}
\def\Cnodeput@iv#1{%
  \pst@newnode{#1}{11}{%
    \pst@number{\wd\pst@hbox} 2 div \pst@number\pst@dima % x y
    \pst@number\pst@dimb \pst@number\pslinewidth \psk@dimen .5 sub mul sub }% r
       {\tx@InitCnode}%
  \global\let\pst@nodehook\relax}
%
\def\circlenode{\pst@object{circlenode}}
\def\circlenode@i#1{\pst@makebox{\circlenode@ii{#1}}}
\def\circlenode@ii#1{%
  \begingroup
  \pst@useboxpar
  \setbox\pst@hbox=\hbox{%
    \cnodeput@iv{#1}%
    \pscirclebox@iii
    \box\pst@hbox}%
  \ifPst@nodealign \psboxseptrue \fi
  \ifpsboxsep \pscirclebox@sep \fi
  \leavevmode
  \ifPst@nodealign\pst@nodealign\fi
  \box\pst@hbox
  \endgroup}
%
\def\Circlenode{\pst@object{Circlenode}}
\def\Circlenode@i#1{\pst@makebox{\Circlenode@ii{#1}}}
\def\Circlenode@ii#1{%
\begingroup
  \pst@useboxpar
  \pst@dima=\ht\pst@hbox
  \advance\pst@dima by -\dp\pst@hbox
  \divide\pst@dima by \tw@
  \pssetlength\pst@dimb\psk@radius
  \setbox\pst@hbox=\hbox{%
  \Cnodeput@iv{#1}%
  \pscircle(.5\wd\pst@hbox,\pst@dima){\pst@dimb}%
  \box\pst@hbox}%
  \ifPst@nodealign \psboxseptrue \fi
  \ifpsboxsep \psCirclebox@sep \fi
  \leavevmode
  \ifPst@nodealign\pst@nodealign\fi
  \box\pst@hbox
  \endgroup}
\def\tx@GetRnodePos{GetRnodePos }
\def\tx@InitRnode{InitRnode }
%
\def\psnode{\pst@object{psnode}}
\def\psnode@i{\@ifnextchar(\psnode@ii{\psnode@ii(0,0)}}
\def\psnode@ii(#1)#2#3{%    #1: coordinates, #2: node name,  #3 contents
  \rput(#1){\rnode{#2}{#3}}}
%
\def\rnode{\@ifnextchar[{\rnode@i}{\def\pst@par{}\rnode@ii}}
\def\rnode@i[#1]{\def\pst@par{ref=#1}\rnode@ii}
\def\rnode@ii#1{\pst@makebox{\rnode@iii\rnode@iv{#1}}}
\def\rnode@iii#1#2{%
% DG modification begin - Jan. 1997
\leavevmode
% DG modification end
\begingroup
% DG/SR modification begin - Apr. 28, 1998 - Patch 6
\pst@useboxpar
% DG/SR modification end
#1%
%\if@star\pst@starbox\fi%  commented to fix bug witzh \psframebox*{\rnode...}
\ifPst@nodealign\lower\pst@dimb\fi
\hbox{%
\pst@newnode{#2}{16}{%
\pst@number{\ht\pst@hbox}%
\pst@number{\dp\pst@hbox}%
\pst@number{\wd\pst@hbox}%
\pst@number\pst@dima%
\pst@number\pst@dimb}%
{\tx@InitRnode}%
\box\pst@hbox}%
\endgroup}
\def\rnode@iv{%
\pst@dima=\psk@xref\wd\pst@hbox
\ifx\psk@yref\relax
\pst@dimb=\z@
\else
\pst@dimb=\ht\pst@hbox
\advance\pst@dimb\dp\pst@hbox
\pst@dimb=\psk@yref\pst@dimb
\advance\pst@dimb-\dp\pst@hbox
\fi}
%
\define@key[psset]{pst-node}{href}[0]{\pst@checknum{#1}\psk@href}
\psset[pst-node]{href=0}
\define@key[psset]{pst-node}{vref}[0.7ex]{\def\psk@vref{#1}}
\psset[pst-node]{vref=0.7ex}
\def\Rnode{\pst@object{Rnode}}
\def\Rnode@i#1{\pst@makebox{\rnode@iii\Rnode@ii{#1}}}
\def\Rnode@ii{%
% DG modification begin - Jan. 1997
%   - \begingroup removed  as it seems to doesn't work any more
%   - \Rnode doesn't process the optional parameter changes
%\begingroup
\use@par
% DG modification end
\pst@dima=\psk@href\wd\pst@hbox
\advance\pst@dima\wd\pst@hbox
\divide\pst@dima 2
\pssetlength\pst@dimb{\psk@vref}}
\def\tx@DiaNodePos{DiaNodePos }
\def\dianode{\pst@object{dianode}}
\def\dianode@i#1{\pst@makebox{\dianode@ii{#1}}}
\def\dianode@ii#1{%
\begingroup
\pst@useboxpar
\psdiabox@iii
\setbox\pst@hbox=\hbox{%
\pst@newnode{#1}{14}{}{%
/X \pst@number\pst@dima def
/Y \pst@number\pst@dimb def
/w \pst@number\pst@dimc 2 mul def
/h \pst@number\pst@dimd 2 mul def
/NodePos { \tx@DiaNodePos } def}%
\box\pst@hbox}%
\ifPst@nodealign\psboxseptrue\fi
\ifpsboxsep\psdiabox@sep\fi
% DG/SR modification begin - Sep. 2, 1997 - Patch 3
\leavevmode
% DG/SR modification end
\ifPst@nodealign\lower\pst@dimb\fi
\box\pst@hbox
\endgroup}
%
\def\tx@TriNodePos{TriNodePos }
\def\tx@InitTriNode{InitTriNode }
%
\def\trinode{\pst@object{trinode}}
\def\trinode@i#1{\pst@makebox{\trinode@ii{#1}}}
\def\trinode@ii#1{%
  \begingroup%
  \pst@useboxpar%
  \pstribox@iii
  \setbox\pst@hbox=\hbox{%
    \pst@newnode{#1}{14}{}{
      \pst@number\pst@dimc
      \pst@number\pst@dimd
      \ifodd\psk@trimode
        exch
        \pst@number\pst@dima
      \else
        \pst@number\pst@dimb
      \fi
      \psk@trimode
      \pst@number{\wd\pst@hbox}
      \pst@number{\ht\pst@hbox}
      \pst@number{\dp\pst@hbox}
      \tx@InitTriNode
    }%
    \box\pst@hbox%
  }%
  \ifPst@nodealign\psboxseptrue\fi
  \ifpsboxsep\pstribox@sep\fi
% DG/SR modification begin - Sep. 2, 1997 - Patch 3
  \leavevmode
% DG/SR modification end
  \ifPst@nodealign\lower\pst@tempa\fi
  \box\pst@hbox%
  \endgroup}
%
\def\tx@OvalNodePos{OvalNodePos }
\def\ovalnode{\pst@object{ovalnode}}
\def\ovalnode@i#1{\pst@makebox{\ovalnode@ii{#1}}}
\def\ovalnode@ii#1{%
\begingroup
\pst@useboxpar
\psovalbox@iii
\setbox\pst@hbox=\hbox{%
\pst@newnode{#1}{14}{}{%
/X \pst@number\pst@dima def
/Y \pst@number\pst@dimb def
/w \pst@number\pst@dimc def
/h \pst@number\pst@dimd def
/NodePos { \tx@OvalNodePos } def}%
\unhbox\pst@hbox}%
\ifPst@nodealign\psboxseptrue\fi
\ifpsboxsep\psovalbox@sep\fi
% DG/SR modification begin - Sep. 2, 1997 - Patch 3
\leavevmode
% DG/SR modification end
\ifPst@nodealign\lower\pst@dimb\fi
\box\pst@hbox
\endgroup}
%
\def\dotnode{\pst@object{dotnode}}
\def\dotnode@i{\@ifnextchar({\dotnode@ii}{\dotnode@ii(\z@,\z@)}}
\def\dotnode@ii(#1)#2{%
  \leavevmode
  \hbox{%
    \use@par
    \pst@@getcoor{#1}%
    \pst@getdotsize
    \pstree@nodehook
    \ifPst@nodealign
      \pst@dima=\pst@dimg
      \kern\pst@dima
      \vrule width\z@ height \pst@dimh depth \pst@dimh
    \fi
    \pst@newnode{#2}{14}{}{
      \pst@coor
      /Y exch def /X exch def
      /w \pst@number\pst@dimg def
      /h \pst@number\pst@dimh def
      /NodePos { \tx@OvalNodePos } def}%
    \psdot@ii(#1)%
    \ifPst@nodealign\kern\pst@dima\fi}%
  \ifPst@markNode\uput[\ifx\psk@rot\@empty0\else\psk@rot\fi]{0}(#2){#2}\fi
  \ignorespaces}
%
\def\dotnodes{\pst@object{dotnodes}}
\def\dotnodes@i{\use@par\dotnodes@ii}
\def\dotnodes@ii(#1)#2{%
  \dotnode(#1){#2}%
  \@ifnextchar(\dotnodes@ii{\def\pst@par{}}}
%
\define@key[psset]{pst-node}{framesize}{\pst@expandafter\psset@@framesize{#1} \@nil}
\def\psset@@framesize#1 #2\@nil{%
  \pssetlength\pst@dimg{#1}%
  \divide\pst@dimg2
  \edef\psk@framewidth{\pst@number\pst@dimg}%
  \ifx\@empty#2\@empty
    \let\psk@frameheight\psk@framewidth
  \else
    \pssetlength\pst@dimg{#2}%
    \divide\pst@dimg2
    \edef\psk@frameheight{\pst@number\pst@dimg}%
  \fi}
%
\psset[pst-node]{framesize=10pt}
%
\def\fnode{\pst@object{fnode}}
\def\fnode@i{\@ifnextchar({\fnode@ii}{\fnode@ii(\z@,\z@)}}
\def\fnode@ii(#1)#2{%
  \leavevmode
  \pst@killglue
  \hbox{%
    \use@par%
    \begin@ClosedObj%
    \ifPst@nodealign
      \kern\psk@framewidth\p@
      \vrule width\z@ height \psk@frameheight\p@ depth \psk@frameheight\p@
      \edef\pst@coor{0 0 }%
    \else\pst@@getcoor{#1}\fi
    \pst@newnode{#2}{14}{}{
      \pst@coor
      /Y exch def /X exch def
      /d \psk@dimen .5 sub CLW mul neg def
      /r \psk@framewidth d add def
      /l r neg def
      /u \psk@frameheight d add def
      /d u neg def
      /NodePos { \tx@GetRnodePos } def}%
    \addto@pscode{
      /x2 \psk@framewidth CLW \psk@dimen mul sub def
      /y2 \psk@frameheight CLW \psk@dimen mul sub def
      \pst@coor 2 copy
      y2 sub /y1 ED
      x2 sub /x1 exch def
      y2 add /y2 exch def
      x2 add /x2 exch def
      \psk@cornersize
      1 index 0 eq { pop pop \tx@Rect } { \tx@OvalFrame } ifelse}%
    \def\pst@linetype{2}%
    \showpointsfalse%
    \end@ClosedObj%
    \ifPst@nodealign\kern\psk@framewidth\p@\fi}% end of \hbox
  \ignorespaces}
%
%
% This fixes a bug in pst-node, where the XY-direction is wrong
% the types are changed 1<->2 between X<->Y
%
\define@key[psset]{}{XnodesepA}{\pst@getlength{#1}\psk@nodesepA\def\psk@nodeseptypeA{2 }}
\define@key[psset]{}{XnodesepB}{\pst@getlength{#1}\psk@nodesepB\def\psk@nodeseptypeB{2 }}
\define@key[psset]{}{Xnodesep}{%
    \pst@getlength{#1}\psk@nodesepA
    \let\psk@nodesepB\psk@nodesepA
    \def\psk@nodeseptypeA{2 }%
    \def\psk@nodeseptypeB{2 }}
\define@key[psset]{}{YnodesepA}{\pst@getlength{#1}\psk@nodesepA\def\psk@nodeseptypeA{1 }}
\define@key[psset]{}{YnodesepB}{\pst@getlength{#1}\psk@nodesepB\def\psk@nodeseptypeB{1 }}
\define@key[psset]{}{Ynodesep}{%
    \pst@getlength{#1}\psk@nodesepA
    \let\psk@nodesepB\psk@nodesepA
    \def\psk@nodeseptypeA{1 }%
    \def\psk@nodeseptypeB{1 }}
%%%% end bugfix %%%%%
\define@key[psset]{pst-node}{nodesepA}[0pt]{\pst@getlength{#1}\psk@nodesepA \def\psk@nodeseptypeA{0 }}
\define@key[psset]{pst-node}{nodesepB}[0pt]{\pst@getlength{#1}\psk@nodesepB \def\psk@nodeseptypeB{0 }}
\define@key[psset]{pst-node}{nodesep}[0pt]{%
  \pst@getlength{#1}\psk@nodesepA
  \let\psk@nodesepB\psk@nodesepA
  \def\psk@nodeseptypeA{0 }%
  \def\psk@nodeseptypeB{0 }}
\psset[pst-node]{nodesep=0pt}
%\define@key[psset]{pst-node}{XnodesepA}[]{\pst@getlength{#1}\psk@nodesepA \def\psk@nodeseptypeA{1 }}
%\define@key[psset]{pst-node}{XnodesepB}[]{\pst@getlength{#1}\psk@nodesepB \def\psk@nodeseptypeB{1 }}
%\define@key[psset]{pst-node}{Xnodesep}[]{%
%  \pst@getlength{#1}\psk@nodesepA
%  \let\psk@nodesepB\psk@nodesepA
%  \def\psk@nodeseptypeA{1 }%
%  \def\psk@nodeseptypeB{1 }}
%\define@key[psset]{pst-node}{YnodesepA}[]{\pst@getlength{#1}\psk@nodesepA \def\psk@nodeseptypeA{2 }}
%\define@key[psset]{pst-node}{YnodesepB}[]{\pst@getlength{#1}\psk@nodesepB \def\psk@nodeseptypeB{2 }}
%\define@key[psset]{pst-node}{Ynodesep}[]{
%  \pst@getlength{#1}\psk@nodesepA
%  \let\psk@nodesepB\psk@nodesepA
%  \def\psk@nodeseptypeA{2 }%
%  \def\psk@nodeseptypeB{2 }}
\define@key[psset]{pst-node}{armA}[10pt]{\pst@getlength{#1}\psk@armA \def\psk@armtypeA{0 }}
\define@key[psset]{pst-node}{armB}[10pt]{\pst@getlength{#1}\psk@armB \def\psk@armtypeB{0 }}
\define@key[psset]{pst-node}{arm}[10pt]{%
  \pst@getlength{#1}\psk@armA
  \let\psk@armB\psk@armA
  \def\psk@armtypeA{0 }%
  \def\psk@armtypeB{0 }}
\psset[pst-node]{arm=10pt}
\define@key[psset]{pst-node}{XarmA}[]{\pst@getlength{#1}\psk@armA \def\psk@armtypeA{1 }}
\define@key[psset]{pst-node}{XarmB}[]{\pst@getlength{#1}\psk@armB \def\psk@armtypeB{1 }}
\define@key[psset]{pst-node}{Xarm}{%
  \pst@getlength{#1}\psk@armA
  \let\psk@armB\psk@armA
  \def\psk@armtypeA{1 }%
  \def\psk@armtypeB{1 }}
\define@key[psset]{pst-node}{YarmA}[]{\pst@getlength{#1}\psk@armA \def\psk@armtypeA{2 }}
\define@key[psset]{pst-node}{YarmB}[]{\pst@getlength{#1}\psk@armB \def\psk@armtypeB{2 }}
\define@key[psset]{pst-node}{Yarm}[]{%
  \pst@getlength{#1}\psk@armA
  \let\psk@armB\psk@armA
  \def\psk@armtypeA{2 }%
  \def\psk@armtypeB{2 }}
\define@key[psset]{pst-node}{offsetA}[0pt]{\pst@getlength{#1}\psk@offsetA}
\define@key[psset]{pst-node}{offsetB}[0pt]{\pst@getlength{#1}\psk@offsetB}
\define@key[psset]{pst-node}{offset}[0pt]{\pst@getlength{#1}\psk@offsetA\let\psk@offsetB\psk@offsetA}
\psset[pst-node]{offset=0pt}
\define@key[psset]{pst-node}{angleA}[0]{\pst@getangle{#1}\psk@angleA}
\define@key[psset]{pst-node}{angleB}[0]{\pst@getangle{#1}\psk@angleB}%
\define@key[psset]{pst-node}{angle}[0]{%
  \pst@getangle{#1}\psk@angleA
  \let\psk@angleB\psk@angleA}
\psset[pst-node]{angle=0}
\define@key[psset]{pst-node}{arcangleA}[8]{\pst@getangle{#1}\psk@arcangleA}
\define@key[psset]{pst-node}{arcangleB}[8]{\pst@getangle{#1}\psk@arcangleB}%
\define@key[psset]{pst-node}{arcangle}[8]{%
  \pst@getangle{#1}\psk@arcangleA
  \let\psk@arcangleB\psk@arcangleA}
\psset[pst-node]{arcangle=8}
\define@key[psset]{pst-node}{ncurvA}[0.67]{\pst@checknum{#1}\psk@ncurvA}
\define@key[psset]{pst-node}{ncurvB}[0.67]{\pst@checknum{#1}\psk@ncurvB}%
\define@key[psset]{pst-node}{ncurv}[0.67]{\pst@checknum{#1}\psk@ncurvA\let\psk@ncurvB\psk@ncurvA}
\psset[pst-node]{ncurv=0.67}
%
\def\tx@GetCenter{GetCenter }
\def\tx@XYPos{XYPos }
\def\tx@GetEdge{GetEdge }
\def\tx@AddOffset{AddOffset }
\def\tx@GetEdgeA{GetEdgeA }
\def\tx@GetEdgeB{GetEdgeB }
\def\tx@GetArmA{GetArmA }
\def\tx@GetArmB{GetArmB }
%
\def\check@arrow#1#2{%
  \check@@arrow#2-\@nil
  \if@pst\addto@par{arrows=#2}\def\next{#1}%
  \else\def\next{#1{#2}}\fi
  \next}
\def\check@@arrow#1-#2\@nil{%
\ifx\@nil#2\@nil\@pstfalse\else\@psttrue\fi}
%
\def\tx@InitNC{InitNC }
\def\nc@object#1#2#3#4#5{%
  \csname begin@#1Obj\endcsname
  \showpointsfalse
  \pst@getnode{#2}\pst@tempa
  \pst@getnode{#3}\pst@tempb
  \gdef\npos@default{#4 }%
  \addto@pscode{%
    /NCLW CLW def
    \pst@nodedict
    \psk@offsetA
    \psk@offsetB neg
    \psk@nodesepA
    \psk@nodesepB
    \psk@nodeseptypeA
    \psk@nodeseptypeB
    \pst@tempa
    \pst@tempb
    \tx@InitNC { #5 } if
    end }%
  \def\use@pscode{%
    \pst@Verb{gsave \tx@STV newpath \pst@code\space grestore}%
    \gdef\pst@code{}}%
  \csname end@#1Obj\endcsname
  \pst@shortput}
%
\def\npos@default{.5 }
%
\def\pc@object#1{%
  \@ifnextchar({\pc@@object#1}{\pst@getarrows{\pc@@object#1}}}
\def\pc@@object#1(#2)(#3){%
  \pnode(#2){@@A}\pnode(#3){@@B}%
  #1{@@A}{@@B}}
%
\def\tx@LPutLine{LPutLine }
\def\tx@LPutLines{LPutLines }
\def\tx@BezierMidpoint{BezierMidpoint }
\def\tx@HPosBegin{HPosBegin }
\def\tx@HPosEnd{HPosEnd }
\def\tx@HPutLine{HPutLine }
\def\tx@HPutLines{HPutLines }
\def\tx@VPosBegin{VPosBegin }
\def\tx@VPosEnd{VPosEnd }
\def\tx@VPutLine{VPutLine }
\def\tx@VPutLines{VPutLines }
\def\tx@HPutCurve{HPutCurve }
\def\tx@NCCoor{NCCoor }
\def\tx@NCLine{NCLine }
%
\def\ncline{\pst@object{ncline}}
\def\ncline@i{\check@arrow{\ncline@ii}}
\def\ncline@ii#1#2{\nc@object{Open}{#1}{#2}{.5}{\tx@NCLine}}
%
\def\pcline{\pst@object{pcline}}
\def\pcline@i{\pc@object\ncline@ii}
%
\def\ncLine{\pst@object{ncLine}}
\def\ncLine@i{\check@arrow{\ncLine@ii}}
\def\ncLine@ii#1#2{\nc@object{Open}{#1}{#2}{.5}%
% DG/SR modification begin - Apr. 14, 1999 - Patch 9
%{\tx@NCLine /LPutPos { xB xA yB yA \tx@LPutLine } def}}
{\tx@NCLine /LPutPos { xB yB xA yA \tx@LPutLine } def}}
% DG/SR modification end
%
\def\tx@NCLines{NCLines }
\def\nclines{\pst@object{nclines}}
\def\nclines@i{\check@arrow\nclines@ii}
\def\nclines@ii#1#2{%
\begingroup
\use@par
\def\pst@aftercoors{\nclines@iii{#1}{#2}}%
\def\pst@coors{}%
\pst@@getcoors}
\def\nclines@iii#1#2{%
\nc@object{Open}{#1}{#2}{.5}{%
tx@Dict begin \psline@iii pop end
mark \pst@coors \tx@NCLines}%
\endgroup
\ignorespaces}
\def\tx@NCCurve{NCCurve }
\def\nccurve{\pst@object{nccurve}}
\def\nccurve@i{\check@arrow{\nccurve@ii}}
\def\nccurve@ii#1#2{\nc@object{Open}{#1}{#2}{.5}{%
  /AngleA \psk@angleA\space def /AngleB \psk@angleB\space def
  \psk@ncurvB\space \psk@ncurvA\space
  \tx@NCCurve}}
\def\pccurve{\pst@object{pccurve}}
\def\pccurve@i{\pc@object\nccurve@ii}
%
\def\ncarc{\pst@object{ncarc}}
\def\ncarc@i{\check@arrow{\ncarc@ii}}
\def\ncarc@ii#1#2{\nc@object{Open}{#1}{#2}{.5}{%
  yB yA sub xB xA sub \tx@Atan dup
  \psk@arcangleA\space add /AngleA exch def
  \psk@arcangleB\space sub 180 add /AngleB exch def
  \psk@ncurvB\space \psk@ncurvA\space
  \tx@NCCurve}}
\def\pcarc{\pst@object{pcarc}}
\def\pcarc@i{\pc@object\ncarc@ii}
%
\def\tx@NCAngles{NCAngles }
%
%border or center as reference point (hv)
\define@boolkey[psset]{pst-node}[Pst@]{pcRef}[true]{}
\psset[pst-node]{pcRef=false}
%
\def\ncangles{\pst@object{ncangles}}
\def\ncangles@i{\check@arrow{\ncangles@ii}}
\def\ncangles@ii#1#2{%
  \nc@object{Open}{#1}{#2}{1.5}{\ncangles@iii \tx@NCAngles}}
\def\ncangles@iii{
  tx@Dict begin \psline@iii pop end
  /AngleA \psk@angleA def
  /AngleB \psk@angleB def
  /ArmA \psk@armA \ifPst@pcRef 
    GetEdgeA yA yA1 sub dup mul xA xA1 sub dup mul add sqrt sub \fi def
  /ArmB \psk@armB def
  /ArmTypeA \psk@armtypeA def
  /ArmTypeB \psk@armtypeB def }
%
\def\pcangles{\pst@object{pcangles}}
\def\pcangles@i{\pc@object\ncangles@ii}
\def\tx@NCAngle{NCAngle }
\def\ncangle{\pst@object{ncangle}}
\def\ncangle@i{\check@arrow{\ncangle@ii}}
\def\ncangle@ii#1#2{%
\nc@object{Open}{#1}{#2}{1.5}{\ncangles@iii \tx@NCAngle}}
\def\pcangle{\pst@object{pcangle}}
\def\pcangle@i{\pc@object\ncangle@ii}
\def\tx@NCBar{NCBar }
\def\ncbar{\pst@object{ncbar}}
\def\ncbar@i{\check@arrow{\ncbar@ii}}
\def\ncbar@ii#1#2{\nc@object{Open}{#1}{#2}{1.5}{%
\ncangles@iii /AngleB \psk@angleA def \tx@NCBar}}
\def\pcbar{\pst@object{pcbar}}
\def\pcbar@i{\pc@object\ncbar@ii}
%
\define@key[psset]{pst-node}{lineAngle}[0]{%
  \ifdim#1pt=\z@\else\psset{armB=0.5}\fi
  \def\psk@lineAngle{#1}}%
\psset[pst-node]{lineAngle=0}%
%
\def\tx@NCDiag{NCDiag }
\def\ncdiag{\pst@object{ncdiag}}
\def\ncdiag@i{\check@arrow{\ncdiag@ii}}
\def\ncdiag@ii#1#2{%
  \nc@object{Open}{#1}{#2}{1.5}{\ncangles@iii \psk@lineAngle\space \tx@NCDiag}}
%
\def\pcdiag{\pst@object{pcdiag}}
\def\pcdiag@i{\pc@object\ncdiag@ii}
%
\def\tx@NCDiagg{NCDiagg }
\def\ncdiagg{\pst@object{ncdiagg}}
\def\ncdiagg@i{\check@arrow{\ncdiagg@ii}}
\def\ncdiagg@ii#1#2{%
  \nc@object{Open}{#1}{#2}{.5}{\ncangles@iii \psk@lineAngle\space \tx@NCDiagg}}
\def\pcdiagg{\pst@object{pcdiagg}}
%
\def\pcdiagg@i{\pc@object\ncdiagg@ii}
\def\tx@NCLoop{NCLoop }
\define@key[psset]{pst-node}{loopsize}{\pst@getlength{#1}\psk@loopsize}
\psset[pst-node]{loopsize=1cm}
\def\ncloop{\pst@object{ncloop}}
\def\ncloop@i{\check@arrow{\ncloop@ii}}
\def\ncloop@ii#1#2{%
\nc@object{Open}{#1}{#2}{2.5}%
{\ncangles@iii /loopsize \psk@loopsize def \tx@NCLoop}}
\def\pcloop{\pst@object{pcloop}}
\def\pcloop@i{\pc@object\ncloop@ii}
\def\tx@NCCircle{NCCircle }
\def\nccircle{\pst@object{nccircle}}
\def\nccircle@i{\check@arrow{\nccircle@ii}}
\def\nccircle@ii#1#2{%
\pssetlength\pst@dima{#2}%
\nc@object{Open}{#1}{#1}{.5}{%
/AngleA \psk@angleA def
/r \pst@number\pst@dima def
\tx@NCCircle \psarc@v end}}
\def\tx@NCBox{NCBox }
\def\ncbox{\pst@object{ncbox}}
\def\ncbox@i{\check@arrow{\ncbox@ii}}
\def\ncbox@ii#1#2{%
\def\pst@linetype{2}%
\nc@object{Closed}{#1}{#2}{.5}{%
tx@Dict begin \psline@iii pop end
\psk@boxheight \psk@boxdepth
\tx@NCBox}}
\def\pcbox{\pst@object{pcbox}}
\def\pcbox@i{\pc@object\ncbox@ii}
\def\tx@NCArcBox{NCArcBox }
\define@key[psset]{pst-node}{boxheight}[0.4cm]{\pst@getlength{#1}\psk@boxheight}
\define@key[psset]{pst-node}{boxdepth}[0.4cm]{\pst@getlength{#1}\psk@boxdepth}
\define@key[psset]{pst-node}{boxsize}[0.4cm]{%
  \pst@getlength{#1}\psk@boxheight%  
  \let\psk@boxdepth\psk@boxheight}
\psset[pst-node]{boxsize=0.4cm}
%
\def\ncarcbox{\pst@object{ncarcbox}}
\def\ncarcbox@i{\check@arrow{\ncarcbox@ii}}
\def\ncarcbox@ii#1#2{%
\def\pst@linetype{1}%
\nc@object{Closed}{#1}{#2}{.5}{%
\psk@arcangleA \psk@boxheight \psk@boxdepth \pst@number\pslinearc
\tx@NCArcBox}}
\def\pcarcbox{\pst@object{pcarcbox}}
\def\pcarcbox@i{\pc@object\ncarcbox@ii}
\def\tx@Tfan{Tfan }
% Changed according pst-beta.bug December 3, 1993
% nrot=:<angle> does not work when : is active.
\begingroup
\catcode`\:=13
\gdef\pst@activerot{\def:{\string:}}
\endgroup
\define@key[psset]{pst-node}{nrot}[0]{%
  \begingroup
  \pst@activerot
  \pst@expandafter{\@ifnextchar:{\psset@@nrot}{\psset@@rot}}{#1}\@nil
  \global\let\pst@tempg\psk@rot
  \endgroup
  \let\psk@nrot\pst@tempg}
%  
\def\psset@@nrot:#1\@nil{%
  \psset@@rot#1\@nil
  \edef\psk@rot{NAngle \ifx\psk@rot\@empty\else\psk@rot add \fi}}
\psset[pst-node]{nrot=0}
%
\def\tx@LPutCoor{LPutCoor }
\def\tx@LPut{LPut }
\define@key[psset]{pst-node}{npos}[{}]{%
  \def\pst@tempa{#1}%
  \ifx\pst@tempa\@empty\def\psk@npos{\npos@default}\else\pst@checknum{#1}\psk@npos\fi}
\psset[pst-node]{npos=}
%
\def\ncput{\pst@object{ncput}}
\def\ncput@i{\pst@killglue\pst@makebox{\ncput@ii}}
\def\ncput@ii{%
  \begingroup
  \use@par
  \if@star\pst@starbox\fi%
  \pst@makesmall\pst@hbox%
  \expandafter\ifx\expandafter\relax\psk@nrot\relax\else% prevent empty value for \psk@rot
    \ifPSTlualatex
      \pst@rotate{\psk@nrot\space neg }\pst@hbox
    \else
      \pst@rotate{\psk@nrot}\pst@hbox
    \fi
  \fi
  \ncput@iii%
  \endgroup%
  \pst@shortput}
\def\ncput@iii{%
  \leavevmode%
  \hbox{%
    \pst@Verb{
      \pst@nodedict
      /t \psk@npos def
      \tx@LPut
      end
      \tx@PutBegin}%
    \box\pst@hbox%
    \pst@Verb{\tx@PutEnd}}}
%
\def\naput{\pst@object{naput}}
\def\naput@i{\pst@killglue\pst@makebox{\naput@ii{NAngle 90 add}}}
\def\naput@ii#1{%
  \begingroup
%  \addto@par{labelsep=15pt}%
  \use@par
  \if@star\pst@starbox\fi
  \def\psk@refangle{#1 }%
  \let\psk@rot\psk@nrot
  \pst@Verb{ 
    gsave  STV CP T /ps@refangle {#1 } def 
    /ps@rot { \psk@rot } def grestore }%ADDED (MJS)
  \uput@vii
  {exch pop add a \tx@PtoC h1 add exch w1 add exch }%
  {tx@Dict /NCLW known { NCLW add } if }%
  \ncput@iii
  \endgroup
  \pst@shortput}
%
\def\nbput{\pst@object{nbput}}
\def\nbput@i{\pst@killglue\pst@makebox{\naput@ii{NAngle 90 sub}}}
\define@key[psset]{pst-node}{tpos}[0.5]{%
  \pst@checknum{#1}\psk@tpos
  \ifdim\psk@tpos \p@<\z@
    \def\psk@tpos{.5}%
% DG/SR modification begin - Sep. 23, 1998 - Patch 7
%\@pstrickserr{Bad `tpos' value: `#1'. Must be 0<tpos<1}\@epha
    \@pstrickserr{Bad `tpos' value: `#1'. Must be 0<tpos<1}\@ehpa
% DG/SR modification end
  \else
    \ifdim\psk@tpos \p@>\p@
      \def\psk@tpos{.5}%
% DG/SR modification begin - Sep. 23, 1998 - Patch 7
%\@pstrickserr{Bad `tpos' value: `#1'. Must be 0<tpos<1}\@epha
      \@pstrickserr{Bad `tpos' value: `#1'. Must be 0<tpos<1}\@ehpa%
% DG/SR modification end
    \fi%
  \fi}
\psset[pst-node]{tpos=0.5}
%
\def\nlput{\pst@object{nlput}}
\def\nlput@i(#1)(#2)#3#4{%
  \begin@SpecialObj
  \psLDNode(#1)(#2){#3}{temp@lnput}
  \pcline[linestyle=none](#1)(temp@lnput)%
  \ncput[npos=1]{#4}%
  \end@SpecialObj}
%
\def\tvput{\pst@object{tvput}}
\def\tvput@i{\pst@makebox{\psput@tput{H}{1}}}
\def\tlput{\pst@object{tlput}}
\def\tlput@i{\pst@makebox{\psput@tput{H}{true}}}
\def\trput{\pst@object{trput}}
\def\trput@i{\pst@makebox{\psput@tput{H}{false}}}
\def\thput{\pst@object{thput}}
\def\thput@i{\pst@makebox{\psput@tput{V}{1}}}
\def\taput{\pst@object{taput}}
\def\taput@i{\pst@makebox{\psput@tput{V}{true}}}
\def\tbput{\pst@object{tbput}}
\def\tbput@i{\pst@makebox{\psput@tput{V}{false}}}
\def\tx@HPutAdjust{HPutAdjust }
\def\tx@VPutAdjust{VPutAdjust }
\def\psput@tput#1#2{%
  \begingroup
  \use@par
  \pst@tputmakesmall
  \leavevmode
  \hbox{%
    \pst@Verb{%
      \pst@nodedict
      /t \psk@tpos \pst@tposflip def
      tx@NodeDict /HPutPos known
        { #1PutPos }
        { CP /Y exch def /X exch def /NAngle 0 def /NCLW 0 def }
      ifelse
      /Sin NAngle sin def
      /Cos NAngle cos def
      /s \pst@number\pslabelsep NCLW add def
      /l \pst@number\pst@dima def
      /r \pst@number\pst@dimb def
      /h \pst@number\pst@dimc def
      /d \pst@number\pst@dimd def
% DG/SR modification begin - Sep. 26, 1997 - Patch 4
%\ifnum1=0#2\else
      \ifnum1=0#2 \else
% DG/SR modification end
        /flag #2 def
        \csname tx@#1PutAdjust\endcsname
      \fi
      \tx@LPutCoor
      end
      \tx@PutBegin}%
    \box\pst@hbox
    \pst@Verb{\tx@PutEnd}}%
  \endgroup
  \pst@shortput}
%  
\def\pst@tposflip{}
\def\pst@tputmakesmall{%
%
\pst@dima=\wd\pst@hbox
\divide\pst@dima 2
\pst@dimg=\psk@href\pst@dimg
\pst@dimb\pst@dima
\advance\pst@dima\pst@dimg % leftsize
\advance\pst@dimb-\pst@dimg % rightsize
\pst@dimd=\psk@vref\relax
\pst@dimc=\ht\pst@hbox
\advance\pst@dimc-\pst@dimd % height
\advance\pst@dimd\dp\pst@hbox % depth
\setbox\pst@hbox=\hbox to\z@{%
\kern-\pst@dima\vbox to\z@{\vss\box\pst@hbox\vskip-\pst@dimd}\hss}}
\def\MakeShortNab#1#2{%
  \def\pst@shortput@nab{%
    \def\pst@tempg{\next}%
    \ifx#1\next
      \let\pst@tempg\naput
    \else
      \ifx#2\next
        \let\pst@tempg\nbput
      \else
        \ifx\@sptoken\next
          \let\pst@tempg\pst@shortput
        \fi
      \fi
    \fi
    \pst@tempg}}
\MakeShortNab{^}{_}
\def\MakeShortTablr#1#2#3#4{%
  \def\pst@shortput@tablr{%
    \def\pst@tempg{\next}%
    \ifx#1\next
      \let\pst@tempg\taput
    \else
      \ifx#2\next
        \let\pst@tempg\tbput
      \else
        \ifx#3\next
          \let\pst@tempg\tlput
        \else
          \ifx#4\next
            \let\pst@tempg\trput
          \else
            \ifx\@sptoken\next
              \let\pst@tempg\pst@shortput
            \fi
          \fi
        \fi
      \fi
    \fi
    \pst@tempg}}
\MakeShortTablr{^}{_}{<}{>}
\def\MakeShortTab#1#2{%
  \def\pst@shortput@tab{%
    \def\pst@tempg{\next}%
    \ifx#1\next
      \def\pst@tempg{%
        \@nameuse{%
          t\ifodd\psk@treemode\ifpstreeflip b\else a\fi
          \else\ifpstreeflip r\else l\fi\fi put}}%
    \else
      \ifx#2\next
        \def\pst@tempg{%
          \@nameuse{%
            t\ifodd\psk@treemode\ifpstreeflip a\else b\fi
            \else\ifpstreeflip l\else r\fi\fi put}}%
      \else
        \ifx\@sptoken\next
          \let\pst@tempg\pst@shortput
        \fi
      \fi
    \fi
    \pst@tempg}}
\MakeShortTab{^}{_}
\define@key[psset]{pst-node}{shortput}[none]{%
  \def\pst@tempg{#1}%
  \ifx\pst@tempg\@none
    \let\pst@shortput\ignorespaces
  \else
    \@ifundefined{pst@shortput@#1}%
     {\@pstrickserr{Bad short put: `#1'}\@ehpa}%
     {\edef\pst@shortput{\noexpand\afterassignment\expandafter\noexpand
      \csname pst@shortput@#1\endcsname\noexpand\let\noexpand\next}}%
  \fi}
\psset[pst-node]{shortput=none}
%
\def\lput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\lput@i}{\lput@ii}}}
\def\lput@i[#1]{\addto@par{ref=#1}\lput@ii}
\def\lput@ii{\@ifnextchar({\lput@iv}{\lput@iii}}
\def\lput@iii#1{\addto@par{nrot=#1}\@ifnextchar({\lput@iv}{\ncput@i}}
\def\lput@iv(#1){\addto@par{npos=#1}\ncput@i}
\def\mput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\mput@i}{\ncput@i}}}
\def\mput@i[#1]{\addto@par{ref=#1}\ncput@i}
\def\Lput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\Lput@ii}{\Lput@i}}}
\def\Lput@i#1{\addto@par{labelsep=#1}\Lput@ii}
\def\Lput@ii[#1]{\addto@par{ref={#1}}\@ifnextchar({\Lput@iv}{\Lput@iii}}
\def\Lput@iii#1{\addto@par{nrot={#1}}\@ifnextchar({\Lput@iv}{\Lput@v}}
\def\Lput@iv(#1){\addto@par{npos=#1}\Lput@v}
\def\Lput@v{\pst@killglue\pst@makebox{\Lput@vi}}
\def\Lput@vi{%
\begingroup
\use@par
\if@star\pst@starbox\fi
\Rput@vi
\pst@makesmall\pst@hbox
\ifx\psk@rot\@empty\else\pst@rotate{ps@rot }\pst@hbox\fi% (MJS)
%\pst@rotate\psk@nrot\pst@hbox
\ncput@iii
\endgroup
\pst@shortput}
\def\Mput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\Mput@ii}{\Mput@i}}}
\def\Mput@i#1{\addto@par{labelsep=#1}\Mput@ii}
\def\Mput@ii[#1]{\addto@par{ref={#1}}\Lput@v}
\def\aput@#1{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\aput@i#1}{\aput@ii#1}}}
\def\aput@i#1[#2]{\addto@par{labelsep=#2}\aput@ii#1}
\def\aput@ii#1{\@ifnextchar({\aput@iv#1}{\aput@iii#1}}
\def\aput@iii#1#2{\addto@par{nrot=#2}\@ifnextchar({\aput@iv#1}{#1}}
\def\aput@iv#1(#2){\addto@par{npos=#2}#1}
\def\aput{\aput@\naput@i}
\def\bput{\aput@\nbput@i}
\def\Aput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\Aput@i}{\naput@i}}}
\def\Aput@i[#1]{\addto@par{labelsep=#1}\naput@i}
\def\Bput{\def\pst@par{}\pst@ifstar{\@ifnextchar[{\Bput@i}{\nbput@i}}}
\def\Bput@i[#1]{\addto@par{labelsep=#1}\nbput@i}
%
\def\node@coor#1;#2\@nil{%  for normal nodes (name)
  \pst@getnode{#1}\pst@tempg
  \edef\pst@coor{%
    \pst@nodedict
    tx@NodeDict \pst@tempg known
    \pslbrace \pst@tempg load \tx@GetCenter \psrbrace
    \pslbrace 0 0 \psrbrace ifelse
    end }}
%
\def\Node@coor[#1]#2;#3\@nil{%  for special nodes ([...]{node}node)
\begingroup
\psset{angle=0,#1}%   angle=0, to prevent problems if angle is set globally
\@ifnextchar\bgroup{\Node@@@coor}% we have an additional node [...]{node}
                   {\Node@@coor}#2\@nil% we have  [...]node
\endgroup
\let\pst@coor\pst@tempg}
%
\def\Node@@coor#1\@nil{%
\pst@getnode{#1}\pst@tempg
\xdef\pst@tempg{%
\pst@nodedict
tx@NodeDict \pst@tempg known
  { \psk@nodesepA \psk@angleA 
    \pst@tempg load \psk@nodeseptypeA \tx@GetEdge
    \psk@offsetA \psk@angleA \tx@AddOffset
    \pst@tempg load \tx@GetCenter
    3 -1 roll add 3 1 roll add exch }
  { CP } ifelse end }}
%
\def\Node@@@coor#1{%   [...]{#1}node
\pst@@getcoor{#1}%
\def\psk@angleA{%
  \pst@tempg load \tx@GetCenter \pst@coor
  3 -1 roll sub 3 1 roll sub neg \tx@Atan \psk@angleB add
  }%
\Node@@coor}
%
\def\nput{\pst@object{nput}}
\def\nput@i#1#2{\pst@killglue\pst@makebox{\nput@ii{#1}{#2}}}
\def\nput@ii#1#2{%
  \begingroup
  \use@par
  \if@star\pst@starbox\fi%
  \psset[pstricks]{refangle=#1}%
  \let\psk@angleA\psk@refangle
  \edef\psk@nodesepA{\pst@number\pslabelsep}%
  \def\psk@nodeseptypeA{0 }%
  \pslabelsep\z@
  \uput@vi
  \Node@@coor#2\@nil
  \let\pst@coor\pst@tempg
  \leavevmode
  \psput@special\pst@hbox
  \endgroup
  \ignorespaces}
%  
\newcount\psrow
\newcount\pscol
\newcount\psmatrixcnt
\newskip\psrowsep
\newskip\pscolsep
%
\define@key[psset]{pst-node}{colsep}[1.5cm]{\pssetlength\pscolsep{#1}}
\define@key[psset]{pst-node}{rowsep}[1.5cm]{\pssetlength\psrowsep{#1}}
\psset[pst-node]{colsep=1.5cm}
\psset[pst-node]{rowsep=1.5cm}
\newif\ifpsmatrix
% DG/SR modification begin - Nov. 27, 1998 - Patch 8
%\let\mscount\@multicnt
\ifx\mscount\@undefined\let\mscount\@multicnt\fi
% DG/SR modification end
\def\psmatrix{\begingroup{\ifnum0=`}\fi % Don't want to expand any &.
  \@ifnextchar[{\psmatrix@i}{\ifnum0=`{\fi}{}\psmatrix@ii}}
\def\psmatrix@i[#1]{%
  \ifnum0=`{\fi}{}%
  \psset{#1}%
  \psmatrix@ii}
\def\psmatrix@ii{%
  \KillGlue
  \edef\psm@beginmath{%
    \ifmmode$\m@th\ifinner\textstyle\else\displaystyle\fi\fi}%
  \edef\psm@endmath{\ifmmode$\fi}%
  \let\\\psm@cr
  \advance\psmatrixcnt by \@ne
  \def\psm@thenode{M-\the\psmatrixcnt-\the\psrow-\the\pscol}%
  \tabskip\z@
  \psrow=\@ne
  \pscol\z@
  \psset{shortput=tablr}%
  \leavevmode
  \vbox\bgroup\halign\bgroup&%
  \begingroup
  \global\advance\pscol by \@ne
  \csname psrowhook\romannumeral\psrow\endcsname
  \csname pscolhook\romannumeral\pscol\endcsname
  \psm@beginnode##\psm@endnode\endgroup
  \cr}
%
\def\endpsmatrix{%
  \crcr\egroup\unskip\egroup
  \endgroup}
%
% hv 2007-10-16  fix bug with \\[name=...]
%\def\psm@cr{{\ifnum0=`}\fi\@ifnextchar[{\psm@@cr}{\psm@@@cr{}}}
\def\psm@cr{{\ifnum0=`}\fi\ps@ifnextchar[{\psm@@cr}{\psm@@@cr{}}}
%
\def\psm@@cr[#1]{\psm@@@cr{\vskip#1\relax}}
\def\psm@@@cr#1{%
  \ifnum0=`{\fi}{}\cr
  \noalign{%
  \global\advance\psrow 1
  \global\pscol\z@
  \vskip\psrowsep
  #1}}
\def\psm@beginnode{%
  \@ifnextchar\psm@endnode
    {\let\psm@endnode@i\relax\setbox\pst@hbox=\hbox{}}%
    {\pst@object{psm@beginnode}}}
\def\psm@beginnode@i{%
  \setbox\pst@hbox=\hbox\bgroup
  \psm@beginmath
  \begingroup
  \ignorespaces}
\def\psm@endnode@i{%
  \unskip
  \endgroup
  \psm@endmath
  \egroup
  \use@par
  \@psttrue}
\def\psm@endnode{%
  \@pstfalse
  \psm@endnode@i
  \ifnum\pscol>1\relax \pshskip\pscolsep \fi
  \psk@mnodesize
  \hfil
  \Pst@nodealigntrue
  \if@pst\csname mnode@\psk@mnode\endcsname
  \else\csname mnode@\psk@emnode\endcsname\fi
  \psk@mcol
  \psk@@mnodesize}
% DG/SR modification begin - Sep. 3, 1999 - Patch 10 - From Michael Sharpe
%\def\psspan#1{\mscount#1\relax\loop\ifnum\mscount>\@ne \sp@n\repeat}
\def\psspan#1{\global\mscount#1\relax\pstloop\ifnum\mscount>\@ne\sp@n\repeat}
\def\pstloop#1\repeat{\gdef\pstiterate{#1\relax\expandafter\pstiterate\fi}%
  \pstiterate
  \let\pstiterate\relax}
% DG/SR modification end
\define@key[psset]{pst-node}{name}[\relax]{\pst@getnode{#1}\psk@name}
\let\psk@name\relax
\define@key[psset]{pst-node}{mcol}[c]{%
  \ifx r#1\relax\let\psk@mcol\relax\else
    \ifx l#1\relax\let\psk@mcol\hfill\else
    \let\psk@mcol\hfil\fi\fi}
\psset[pst-node]{mcol=c}
%
\define@key[psset]{pst-node}{mnodesize}[-1pt]{%
  \pssetlength\pst@dimg{#1}%
  \ifdim\pst@dimg<\z@
    \let\psk@mnodesize\relax
    \let\psk@@mnodesize\relax
  \else
    \edef\psk@mnodesize{\noexpand\hbox to\number\pst@dimg sp\noexpand\bgroup}%
    \let\psk@@mnodesize\egroup
  \fi}
\psset[pst-node]{mnodesize=-1pt}
%
\def\mnode@R{\rnode@iii\Rnode@ii{\psm@thenode}}
\def\mnode@r{\rnode@iii\rnode@iv{\psm@thenode}}
\def\mnode@oval{\ovalnode@ii{\psm@thenode}}
\def\mnode@tri{\trinode@ii{\psm@thenode}}
\def\mnode@dia{\dianode@ii{\psm@thenode}}
\def\mnode@C{{\Pst@nodealigntrue\cnode@ii(\z@,\z@){\psk@radius}{\psm@thenode}}}
\def\mnode@f{{\Pst@nodealigntrue\fnode@ii(\z@,\z@){\psm@thenode}}}
\def\mnode@circle{\circlenode@ii{\psm@thenode}}
% hv modification begin - Aug. 16, 2007
\def\mnode@Circle{\Circlenode@ii{\psm@thenode}}
% hv modification end - Aug. 16, 2007
\def\mnode@p{\pnode(\z@,\z@){\psm@thenode}}
% DG/SR modification begin - Jul. 22, 1997 - Patch 1
\def\mnode@dot{\dotnode@ii(\z@,\z@){\psm@thenode}}
% DG/SR modification end
\def\mnode@none{\box\pst@hbox}
%
\define@key[psset]{pst-node}{mnode}[R]{%
  \@ifundefined{mnode@#1}%
    {\@pstrickserr{\string\psmatrix\space node `#1' not defined.}\@ehpa}%
    {\edef\psk@mnode{#1}}}
\define@key[psset]{pst-node}{emnode}[none]{%
  \@ifundefined{mnode@#1}%
    {\@pstrickserr{\string\psmatrix\space node `#1' not defined.}\@ehpa}%
    {\edef\psk@emnode{#1}}}
\psset[pst-node]{mnode=R,emnode=none}
%
%%%% FROM pst-coil.tex
\def\nccoil{\pst@object{nccoil}}
\def\nccoil@i{\check@arrow{\nccoil@ii}}
\def\nccoil@ii#1#2{\nc@object{Open}{#1}{#2}{.5}{
  \tx@NCCoor
  tx@Dict begin
  4 2 roll
  \psk@coilwidth \pscoilheight
  \psk@coilarmA \psk@coilarmB
  \psk@coilaspect \psk@coilinc
  \pst@coildict \tx@Coil end
  end}%
}
\def\nczigzag{\pst@object{nczigzag}}
\def\nczigzag@i{\check@arrow{\nczigzag@ii}}
\def\nczigzag@ii#1#2{\nc@object{Open}{#1}{#2}{.5}{
  \tx@NCCoor
  tx@Dict begin
  4 2 roll
  \pscoilheight
  \psk@coilwidth
  \psk@coilarmA
  \psk@coilarmB
  \pst@coildict \tx@ZigZag end
  \psline@iii
  \tx@Line
  end}%
}
% \psGetNodeCenter defines the PS variable #1.x and #1.y, which can then
% be used by the user. #1 must be a valid node name
\def\psGetNodeCenter#1{ tx@NodeDict begin /N@#1 load GetCenter end % x y on stack in system coor
  \pst@number\psyunit div /#1.y exch def 	% /#1.y in user coor
  \pst@number\psxunit div /#1.x exch def }	% /#1.x in user coor
%\def\psGetNodeEdgeA#1#2{ tx@NodeDict begin /N@#2 load #2 GetEdgeA end % x y on stack in system coor
%  \pst@number\psyunit div /#1.y exch def 	% /#1.y in user coor
%  \pst@number\psxunit div /#1.x exch def }	% /#1.x in user coor
\def\psGetEdgeA#1#2{
  tx@NodeDict begin \psk@offsetA \psk@offsetB neg 
    \psk@nodesepA \psk@nodesepB 0 0 
    /N@#1 /N@#2 InitNC { NCCoor } if pop pop \tx@UserCoor end}
\def\psGetEdgeB#1#2{
  tx@NodeDict begin \psk@offsetA \psk@offsetB neg 
    \psk@nodesepA \psk@nodesepB 0 0 
    /N@#1 /N@#2 InitNC { NCCoor } if 4 2 roll pop pop \tx@UserCoor end}
%
%%%%%%%%%%%%%% the pst-node-tools part %%%%%%%%%%%%%%%%%%%%%%%%
%
\def\ncbarr{\pst@object{ncbarr}}
\def\ncbarr@i#1#2{%
  \begingroup
  \use@par%
  \psLNode(#1)(#2){0.5}{barr@tempNode}%
  \pst@dimc=\psk@angleA pt
  \pst@dimd=180pt
  % be sure, that angleA is 0 or 180. if not, we set it to 0
  \ifdim\pst@dimc=\z@\else\ifdim\pst@dimc=\pst@dimd\else\psset{angleA=0}\fi\fi
  \ncbar[arrows=-]{#1}{barr@tempNode}
  \ifdim\psk@angleA pt=\z@\relax
    \ncbar[angleA=180,angleB=180]{barr@tempNode}{#2}
  \else\ncbar[angleA=0,angleB=0]{barr@tempNode}{#2}\fi%
  \endgroup%
}
%   #1-------#4----------------#2
% where #1#4= #3 * #1#2
%
\def\psLNode(#1)(#2)#3#4{%
  \pst@getcoor{#1}\pst@tempA%
  \pst@getcoor{#2}\pst@tempB%
  \pnode(!
    \pst@tempA /YA exch \pst@number\psyunit div def
    /XA exch \pst@number\psxunit div def
    \pst@tempB /YB exch \pst@number\psyunit div def
    /XB exch \pst@number\psxunit div def
    /dx XB XA sub def
    /dy YB YA sub def
    XA dx #3\space mul add YA dy #3\space mul add){#4}}
%
% build the linear combination #2*#1+#4*#3=#5
\def\psLCNode(#1)#2(#3)#4#5{%
  \pst@getcoor{#1}\pst@tempA%
  \pst@getcoor{#3}\pst@tempB%
  \pnode(!
    \pst@tempA /YA exch \pst@number\psyunit div def
    /XA exch \pst@number\psxunit div def
    \pst@tempB /YB exch \pst@number\psyunit div def
    /XB exch \pst@number\psxunit div def
    XA #2\space mul XB #4\space mul add
    YA #2\space mul YB #4\space mul add){#5}}
%
\def\psLDNode(#1)(#2)#3#4{%  
% #1: node A  #2: node B  #3: dimen measured from A  #4: node name
  \pst@getcoor{#1}\pst@tempA%
  \pst@getcoor{#2}\pst@tempB%
  \pssetlength\pst@dimb{#3}%
  \pnode(!%
    \pst@tempA /YA exch \pst@number\psyunit div def
    /XA exch \pst@number\psxunit div def
    \pst@tempB /YB exch \pst@number\psyunit div def
    /XB exch \pst@number\psxunit div def
    /dx XB XA sub def
    /dy YB YA sub def
    /angle dy dx Atan def
    /linelength \pst@number\pst@dimb \pst@number\psunit div def
    XA linelength angle cos mul add YA linelength angle sin mul add ){#4}}
%
\def\psRelNode{\pst@object{psRelNode}}
\def\psRelNode@i(#1)(#2)#3#4{{% A - B - factor - node name
  \use@par
%  \pst@killglue
  \pst@getcoor{#1}\pst@tempA%
  \pst@getcoor{#2}\pst@tempB%
  \pnode(!
    \pst@tempA /YA exch \pst@number\psyunit div def
    /XA exch \pst@number\psxunit div def
    \pst@tempB /YB exch \pst@number\psyunit div def
    /XB exch \pst@number\psxunit div def
    /AlphaStrich \psk@angleA\space def
    /unit \pst@number\psyunit \pst@number\psxunit div def % yunit/xunit
%            
    /dx__ XB XA sub  def
    /dy__ YB YA sub \ifPst@trueAngle\space unit mul \fi\space def
    /laenge dy__ dup mul dx__ dup mul add sqrt #3 mul def
    /Alpha dy__ dx__ atan def 
    /beta Alpha AlphaStrich add def
    laenge beta cos mul XA add
    laenge beta sin mul \ifPst@trueAngle\space unit div \fi\space YA add ){#4}%
}\ignorespaces}
%
\define@cmdkeys[psset]{pstricks-add}[PSTPSPNk@]{% Christophe Jorssen 2007
  blName,bcName,brName,
  clName,ccName,crName,
  tlName,tcName,trName}[]{}%
\psset[pstricks-add]{%
  blName=PSPbl,bcName=PSPbc,brName=PSPbr,
  clName=PSPcl,ccName=PSPcc,crName=PSPcr,
  tlName=PSPtl,tcName=PSPtc,trName=PSPtr}
\def\psDefPSPNodes{\def\pst@par{}\pst@object{psDefPSPNodes}}
\def\psDefPSPNodes@i{%
  \pst@killglue
  \begingroup
  \use@par
  \expandafter\psDefPSPNodes@ii\pic@coor}
%
\def\psDefPSPNodes@ii(#1)(#2)(#3){%
%    \pnode(#1){PSPN@temp}\pnode([nodesep=.75,angle=45]PSPN@temp){\PSTPSPNk@blName}
%    \pnode(#3){PSPN@temp}\pnode([nodesep=.75,angle=-135]PSPN@temp){\PSTPSPNk@trName}
    \pnode(#1){PSPN@temp}\pnode([angle=45]PSPN@temp){\PSTPSPNk@blName}
    \pnode(#3){PSPN@temp}\pnode([angle=-135]PSPN@temp){\PSTPSPNk@trName}
    \pnode(\PSTPSPNk@blName|\PSTPSPNk@trName){\PSTPSPNk@tlName}
    \pnode(\PSTPSPNk@trName|\PSTPSPNk@blName){\PSTPSPNk@brName}
    \ncline[linestyle=none]{\PSTPSPNk@blName}{\PSTPSPNk@tlName}
    \ncput[npos=.5]{\pnode{\PSTPSPNk@clName}}
    \ncline[linestyle=none]{\PSTPSPNk@blName}{\PSTPSPNk@brName}
    \ncput[npos=.5]{\pnode{\PSTPSPNk@bcName}}
    \pnode(\PSTPSPNk@brName|\PSTPSPNk@clName){\PSTPSPNk@crName}
    \pnode(\PSTPSPNk@bcName|\PSTPSPNk@trName){\PSTPSPNk@tcName}
    \pnode(\PSTPSPNk@bcName|\PSTPSPNk@clName){\PSTPSPNk@ccName}
  \endgroup
  \ignorespaces}
%
%
\def\psDefBoxNodes#1#2{\rnode[tl]{#1:tl}{\rnode[Bl]{#1:Bl}{\rnode[tr]{#1:tr}{%
\rnode[bl]{#1:bl}{\rnode[Br]{#1:Br}{\rnode[br]{#1:br}{#2}}}}}}%
\pnode(!\psGetNodeCenter{#1:bl}
          \psGetNodeCenter{#1:tl} 
          #1:bl.x #1:tl.x add 2 div #1:bl.y #1:tl.y add 2 div ){#1:Cl}%
\pnode(!\psGetNodeCenter{#1:tr}
          \psGetNodeCenter{#1:br} 
          #1:tr.x #1:br.x add 2 div #1:tr.y #1:br.y add 2 div ){#1:Cr}%
\pnode(!\psGetNodeCenter{#1:Cl}
          \psGetNodeCenter{#1:Cr} 
          #1:Cl.x #1:Cr.x add 2 div #1:Cl.y #1:Cr.y add 2 div ){#1:C}%
\pnode(!\psGetNodeCenter{#1:Br}
          \psGetNodeCenter{#1:Bl} 
          #1:Br.x #1:Bl.x add 2 div #1:Br.y #1:Bl.y add 2 div ){#1:BC}%
\pnode(!\psGetNodeCenter{#1:tr}
          \psGetNodeCenter{#1:tl} 
          #1:tr.x #1:tl.x add 2 div #1:tr.y #1:tl.y add 2 div ){#1:tC}%
\pnode(!\psGetNodeCenter{#1:br}
          \psGetNodeCenter{#1:bl} 
          #1:br.x #1:bl.x add 2 div #1:br.y #1:bl.y add 2 div ){#1:bC}}%
%
%
%% Author: Michael Sharpe (msharpe at ucsd.edu)
% Macros defined in this file:
% \defaultvalue{<command>}{<value>} assigns <value> to <command> is command is not defined, or is empty.
% \testAlg---used internally to test whether an parametric expression in t is algebraic
% \trim{<command>} trims white space from ends of expansion of <command>
% \hasparen sets \parentrue if its argument contains a (
% \hasequal sets \equaltrue if its argument starts with =
% \equalwhat returns what follows =
% \parsenodexn parses a node expression recursively. Better to use \nodexn.
% \normalvec(<vec>){<nodename>} returns vector normal to <vec> (same length) in <nodename>
% \curvepnode{<t>}{<expression in t>}{<nodename>} Eg, \curvepnode{1}{sin(t) | cos(t)}{P} sets a pnode named P at (cos(1), sin(1))
% \psparnode{<t>}{<expression> in t>}{<nodename>} is called by \curvename if expression is PostScript, not algebraic
% \algparnode{<t>}{<expression> in t>}{<nodename>} is called by \curvename if expression is algebraic, not PostScript
% \nodexn is like \parsenodexn, slightly different syntax. \nodexn{<exn>}{<name>} evaluates <exn> as a node expression and calls the result <name>. 
% \psxline(P){<nodexn1>}{<nodexn2>} draws line from P+<nodexn1> to P+<nodexn2>. The novelty is that the last two arguments can be node expressions.
% \curvepnodes{<tmin>}{<tmax>}{<expression in t>}{<node root name>} Uses current setting of plotpoints (default 50) to define a sequence of pnodes along the curve. Eg, \curvepnodes[plotpoints=100]{0}{1}{t+t^2 | Ex(-t)}{P} sets pnodes P0..P99 at equally spaced t values along the curve, and defines the macro \Pnodecount to 99, the highest index. The expression in t may be either algebraic or PostScript, and is handled automatically detected.
% \fnpnode{<xval>}{<expression in x>}{<nodename>} sets a single pnode on graph. Eg, \fnpnode{.5}{x 2 mul x 1 add mul}{P} declares the pnode P at the point x=0.5 on the graph. (Same as \pnode(!/x 0.5 def x x 2 mul x 1 add mul}){P}.) If your expression in t is algebraic, you must use the keyword algebraic, as in \fnpnode[algebraic]{0.5}{2*x*(x+1)}{P}.
% \fnpnodes{<xmin}{<xmax>}{<expression in x>}{<node root name>} Is exactly the same as \curvenodes, but for the graph of a function. The keyword algebraic must be specified if your expression is algebraic
% \AtoB(A)(B){C} defines node by name C essentially as B-A
% \AplusB(A)(B){C} defines node by name C essentially as A+B
% \midAB(A)(B){C} defines node by name C essentially as (A+B)/2
% \psnline[linewidth=1pt,arrows=->](3,5){P}, for example, expects that there are pnodes named P3..P7 (total of 5), and effectively gives the same result as \psline[linewidth=1pt,arrows=->](P3)(P4)(P5)(P6)(P7). Note that arrow must be specified with a keyword, not as an argument.
% \shownode(P) displays in the console window the coordinates of node P. This will not appear until the final stage of processing the PostScript file. It is a debugging tool.
% \getnodelist{<node root name>}{<next command>} is useful in writing pstricks macros, where there is a list of parenthesized coordinates to be read and turned into a node sequence, following which <next command> is followed.
% \pnodes{P}(1,2)(2;3)... is effectively \getnodelist{P}{}(1,2)(2;3)..., just a quick way to turn a list of coordinates into pnodes P0 P1 ...
% \psLCNodeVar is similar to \psLCNode, and provides a means of forming a linear combination of two nodes, thought of as vectors. Where \psLCNode(A){a}(B){b}{C} effectively makes C=aA+bB, \psLCNodeVar(A)(B)(a,b){C} does the same, but the third argument (a,b) may be specified in PostScript code or any form recognized by \SpecialCoor. Unlike \psLCNode, the name C may be one of A, B.
% \psRelNodeVar is similar to \psRelNode, and provides a means of rotating and changing the length of a line segment AB about A. The effect of \psRelNodeVar(A)(B)(2;30){C} is the same as \psRelNode[angle=30](A)(B){2}{C}, but the third argument (2;30) may be specified in PostScript code, which is not possible with \psRelNode.
% \psRelLineVar stands to \psRelLine as \psRelNodeVar stands to \psRelNode.
% \rhombus{<edge length>}(A)(B){C}{D} computes the two remaining vertices C, D given two opposing vertices A, B of a rhombus with given edge length. It does not draw the rhombus--- that can be handled easily by \pspolygon(A)(C)(B)(D).
% \psrline(P)(Q)... is like \psline, drawing a line starting at (P), with successive increments (Q)... It has the same options as \psline. Eg, \psrline[linecolor=red]{->}(1,1)(1,0)
% \polyIntersection is the most complicated macro in the collection. It has two forms
% \polyIntersection{<Nodename1>}{<Nodename2>}(A)(B)(1,2)(3;30)(6,5)...
%works with the line starting at A heading toward B, and computes the first point that lies on the polyline (1,2)(3;30)(6,5)..., calling it <Nodename1>. It also computes the first point in the opposite direction (from A) lying on that polyline, naming it <Nodename2>. If one or other of these intersections is empty, the nodes are set to remote points on the line. The two nodes are then joined by a line. The effect depends on the location of A and B relative to the polyline, with two cases worth noting.
% (a) if the polyline is closed and if A, B are interior to one of its components, you get a line segment from one edge to the other, containing AB.
% (b) If the polylne is simple and closed, and one of A, B is inside and the other outside, the resulting line segment will contain A but not B. 
% \polyIntersection{<Nodename1>}{<Nodename2>}(A)(B){P}{n} works exactly the same as \polyIntersection{<Nodename1>}{<Nodename2>}(A)(B)(P0)(P1)...(Pn), assuming P0...Pn are previously defined as pnodes.
% \psStepa is like \psStep (pstricks-add) but for a node sequence rather than equally spaced abscissas. \psStepa[options]{<node root>}{<maxindex>} draws a step function with jumps at the successive nodes in the node sequence. Eg, \psStepa{P}{10} has jumps at P0..P10
%
\newcount\pst@args%used in several macros
\newcount\num@pts
\newcount\pst@argcnt% for use in parsing node expressions
\def\PST@root{}
\let\pst@next\relax
%my scratch variables
\def\my@tempA{}
\def\my@tempB{}
\def\my@tempC{}
\def\my@tempD{}
\def\my@next{}
\newif\if@paren%
\newif\if@equal%
\newif\if@colon%
\newif\ifshow
\def\plussign{+}\def\minussign{-}
%
%
\def\defaultvalue#1#2{%#1 is a command, #2 is a value, possibly a command
  \ifdefined#1\ifx#1\@empty\xdef#1{#2}\fi\else\xdef#1{#2}\fi}%
%
\def\testAlg#1|#2\@nil{%
\ifx\relax#2\relax%
   \let\my@next\psparnode\xdef\my@tempD{}%
\else%
   \let\my@next\algparnode\xdef\my@tempD{A}% algebraic
\fi}%
%
%Jonathan Fine's trim
\def\trim #1{\expandafter\trim@\expandafter{#1 }#1}%
\def\trim@ #1{\trim@@ @#1 @ #1 @ @@}%
\def\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}%
\def\unbrace#1{#1}%
\unbrace{\def\trim@@@ #1 } #2@#3{\expandafter\def\expandafter #3\expandafter {#1}}%
%
\def\hasparen#1(#2\@nil{%check if expression contains a (--call with \hasparen#1(\@nil
  \ifx\relax#2\relax \@parenfalse \else \@parentrue\fi}%
%
\def\hasequal#1=#2\@nil{%check if expression contains a =--call with \hasequal#1=\@nil
  \ifx\relax#2\relax \@equalfalse \else \@equaltrue\fi
  \hascolon#2:\@nil}%
%
\def\hascolon#1:#2\@nil{%check if expression contains a :--call with \hascolon#1:\@nil
\ifx\relax#2\relax \@colonfalse \else \@colontrue\fi}%
%
\def\equalwhat#1=#2:#3\@nil{{#2}{#3}}%
%
\def\parsenodexn#1(#2)#3\@nil{%
  \def\coeffA{#1}\edef\nodeA{#2}%
  \trim\coeffA%
  \ifx\nodeA\@empty\else%
    \pnode(#2){@@TMP}%
    \ifx\coeffA\@empty\def\coeffA{1}\else%
      \ifx\coeffA\plussign\def\coeffA{1}\else\ifx\coeffA\minussign\def\coeffA{-1}\fi\fi\fi% 
  \edef\cmd{\noexpand\psLCNode(@TMP\the\pst@argcnt){1}(@@TMP){\coeffA}{@TMP}}%
  \cmd%
  \advance\pst@argcnt by \@ne%
  \pnode(@TMP){@TMP\the\pst@argcnt}%
  \parsenodexn#3\@nil%
  \fi}%
%
\def\normalvec(#1)#2{%
%pnode | new pnode normal to old, same  length
  \psRelNodeVar(0,0)(#1)(0,1){#2}}%
%
\def\curvepnode#1#2#3{%
% #1=t value, #2=x(t) y(t) in either form,#3=node name,
%must first detect which form of x(t) y(t), looking for |
  \edef\my@tempA{#2}% x(t) y(t) expanded
  \expandafter\testAlg\my@tempA|\@nil\my@next {#1}{#2}{#3}}
%
\def\psparnode#1#2#3{%
 % #1=t value, #2=x(t) y(t) in PS form, #3=node name,
 % also returns unit tangent vector at t with node #3tang
   \pnode(! /t #1 def #2){#3}%
   \pnode(! /t #1 dup abs 1 lt {0.001 sub} {dup 0 gt {0.999} {1.001} ifelse mul} ifelse def 
            #2 
            /t #1 dup abs 1 lt {0.001 add} {dup 0 lt {0.999} {1.001} ifelse mul} ifelse def 
            #2 
            3 -1 roll sub 3 1 roll exch sub 2 copy exch dup mul exch dup mul add sqrt 
            dup 3 1 roll div 3 1 roll div){#3tang}% unit tangent vector at t
}%
%
\def\algparnode#1#2#3{%
% #1=t value, #2=x(t) | y(t) in alg form, #3=node name,
% also returns unit tangent vector at t with node #3tang
   \pstVerb{tx@Dict begin /Func (#2) AlgParser cvx def end }%
   \pnode(! /t #1 def Func){#3}%
   \pnode(! /t #1 dup abs 1 lt {0.001 sub} {dup 0 gt {0.999} {1.001} ifelse mul} ifelse def 
            Func 
            /t #1 dup abs 1 lt {0.001 add}{dup 0 lt {0.999} {1.001} ifelse mul } ifelse def 
            Func 
            3 -1 roll sub 3 1 roll exch sub 2 copy exch dup mul exch dup mul add sqrt 
            dup 3 1 roll div 3 1 roll div){#3tang}% unit tangent vector at t
}%
%
\def\nodex#1{%
%#1=node expression --set nodename to @TMP
\expandafter\hasparen#1(\@nil%
\if@paren%it's an expression
  \pnode(0,0){@TMP0}%
  \pst@argcnt=0%
  \expandafter\parsenodexn#1()\@nil%
\else%
  \def\my@tempC{#1}%
  \ifx\my@tempC\@empty\pnode(0,0){@TMP}\else\pnode(#1){@TMP}\fi%
\fi}%\if@paren
%
\def\nodexn#1#2{%
%#1=node expression | #2=node name
\expandafter\hasparen#1(\@nil%%%      hv 20130917 use \expandafter
\if@paren%it's an expression
  \pnode(0,0){@TMP0}%
  \pst@argcnt=0%
  \parsenodexn#1()\@nil%
  \pnode(@TMP){#2}%
\else%
  \def\my@tempC{#1}%
  \ifx\my@tempC\@empty\pnode(0,0){#2}\else\pnode(#1){#2}\fi%
\fi}%\if@paren
%
\def\psxline{\pst@object{psxline}}%
\def\psxline@i{\@ifnextchar({\psxline@iii}{\psxline@ii}}%
\def\psxline@ii#1{%
\addto@par{arrows=#1}%
\psxline@iii}%
\def\psxline@iii(#1)#2#3{{%#1=basepoint, #2,#3 node expressions
\pst@killglue%
\use@par%
\nodexn{#2}{@TMP@a}%
\AplusB(#1)(@TMP@a){@TMP@A}%
\nodexn{#3}{@TMP@a}%
\AplusB(#1)(@TMP@a){@TMP@B}%
\psline(@TMP@A)(@TMP@B)%
}\ignorespaces}%
%
\def\curvepnodes{\pst@object{curvepnodes}}
\def\curvepnodes@i#1#2#3#4{{%optional [plotpoints=xx]
%  #1=tmin,#2=tmax,#3=function (of t),#4=node root name,
  \pst@killglue
  \use@par
  \edef\my@tempA{#3}% x(t) y(t) expanded
  \expandafter\testAlg\my@tempA|\@nil %
  \pstVerb{% 
	tx@Dict begin % so we can use definitions from tx@Dict
	/t0 #1 def
	/t1 #2 def  
	 t1 t0 sub end \psk@plotpoints div /dt exch def }%
  \pst@cntc=\psk@plotpoints\relax%\psk@plotpoints=plotpoints-1
  \advance\pst@cntc by \@ne\relax %=plotpoints
  \ifx\my@tempD\@empty\pstVerb{tx@Dict begin /Func (#3) cvx def end }%add tx@Dict
  \else\pstVerb{tx@Dict begin /Func (#3 ) AlgParser cvx def end }%
  \fi%
    \multido{\i=0+1}{\pst@cntc}{%
      \pnode(! /t #1 dt \i\space mul add def Func ){#4\i}}% remove t before Func
    \expandafter\xdef \csname #4nodecount\endcsname {\psk@plotpoints}%
    \ifnum\Pst@Debug>0 \typeout{Created nodes #40 .. #4\psk@plotpoints}\fi%
}\ignorespaces}%
%
\def\fnpnode{\pst@object{fnpnode}}
\def\fnpnode@i#1#2#3{{%optional [algebraic]
%#1=x value | #2=fn of x | #3=node name
  \pst@killglue
  \use@par
  \ifPst@algebraic\pnode(*#1 {#2}){#3}\else\pnode(! /x #1 def x #2){#3}\fi
}\ignorespaces}%
%
\def\fnpnodes{\pst@object{fnpnodes}}
\def\fnpnodes@i#1#2#3#4{{%optional [algebraic]
%#1=xmin | #2=xmax | #3= fn of x | #4=node name
\pst@killglue
\use@par
\pst@dima=#1pt \pst@dimb=#2pt \advance\pst@dimb -\pst@dima%
\pst@cnta=\psk@plotpoints \relax %=plotpoints-1
\def\PST@root{#4}
\divide\pst@dimb by \pst@cnta%plotpoint-1 intervals
\pst@cntc=\pst@cnta %
\advance\pst@cntc by 1 \relax %=plotpoints
\ifPst@algebraic 
  \multido{\i=0+1}{\pst@cntc}{\pnode(*{\pst@number\pst@dima} {#3}){#4\i}%  hv 20130713
  \advance\pst@dima \pst@dimb}%
\else
    \multido{\i=0+1}{\pst@cntc}{\pnode(!/x \pst@number\pst@dima\space def x #3){#4\i}%
  \advance\pst@dima \pst@dimb}%
\fi
  \expandafter\xdef \csname \PST@root nodecount\endcsname {\the\pst@cnta}%
  \ifnum\Pst@Debug>0 \typeout{Created nodes #40 .. #4\the\pst@cnta}\fi%
}\ignorespaces}%
%
\def\AtoB(#1)(#2)#3{\psLCNodeVar(#1)(#2)(-1,1){#3}}
\def\AplusB(#1)(#2)#3{\psLCNodeVar(#1)(#2)(1,1){#3}}
\def\midAB(#1)(#2)#3{\psLCNodeVar(#1)(#2)(.5,.5){#3}}
%
\def\psnline{\pst@object{psnline}}%line of nodes
\def\psnline@i{\pst@getarrows{\psnline@ii}}
\def\psnline@ii(#1,#2)#3{{%
\pst@killglue%
\use@par%
\pst@cnta=#2 \relax\advance\pst@cnta by 1
\edef\@tmp{}%
\multido{\i=#1+1}{\pst@cnta}{\xdef\@tmp{\@tmp(#3\i)}}%
\expandafter\psline\@tmp}%
\ignorespaces}%
%
\def\psnpolygon{\pst@object{psnpolygon}}%polygon of nodes
\def\psnpolygon@i{\pst@getarrows{\psnpolygon@ii}}
\def\psnpolygon@ii(#1,#2)#3{{%
\pst@killglue%
\use@par%
\pst@cnta=#2 \relax\advance\pst@cnta by 1
\edef\@tmp{}%
\multido{\i=#1+1}{\pst@cnta}{\xdef\@tmp{\@tmp(#3\i)}}%
\expandafter\pspolygon\@tmp}%
\ignorespaces}%
%
\def\psncurve{\pst@object{psncurve}}%line of nodes
\def\psncurve@i{\pst@getarrows{\psncurve@ii}}
\def\psncurve@ii(#1,#2)#3{{%
\pst@killglue%
\use@par%
\pst@cnta=#2 \relax\advance\pst@cnta by 1
\edef\@tmp{}%
\multido{\i=#1+1}{\pst@cnta}{\xdef\@tmp{\@tmp(#3\i)}}%
\expandafter\pscurve\@tmp}%
\ignorespaces}%
%
\def\psnccurve{\pst@object{psnccurve}}%line of nodes
\def\psnccurve@i{\pst@getarrows{\psnccurve@ii}}
\def\psnccurve@ii(#1,#2)#3{{%
\pst@killglue%
\use@par%
\pst@cnta=#2 \relax\advance\pst@cnta by 1
\xdef\@tmp{}%
\multido{\i=#1+1}{\pst@cnta}{\xdef\@tmp{\@tmp(#3\i)}}%
\expandafter\psccurve\@tmp}%
\ignorespaces}%
%
\def\shownode(#1){%display node user coords in console
  \pst@killglue%
  \pstVerb{% 
    gsave tx@Dict begin %
    tx@NodeDict /N@#1 known { % known node
      /tmpar [(Node #1: ) <28> () (, ) () <29>] def %
      /str 12 string def 
      STV CP T \psGetNodeCenter{#1}\space 
      tmpar 2 #1.x str cvs put 
      /str 12 string def 
      tmpar 4 #1.y str cvs put 
      tmpar concatstringarray = }%
    {% not known
      (Node #1: (NOT KNOWN)) = %
    } ifelse %
    end grestore }%
  \ignorespaces}%
%
% Use to construct a sequence of nodes
% Eg, \pnodes{P}(0,1)(2;5)(3,4) defines nodes P0, P1, P2 with respective locations
% and a macro \Pnodecount containing the highest index created
\def\pnodes@ii#1{\getnodelist{#1}{}}
%
\def\getnodelist#1#2{%
\pst@args=0 \relax%
\def\PST@root{#1}%
\def\pst@next{#2}% command to perform after reading list
\getnext@Node}%
%
\def\getnext@Node{\@ifnextchar({\getnext@Node@i}%
  {\advance\pst@args by \m@ne \expandafter\xdef \csname \PST@root nodecount\endcsname {\the\pst@args}
  \ifnum\Pst@Debug>0 \typeout{Created nodes \PST@root0 .. \PST@root\the\pst@args}\fi% 
  \pst@next}%
}%
%
\def\getnext@Node@i(#1){%
\pnode(#1){\PST@root\the\pst@args}%
\advance\pst@args by \@ne\relax%
\getnext@Node}%
%
\def\psLCNodeVar(#1)(#2)(#3)#4{%
\pst@getcoor{#1}\my@tempA%
\pst@getcoor{#2}\my@tempB%
\pnode(#3){tmpLCn@de}%
\pnode(!%
  \my@tempA /YA exch \pst@number\psyunit div def
  /XA exch \pst@number\psxunit div def
  \my@tempB /YB exch \pst@number\psyunit div def
  /XB exch \pst@number\psxunit div def %stack now empty
  \psGetNodeCenter{tmpLCn@de}\space
  XA tmpLCn@de.x mul XB tmpLCn@de.y mul add
  YA tmpLCn@de.x mul YB tmpLCn@de.y mul add){tmpLCn@deA}%
\pnode(tmpLCn@deA){#4}%
}%
%
\def\psRelNodeVar{\pst@object{psRelNodeVar}}
\def\psRelNodeVar@i(#1)(#2)(#3)#4{{% A - B - factor;angle - node name
  \use@par
  \pst@getcoor{#1}\my@tempA%
  \pst@getcoor{#2}\my@tempB%
   \pnode(#3){tmpn@de}%
\pnode(!
  /unit \pst@number\psyunit \pst@number\psxunit div def % yunit/xunit
    \my@tempA /YA exch \pst@number\psyunit div def
    /XA exch \pst@number\psxunit div def
    \my@tempB /YB exch \pst@number\psyunit div YA sub 
    \ifPst@trueAngle\space unit mul \fi\space def
    /XB exch \pst@number\psxunit div XA sub def
    %complex multiply (XB,YB) and (P.x,P.y), then add (XA,YA)
    \psGetNodeCenter{tmpn@de}
    XB tmpn@de.x mul YB tmpn@de.y mul sub
    YB tmpn@de.x mul XB tmpn@de.y mul add
    \ifPst@trueAngle\space unit div \fi\space 
   YA add exch XA add exch %x, y coords on stack
    ){#4}%
}}
%
\def\psRelLineVar{\pst@object{psRelLineVar}}
\def\psRelLineVar@i{\@ifnextchar({\psRelLineVar@iii}{\psRelLineVar@ii}}
\def\psRelLineVar@ii#1{%
  \addto@par{arrows=#1}%
  \psRelLineVar@iii}
\def\psRelLineVar@iii(#1)(#2)(#3)#4{{%
  \pst@killglue
  \use@par
  \psRelNodeVar(#1)(#2)(#3){#4}%
  \psline(#1)(#4)%
}\ignorespaces}
%
\def\rhombus#1(#2)(#3)#4#5{% \rhombus{m}(B)(D){A}{C} 
\AtoB(#2)(#3){node@P}% P=BD
% compute angle between BD and BC, in Postscript
\pnode(! %compute angle and scale in PS
/tmp \psGetNodeCenter{node@P} node@P.x node@P.y 
Pyth 2 div def %tmp=half-length of BD
/ang tmp #1\space div Acos def %ang=angle from BD to BC & BA
#1\space tmp 2 mul div %scale factor s=m/BD
dup ang cos mul exch ang sin mul ){node@A1}% s cos(ang), s sin(ang)
\pnode(! \psGetNodeCenter{node@A1} node@A1.x node@A1.y neg ){node@A2}%reflect in x axis
\psRelNodeVar(#2)(#3)(node@A1){#4}%
\psRelNodeVar(#2)(#3)(node@A2){#5}%
}%
%
\def\psrline{\pst@object{psrline}}% relative lines
\def\psrline@i{\@ifnextchar({\psrline@iii}{\psrline@ii}}%
\def\psrline@ii#1{%
\addto@par{arrows=#1}%
\psrline@iii}%
\def\psrline@iii{%
\getnodelist{@tmpnode}{\psrline@iv}%
}%
\def\psrline@iv{%
   \ifnum\pst@args<0\else%do nothing
      \pnode(@tmpnode0){@tmpnodeB0}%
      \multido{\iA=1+1,\iB=0+1}{\pst@args}{%
      \AplusB(@tmpnodeB\iB)(@tmpnode\iA){@tmpnodeB\iA}}%
      \psrline@v%
   \fi%
}%
\def\psrline@v{{%finish up
  \pst@killglue%
  \use@par%
  \xdef\tmp{(@tmpnodeB0)}%
  \multido{\i=1+1}{\pst@args}%
{\xdef\tmp{\tmp(@tmpnodeB\i)}}%
\expandafter\psline\tmp%
}\ignorespaces}%
%
\def\polyIntersections#1#2(#3)(#4){%
%nodename1 | nodename2 | A | B | % intersections with line from A, B 
\def\nodenameA{#1}\def\nodenameB{#2}%
\pnode(#3){P@A}\pnode(#4){P@B}%
\@ifnextchar({\polyIntersections@next}{\polyIntersections@ii}%
}%
\def\polyIntersections@ii#1#2{%
\def\root@node{#1}\num@pts=#2 \relax%
\polyIntersections@iii}% 
%
\def\polyIntersections@next{%read as many points as exist
\def\root@node{P@}\getnodelist{P@}{\num@pts=\pst@args \relax\polyIntersections@iii}%
}%
\def\polyIntersections@iii{%nodes are now XXX0....XXXn, n=num@pts
\pst@cnta=\num@pts \relax\advance\pst@cnta by 1 \relax%
\pstVerb{%
 /xarray \the\pst@cnta\space array def
 /yarray \the\pst@cnta\space array def  tx@Dict begin }%
\multido{\i=0+1}{\the\pst@cnta}{\pstVerb{ \psGetNodeCenter{\root@node\i} xarray \i\space \root@node\i.x put yarray \i\space \root@node\i.y put }}%
\pstVerb{ /tposmin 100 def /tnegmax -100 def %/argposmin 0 def /argposmax 0 def 
\psGetNodeCenter{P@B} \psGetNodeCenter{P@A} 
/dx P@B.x P@A.x sub def 
/dy P@B.y P@A.y sub def 
/lenAB dx dy Pyth def
/oldx xarray 0 get def /oldy yarray 0 get def 
1 1 \the\num@pts\space {/k exch def /newx xarray k get def /newy yarray k get def 
/ddx newx oldx sub def /ddy newy oldy sub def 
/det ddy dx mul ddx dy mul sub def
det abs lenAB ddx ddy Pyth mul .001 mul gt 
{/ac oldx P@A.x sub def /bd oldy P@A.y sub def 
 /tt  ac ddy mul bd ddx mul sub det div def %solve for t value at intersection
 /ss ac  dy mul bd dx mul sub det div def % solve for s value at intersection
ss 0 ge 
   {ss 1 le 
        {tt 0 lt {tt tnegmax gt {/tnegmax tt def} if } {tt tposmin lt {/tposmin tt def} if } ifelse }
    if } % ss 1 le
if }%ss 0 ge
 if %det>
 /oldx newx def /oldy newy def} for end }%
\pnode(! \psGetNodeCenter{P@A} \psGetNodeCenter{P@B} P@B.x P@A.x sub  tposmin mul P@A.x add  P@B.y P@A.y sub tposmin  mul P@A.y add ){\nodenameA}%
\pnode(! \psGetNodeCenter{P@A} \psGetNodeCenter{P@B} P@B.x P@A.x sub tnegmax mul P@A.x add P@B.y P@A.y sub tnegmax mul P@A.y add){\nodenameB}%
}%
%
\def\actualscale#1 #2 scale{% extract x-scale from, eg,  {2. 2. scale}
#1}
%
\def\psGetCenter#1{ tx@NodeDict begin /N@#1 load GetCenter end }% x y on stack in system coor
%
\def\ArrowNotch{\pst@object{ArrowNotch}}
\def\ArrowNotch@i#1#2#3#4{{%
%noderootname | index | arrowdirection | notchnodename  % 
\pst@killglue%
\use@par%
\def\inc{-1}%
\ifx#3<\def\inc{1}\fi% -1 means notch to left of arrowhead
%get length of pointed arrow under these conditions (types ->, -D> and their reverses)
\pstVerb{ 
    1 \psk@arrowinset\space sub \psk@arrowlength\space \psk@arrowsize\space  
    \pst@number\pslinewidth \space mul add  mul mul 
    \expandafter\actualscale\psk@arrowscale \space  mul 
    /hh exch def /hh1 hh .05 sub def }% PS variable hh contains dist from tip to notch of arrow, in pts
\def\root@node{#1}\num@pts=\csname\root@node nodecount\endcsname %
\pst@cntb=\num@pts \advance\pst@cntb by \@ne%actual node count
\pst@cnta=\num@pts \advance\pst@cnta by \thr@@%size of PS array
\pst@cntc=#2 \relax% index of center of circle
\ifnum\pst@cntc>\num@pts \pnode(0,0){#4}\else
%compute a (screen based) unit vector in directions P1P0 and Pn-1Pn
\pstVerb{%
/PythSq { dup mul exch dup mul add } def
/PtSub {					%  xA yA xB yB
  3 -1 roll 		% xA xB yB yA
  sub neg		% xA xB yA-yB
  3 1 roll 		% yB-yA xA xB
  sub			% yB-yA xA-xB
  exch                     % xB-xA yA-yB
} def
  /xarray \the\pst@cnta\space array def
  /yarray \the\pst@cnta\space array def  
  tx@Dict begin }% end pstVerb
\multido{\i=0+1,\ib=1+1}{\the\pst@cntb}{\pnode(! \psGetCenter{\root@node\i}\space  % center on stack in system coords, not user coords
yarray \ib\space 3 -1 roll put xarray \ib\space 3 -1 roll put 0 0 ){@tmp}}% end multido
%\pstVerb{ \psGetCenter{\root@node6} == == }
\pnode(! xarray 1 get dup yarray 1 get dup 3 1 roll % x1 y1 x1 y1
xarray 2 get yarray 2 get PtSub  % x1 y1 x1-x2 y1-y2
2 copy Pyth hh div 2 div dup % x1 y1 x1-x2 y1-y2 d d ,d->d/2*hh
3 1 roll % x1 y1 x1-x2 d y1-y2 d
div 3 1 roll div %x1 y1  (y1-y2)/d (x1-x2)/d
3 1 roll %x1  (x1-x2)/d y1  (y1-y2)/d
add 3 1 roll add %  y1-(y2-y1)/d x1-(x2-x1)/d
 xarray 0 3 -1 roll put yarray 0 3 -1 roll put %stack empty
 xarray length 2 sub /topnum exch def 
 xarray topnum get dup yarray topnum get dup 3 1 roll %xn yn xn yn
topnum 1 sub /topnum exch def xarray topnum get yarray topnum get % xn yn xn yn x(n-1) y(n-1)
3 -1 roll sub  neg 3 1 roll sub exch % xn yn (xn-x(n-1)) (yn-y(n-1))
2 copy Pyth hh div 2 div dup % xn yn (xn-x(n-1)) (yn-y(n-1)) d d (d->d/(2*h))
3 1 roll div 3 1 roll div %xn yn (xn-x(n-1))/d (yn-y(n-1))/d
3 -1 roll add 3 1 roll % y(n+1) x(n+1)
topnum 2 add /topnum exch def xarray topnum 3 -1 roll put yarray topnum 3 -1 roll put % empty
% next step--find first index outside circle of radius hh 
 /oldcindex \the\pst@cntc\space 1 add def %position in array
 xarray oldcindex get /xc exch def yarray oldcindex get /yc exch def
 %hh .05 sub /hh exch def % that's close enough for a crossing
/inc \inc\space def %+1 for left facing arrow, else -1 
/cindex oldcindex def 
{cindex inc add /cindex exch def xarray cindex get xc sub yarray cindex get yc sub Pyth dup hh1 gt 
{ exit } if } loop % exit from loop with cindex the first index of an external point--dist on stack
 hh1 .1 add lt { xarray cindex get yarray cindex get } %else within segment
{ xarray cindex inc sub get dup yarray cindex inc sub get dup 4 -1 roll exch 
xarray cindex get yarray cindex get PtSub /dy1 exch def /dx1 exch def dx1 dy1 PythSq /Aterm exch def 
% dx1=x(n-1)-x(n), dy1=y(n-1)-y(n) [if inc=1]: dx1=x(n+1)-x(n), dy1=y(n+1)-y(n) [if inc=-1]
% x(n-inc) y(n-inc),  Aterm=dx1^2+dy1^2
 2 copy xc yc PtSub % x(n-inc) y(n-inc) (x(n-inc)-xc) (y(n-inc)-yc)
 2 copy 2 copy 3 -1 roll mul 3 1 roll mul add hh dup mul sub % x(n-inc) y(n-inc) (y(n-inc)-yc) (x(n-inc)-xc) (x(n-inc)-xc)^2+(y(n-inc)-yc)^2-hh^2
 Aterm div /Cterm exch def  % x(n-inc) y(n-inc)  (y(n-inc)-yc) (x(n-inc)-xc) , Cterm=((x(n-inc)-xc)^2+(y(n-inc)-yc)^2-hh^2)/(Aterm) (<0)
 dx1 dy1 %  x(n-inc) y(n-inc) (y(n-inc)-yc)  (x(n-inc)-xc)  dx1 dy1
 4 1 roll mul 3 1 roll mul add Aterm div /Bterm exch def %   x(n-inc) y(n-inc) , Bterm=( (x(n-inc)-xc)*dx1+(y(n-inc)-yc)*dy1)/Aterm
 Bterm abs neg dup dup mul Cterm sub sqrt add dup /tval exch def
% x(n-inc) y(n-inc) tvalue
 dup dx1 dy1 4 1 roll mul 3 1 roll mul  % x(n-inc) y(n-inc) t*dx1 t*dy1
 PtSub } ifelse % x y screen coords of arrow notch now on stack---convert to user x y
 \pst@number\psyunit div exch \pst@number\psxunit div exch  %use coords now on stack
){#4}\fi%
\pstVerb { end } %tx@Dict
}\ignorespaces}%
%
\def\saveDataAsNodes#1#2{%  Filename NodePrefix
  \psLoopIndex=0\relax
  \typeout{Open file #1}%
  \openin7=#1
  \loop
    \read7 to \@Data
    \ifeof7\else
      \ifx\@Data\@empty
      \else
        \pnode(!\@Data){#2\the\psLoopIndex}%
        \typeout{#2\the\psLoopIndex -> \@Data}%
	\advance\psLoopIndex by 1
        \let\@oldData\@Data
      \fi
  \repeat
  \closein7
  \advance\psLoopIndex by -1
  \pnode(!\@oldData){#2Last}%  
}
%
\catcode`\@=\TheAtCode\relax
\endinput
%%
%% END pst-node.tex
