%% xynecula.tex from $Id: xynecula.doc,v 3.4 2011/03/14 20:14:00 krisrose Exp $
%%
%% Xy-pic ``Necula extensions'' option.
%% Copyright (c) 1998 George C. Necula <necula@cs.cmu.edu>
%%
%% This file is part of the Xy-pic package for graphs and diagrams in TeX.
%% See the companion README and INSTALL files for further information.
%% Copyright (c) 1991-2011 Kristoffer H. Rose <krisrose@tug.org>
%%
%% The Xy-pic package is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by the
%% Free Software Foundation; either version 2 of the License, or (at your
%% option) any later version.
%%
%% The Xy-pic package is distributed in the hope that it will be useful, but
%% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
%% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
%% for more details.
%%
%% You should have received a copy of the GNU General Public License along
%% with this package; if not, see http://www.gnu.org/licenses/.
%%
\ifx\xyloaded\undefined \input xy \fi
\xyprovide{necula}{Necula's extensions}{\stripRCS$Revision: 3.4 $}%
 {George C. Necula}{necula@cs.cmu.edu}%
 {School of Computer Science,
 Carnegie Mellon University,
 5000 Forbes Avenue,
 Pittsburgh, PA 15213-3891, USA}
\def\expandbeforenext@#1{%
 \DN@ e|##1|{\edef\tmp@{##1}\expandafter\xyFN@\expandafter#1\tmp@}%
}
\xylet@\xy@oldOBJECT@=\OBJECT@
\xydef@\xy@newOBJECT@{%
 \ifx \space@\next \expandafter\DN@\space{\xyFN@\xy@newOBJECT@}%
 \else\ifx e\next
 \expandbeforenext@\OBJECT@
 \else
 \DN@{\xy@oldOBJECT@}\fi\fi
 \next@}%
\let\OBJECT@=\xy@newOBJECT@
\xylet@\xy@oldCOORD@=\COORD@
\xydef@\xy@newCOORD@{%
 \ifx \space@\next \expandafter\DN@\space{\xyFN@\xy@newCOORD@}%
 \else\ifx e\next
 \expandbeforenext@\COORD@
 \else
 \DN@{\xy@oldCOORD@}\fi\fi
 \next@}%
\let\COORD@=\xy@newCOORD@
\xydefcsname@{*stylechar@P@}#1{\Pshape@#1@}
\xynew@{count}\c@poly@count \c@poly@count=\z@
\xydef@\Pshape@:#1@{%
 \addtotoks@{%
 \def\poly@list{@}%
 \poly@parse #1,\relax,%Sets the poly@list
 \def\poly@cache{}%
 \edef\poly@id{\the\c@poly@count}%
 \global\advance\c@poly@count\@ne
 \poly@setEdge
 \edef\poly@saveLcshape{\the\L@c}%
 \polygonEdge@Outer% Set U,R,D,L
 \poly@setEdge
 \dimen@=\poly@saveLcshape\advance\dimen@-\L@c
 \advance\R@p -\dimen@
}}
\xydef@\poly@setEdge{\expandafter\poly@setEdge@\poly@list\poly@id}
\xydef@\poly@setEdge@#1@#2{\Edge@c={\polygonEdge#1@#2@}%
 \expandafter\xdef\csname poly@cache#2%
 \endcsname{\poly@cache}}
\xydefcsname@{frm[P]{-}}{\expandafter\draw@polyframe\the\Edge@c{-}}
\xydefcsname@{frm[P]{.}}{\expandafter\draw@polyframe\the\Edge@c{.}}
\xydefcsname@{frm[P]{=}}{\expandafter\draw@polyframe\the\Edge@c{=}}
\xydef@\draw@polyframe\polygonEdge#1@#2@#3{%
 \def\poly@dir{#3}%
 \def\poly@list{#1@}%
 \def\poly@id{#2}%
 \edef\poly@cache{\csname poly@cache\poly@id\endcsname}%
 \draw@polygon}
\xydef@\poly@empty{}
\xydef@\poly@map#1#2,#3;#4@{%
 #1{#2}{#3}%
 \def\tmp@{#4}%
 \ifx \poly@empty\tmp@ \else
 \poly@map@next#1#4@%
 \fi
}
\xydef@\poly@map@stop#1@{}
\xydef@\poly@mapExpand#1#2{%
 \edef\tmp@{\noexpand\poly@map\noexpand #1#2}%
 \tmp@}
\xydef@\poly@parse #1,{%
 \ifx #1\relax
 \poly@close
 \let\next@=\relax
 \else
 \save@
 \POS #1%
 \edef\tmp@{{\the\X@c}{\the\Y@c}}%
 \expandafter\poly@append\tmp@
 \restore
 \let\next@=\poly@parse
 \fi
 \next@
}
\xydef@\poly@append#1#2{\expandafter\poly@append@\poly@list{#1,#2;}}
\xydef@\poly@append@#1@#2{\global\def\poly@list{#1#2@}}
\xydef@\poly@close{\expandafter\poly@close@\poly@list}
\xydef@\poly@close@#1,#2;#3@{\poly@append{#1}{#2}}
\xydef@\draw@polygon{%
 \save@
 \X@origin=\X@c \Y@origin=\Y@c
 \poly@setp
 \U@c=\z@\R@c=\z@\D@c=\z@\L@c=\z@\U@p=\z@\R@p=\z@\D@p=\z@\L@p=\z@
 \Edge@c={\zeroEdge}\Edge@p={\zeroEdge}%
 \let\poly@map@next=\poly@map
 \poly@mapExpand\poly@drawseg\poly@rest
 \restore
}
\xydef@\poly@setp{\expandafter\poly@setp@\poly@list}
\xydef@\poly@setp@#1,#2;#3@{%
 \X@p=#1\advance\X@p\X@origin \Y@p=#2\advance\Y@p\Y@origin%
 \global\def\poly@rest{#3@}}
\xydef@\poly@drawseg#1#2{%
 \dimen@=#1\X@c=\the\dimen@\advance\X@c \X@origin
 \dimen@=#2\Y@c=\the\dimen@\advance\Y@c \Y@origin
 \expandafter\connect@\expandafter\dir\poly@dir%
 \X@p=\X@c\Y@p=\Y@c}
\xydef@\polygonEdge#1@#2@#3{%
 \def\poly@list{#1@}%
 \def\poly@id{#2}%
 \edef\poly@cache{\csname poly@cache\poly@id\endcsname}%
 \ifcase#3\relax
 \DN@{\polygonEdge@Inters
 }%
 \or \DN@{\polygonEdge@Under}%
 \or \DN@{\polygonEdge@Dist}%
 \or \DN@{\rectangleProp@}%
 \or \DN@{\polygonEdge@Inner}%
 \or \DN@{\polygonEdge@Outer}%
 \else \DN@{}\fi
 \next@}
\newif\ifpoly@badinters
\xydef@\polygonEdge@Inters{%
 \ifx\poly@cache\poly@empty
 \poly@intersdoit
 \else
 \expandafter\poly@intersprobecache\poly@cache @%
 \fi
}
\xydef@\poly@cachehit#1#2{%
 \X@c=#1\Y@c=#2}
\xydef@\poly@cachehitdisable#1#2{\poly@intersdoit}
\xydef@\poly@intersprobecache#1,#2,#3,#4,#5@{%
 \dimen@=#1\advance\dimen@-\d@X
 \ifdim\zz@\dimen@
 \dimen@=#2\advance\dimen@-\d@Y
 \ifdim\zz@\dimen@
 \poly@cachehit{#3}{#4}
 \else
 \poly@intersdoit
 \fi
 \else
 \poly@intersdoit
 \fi
}
\xydef@\poly@intersdoit{%
 \edef\polyoldA@{\the\A@}\edef\polyoldB@{\the\B@}%
 \def\poly@intersneg{}\def\poly@interspos{}%
 \save@
 \poly@setorigin
 \def\zeroDivide@{\poly@badinterstrue}%
 \let\poly@map@next=\poly@map
 \poly@mapExpand\poly@interseg\poly@rest
 \ifx\poly@intersneg\poly@empty
 \poly@badinterstrue
 \else
 \ifx\poly@interspos\poly@empty
 \poly@badinterstrue
 \else
 \poly@badintersfalse
 \fi
 \fi
 \restore
 \A@=\polyoldA@\B@=\polyoldB@
 \ifpoly@badinters \else
 \edef\tmp@{\poly@interspos,\poly@intersneg @}%
 \expandafter\poly@intersfinish\tmp@
 \fi
}
\xydef@\poly@intersfinish#1,#2,#3@{%
 \X@c=#1\Y@c=#2\relax
 \xdef\poly@cache{\the\d@X,\the\d@Y,#1,#2,#3}%
 \poly@setEdge
}
\xydef@\poly@setorigin{\expandafter\poly@setorigin@\poly@list}
\xydef@\poly@setorigin@#1,#2;#3@{%
 \X@origin=#1\advance\X@origin\X@c \Y@origin=#2\advance\Y@origin\Y@c%
 \global\def\poly@rest{#3@}}
\xydef@\poly@interseg#1#2{%
 \dimen@=#1\advance\dimen@\X@c \edef\poly@saveXcinters{\the\dimen@}%
 \dimen@=#2\advance\dimen@\Y@c \edef\poly@saveYcinters{\the\dimen@}%
 \save@
 \poly@badintersfalse
 \R@c=\poly@saveXcinters \advance\R@c -\X@origin
 \U@c=\poly@saveYcinters \advance\U@c -\Y@origin
 \intersect@
 \A@=\X@c \B@=\Y@c
 \restore
 \ifpoly@badinters
 \else
\poly@isonseg\X@origin\Y@origin\A@\B@\poly@saveXcinters\poly@saveYcinters
 \ifpoly@badinters
 \else
 \poly@isonray\X@c\Y@c\A@\B@\X@p\Y@p
 \ifpoly@badinters
 \edef\poly@intersneg{\the\A@,\the\B@}%
 \else
 \edef\poly@interspos{\the\A@,\the\B@}%
 \fi
 \fi
 \fi
 \X@origin=\poly@saveXcinters\Y@origin=\poly@saveYcinters
}
\xydef@\polygonEdge@Dist{\xyerror@{Dist is not yet implemented for polygons}}
\newif\ifpoly@closedrange
\xydef@\poly@isinrange#1#2#3{%
 \ifpoly@badinters \else
 \dimen@=#1\dimen@i=#2\dimen@ii=#3\relax
 \advance\dimen@ii -\dimen@ \advance\dimen@i -\dimen@
 \ifdim\dimen@ii<0pt\relax
 \ifdim\dimen@i>100\almostz@
 \poly@badinterstrue
 \fi
 \dimen@i=-\dimen@i \dimen@ii=-\dimen@ii
 \else
 \ifdim\dimen@i<-100\almostz@\relax
 \poly@badinterstrue
 \fi
 \fi
 \ifpoly@closedrange
 \advance\dimen@ii 100\almostz@
 \ifdim\dimen@i>\dimen@ii
 \poly@badinterstrue
 \fi
 \fi
 \fi}
\xydef@\poly@isonseg#1#2#3#4#5#6{%
 \poly@closedrangetrue
 \poly@isinrange{#1}{#3}{#5}%
 \poly@isinrange{#2}{#4}{#6}%
}
\xydef@\poly@isonray#1#2#3#4#5#6{%
 \poly@closedrangefalse
 \poly@isinrange{#1}{#3}{#5}%
 \poly@isinrange{#2}{#4}{#6}%
}
\xydef@\polygonEdge@Under{%
 \edef\polysaveA@under{\the\A@}\edef\polysaveB@under{\the\B@}%
 \edef\poly@saveXcUnder{\the\X@c}\edef\poly@saveYcUnder{\the\Y@c}%
 \polygonEdge@Inters
 \ifpoly@badinters% p is very close to c
 \Inside@true
 \else
 \A@=\X@c\B@=\Y@c
 \X@c=\poly@saveXcUnder\Y@c=\poly@saveYcUnder
 \poly@isonseg\X@c\Y@c\X@p\Y@p\A@\B@
 \ifpoly@badinters \Inside@false \else \Inside@true\fi
 \A@=\polysaveA@under\B@=\poly@saveB@under
 \fi
}
\xydef@\polygonEdge@Inner{%
 \enter@{\basefromthebase@ \pfromthep@ \DirectionfromtheDirection@}%
 \L@c=\X@c \D@c=\Y@c
 \polygonEdge@Inters
 \ifpoly@badinters
 \czeroEdge@
 \else
 \expandafter\poly@getinterspoints\poly@cache @%
 \ifdim\X@c>\R@c
 \L@c=\R@c \R@c=\X@c
 \else
 \L@c=\X@c
 \fi
 \X@c=0.5\L@c \advance\X@c 0.5\R@c \advance\R@c -\X@c \L@c=\R@c
 \ifdim\Y@c>\U@c
 \D@c=\U@c \U@c=\Y@c
 \else
 \D@c=\Y@c
 \fi
 \Y@c=0.5\D@c \advance\Y@c 0.5\U@c \advance\U@c -\Y@c \D@c=\U@c
 \Edge@c={\rectangleEdge}%
 \fi
 \leave@
}
\xydef@\poly@getinterspoints#1,#2,#3,#4,#5,#6@{%
 \R@c=#3\U@c=#4\X@c=#5\Y@c=#6}
\xydef@\polygonEdge@Outer{%
 \enter@{\basefromthebase@ \pfromthep@ \DirectionfromtheDirection@}%
 \czeroEdge@
 \let\poly@map@next=\poly@map
 \poly@mapExpand\poly@findextent\poly@list
 \Edge@c={\rectangleEdge}%
 \leave@
}
\xydef@\poly@findextent#1#2{%
 \dimen@=#1\dimen@=\the\dimen@% it fails if I remove the second assign
 \ifdim\dimen@>\R@c \R@c=\dimen@ \fi
 \ifdim -\dimen@>\L@c \L@c=-\dimen@ \fi
 \dimen@=#2\dimen@=\the\dimen@% it fails if I remove the second assign
 \ifdim\dimen@>\U@c \U@c=\dimen@ \fi
 \ifdim -\dimen@>\D@c \D@c=-\dimen@ \fi
}
\xydef@\Fshape@#1:{\def\whichframe@@{{#1}}\let\whichoptions@@=\empty
 \DN@{{}}\ifx\whichframe@@\next@ \def\whichframe@@{{-}}\fi
 \expandafter\xyFN@\expandafter\Fshape@whichframe\the\Edge@c}
\xydef@\Fshape@whichframe{%
 \ifx\next\circleEdge
 \edef\whichframe@@{[o]\whichframe@@}%
 \DN@##1{\xyFN@\Fshape@i}%
 \else
 \ifx\next\polygonEdge
 \edef\whichframe@@{[P]\whichframe@@}%
 \DN@\polygonEdge##1@##2@{\xyFN@\Fshape@i}%
 \else
 \DN@##1{\xyFN@\Fshape@i}%
 \fi\fi
 \next@
}
\xyendinput
