diff options
Diffstat (limited to 'Master/texmf-dist/source/generic/xypic/xycurve.doc')
-rw-r--r-- | Master/texmf-dist/source/generic/xypic/xycurve.doc | 4920 |
1 files changed, 0 insertions, 4920 deletions
diff --git a/Master/texmf-dist/source/generic/xypic/xycurve.doc b/Master/texmf-dist/source/generic/xypic/xycurve.doc deleted file mode 100644 index 0c14745e7c0..00000000000 --- a/Master/texmf-dist/source/generic/xypic/xycurve.doc +++ /dev/null @@ -1,4920 +0,0 @@ -%% $Id: xycurve.doc,v 3.7 1999/02/16 15:12:50 krisrose Exp $ -%% -%% Xy-pic ``Curves and Splines'' extension. -%% Copyright (c) 1993-1997 Ross Moore <ross@mpce.mq.edu.au> -%% -%% 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-1997 Kristoffer H. Rose <krisrose@ens-lyon.fr> -%% -%% 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, write to the Free Software Foundation, Inc., -%% 675 Mass Ave, Cambridge, MA 02139, USA. -%% -\ifx\xyloaded\undefined \input xy \fi - -\xyprovide{curve}{Curve and Spline extension}{\stripRCS$Revision: 3.7 $}% - {Ross Moore}{ross@mpce.mq.edu.au}% - {Mathematics Department, Macquarie University, NSW~2109, Australia} - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -This option provides \Xy-pic with the ability to typeset spline curves -by constructing curved connections using arbitrary directional objects -and by encircling objects similarly. "Warning": Using curves can be -quite a strain on \TeX's memory; you should therefore limit the length -and number of curves used on a single page. Memory use is less when -combined with a backend capable of producing its own curves; \eg, the -\PS\ backend). - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\paragraph*{Header:}\leavevmode -\DOCHEADER -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsection{Curved connections} -??=[curved connections] - -\DOCMODE( -\message{curve,} -\DOCMODE) - - Simple ways to specify curves in \Xy-pic are as follows: - \begin{defs} -|**\crv{|<poslist>|}| & curved connection \cr -|**\crvs{|<dir>|}| & get <poslist> from the stack \cr -|\curve{|<poslist>|}| & as a <decor>ation \cr - \end{defs} -\noindent\unskip - in which <poslist> is a list of valid <pos>itions. - The decoration form |\curve| is just an abbreviation for |\connect\crv|. - As usual, the current $p$ and $c$ - are used as the start and finish of the connection, respectively. - Within <poslist> the <pos>itions are separated by |&|. -A full description of the syntax for |\crv| is given in figure~??[f.curve]. - -\begin{code} -\xy (0,20)*[o]+{A};(60,0)*[o]+{B}="B" -**\crv{}\POS?(.4)*_+!UR{0},"B" -**\crv{(30,30)}\POS?*^+!D{1},"B" -**\crv{(20,40)&(40,40)} \POS?*^+!D{2},"B" -**\crv{(10,20)&(30,20)&(50,-20)&(60,-10)} -\POS?*+^!UR{4} \endxy -\end{code} -$$\docode$$\goodbreak\goodbreak - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -We need a counter to track the number of control points, (i.e. the number of -<pos>s in <poslist>) and provide a macro to read it. -Also a token list which will store the vital information for -later use, to allow curved connections to work properly. - -\DOCMODE( -\xynew@{count}\crv@cnt@ -\xydef@\xynumctrlpts@{\the\crv@cnt@} -\xynew@{toks}\crvpts@ -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -If <poslist> is empty a straight connection is computed. -When the length of <poslist> is one or two then the curve is uniquely -determined as a single-segment B\'ezier quadratic or cubic spline. -The tangents at $p$ and $c$ are along the lines connecting -with the adjacent control point. -With three or more <pos>itions a cubic B-spline construction is used. -B\'ezier cubic segments are calculated from the given control points. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\setcurve@{% - \edef\xysplineparams@{% - \expandafter\noexpand\csname params@\endcsname}% - \edef\xysplineedges@{% - \expandafter\noexpand\csname edges@\endcsname}% - \edef\xycrvcnt@{% - \expandafter\noexpand\csname crvcnt@\endcsname}% - \expandafter\edef\xycrvcnt@{\number\crv@cnt@}% - \ifcase\crv@cnt@ - \expandafter\xycvxhull@\or - \expandafter\xyquadbezier@\or - \expandafter\xycubicbezier@\or - \expandafter\xybspline@iii\or - \expandafter\xybspline@iv\else - \expandafter\xybspline@ - \fi} -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The previous picture was typeset using: -\begin{code} -\xy (0,20)*+{A};(60,0)*+{B} -**\crv{} -**\crv{(30,30)} -**\crv{(20,40)&(40,40)} -**\crv{(10,20)&(30,20)&(50,-20)&(60,-10)} -\endxy -\end{code} -\displaycode -\noindent except for the labels, which denote the number of entries in the -<poslist>. (Extending this code to include the labels is set below as -an exercise). - -\begin{code} -\xy (0,20)*[o]+{A};(60,0)*[o]+{B}="B" -**\crv{} \POS?(.4)*_+!UR{0},"B" -**\crv{(30,30)} \POS?*^+!D{1},"B" -**\crv{(20,40)&(40,40)} \POS?*^+!D{2},"B" -**\crv{(10,20)&(30,20)&(50,-20)&(60,-10)} -\POS?*+^!UR{4} \endxy -\end{code} - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - The |?|-operator of \S??g[xy.doc:pos] (note~??g[xy.doc:<place>]) - is used to find arbitrary <place>s along a curve in the usual way. - -\begin{exercise} -Extend the code given for the curves in the previous picture -so as to add the labels giving the number of control points. -\answertext{This is the code that was actually used:} -\answercode -\answertext\displaycode -\end{exercise} - - Using |?| will set the current direction to be tangential at that - <place>, and one can <slide> specified distances - along the curve from a found <place> using the |?|\dots|/|<dimen>|/| - notation: - -\begin{code} -\xy (0,20)*+{A};(60,0)*+{B} -**\crv{(10,20)&(30,20)&(50,-20)&(60,-10)} - ?<*\dir{<} ?>*\dir{>} - ?(.65)*{\oplus} *!LD!/^-5pt/{x} - ?(.65)/12pt/*{\oplus} *!LD!/^-5pt/{x'} - ?(.28)*=0{\otimes}-/40pt/*+{Q}="q" - +/100pt/*+{P};"q" **\dir{-} -\endxy -\end{code} - -$$\docode$$ - -\begin{exercise} -Suggest code to produce something like the above picture; -the spline curve is the same as in the previous picture. -"Hints": The line is 140pt long and touches $0.28$ of the way from -$A$ to $B$ and the $x$ is 0.65 of the way from $A$ to $B$. -\answertext{This is the code that was used to typeset the picture:} -\answercode -\answertext\displaycode -\end{exercise} - - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The positions in <poslist> specify -{\em control points\/} which determine the initial and final directions -of the curve---leaving $p$ and arriving at $c$---and how the curve -behaves in between, using standard spline constructions. -In general, control points need not lie upon the actual curve. - -A natural spline parameter varies in the interval $[0,1]$ monotonically -along the curve from $p$ to $c$. This is used to specify <place>s along -the curve, however there is no easy relation to arc-length. -Generally the parameter varies more rapidly where the curvature is -greatest. The following diagram illustrates this effect for a cubic -spline of two segments (3 control points). - -\begin{code} -\def\ssz#1{\hbox{$_{^{#1}}$}} -\xy (0,0)*+{A};(30,-10)*+{B}="B",**\dir{-}, -"B"**\crv{(5,20)&(20,25)&(35,20)} - ?<(0)*\dir{<}="a" ?>(1)*\dir{>}="h" - ?(.1)*\dir{<}="b" ?(.9)*\dir{>}="i" - ?(.2)*\dir{<}="c" ?(.8)*\dir{>}="j" - ?(.3)*\dir{<}="d" ?(.7)*\dir{>}="k" - ?(.4)*\dir{<}="e" ?(.6)*\dir{>}="l" - ?(.5)*\dir{|}="f", - "a"*!RC\txt{\ssz{(\lt)}}; - "h"*!LC\txt{\ssz{\;(\gt)}},**\dir{.}, - "b"*!RD{\ssz{.1}}; - "i"*!L{\ssz{\;.9}},**\dir{-}, - "c"*!RD{\ssz{.2}}; - "j"*!L{\ssz{\;.8}},**\dir{-}, - "d"*!RD{\ssz{.3}}; - "k"*!L{\ssz{\;.7}},**\dir{-}, - "e"*!RD{\ssz{.4}}; - "l"*!LD{\ssz{.6}},**\dir{-}, - "f"*!D!/^-3pt/{\ssz{.5}} -\endxy -\end{code} -$$\docode$$ - -\begin{exercise} -Write code to produce a picture such as the one above. -("Hint": Save the locations of places along the curve for later -use with straight connections.) -\answertext{Here is the code that was used to typeset the picture:} -\answercode -\answertext\displaycode -\end{exercise} - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -To have the same <pos> occuring as a multiple control point simply use -a delimiter, which leaves the <pos> unchanged. Thus -|\curve{|<pos>|&}| uses a cubic spline, whereas |\curve{|<pos>|}| is -quadratic. - -Repeating the same control point three times in succession results in -straight segments to that control point. Using the default styles this -is an expensive way to get straight lines, but it allows for extra -effects with other styles. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Curve Objects:} - -At present the syntax is supported for using a |\curve| object only -as a decoration, constructed from a |\crv| object used as a connection. - -\DOCMODE( -\xydef@\curve{\connect\crv} -\DOCMODE) - -The more general |\crv| object currently works as a connection. -In future this object-type will be extended to allow closed curves as -the boundaries of objects. - -\DOCMODE( -\xydef@\crv#1#{\hbox \bgroup \crvresetbreaks@ \initshape@ - \def\pure@crv{\crv@saveStyles@}\crv@{#1}} - -\xydef@\crv@#1#2{% - \DN@{#1}\ifx\empty\next@ - \DN@{\def\afterCURVEaction@{}\parsecurve@\xycurve@@}% - \else\DN@{\parseCURVE@#1\parsecurve@\curveSTYLE@}\fi - \next@ #2\@endcurve\endcrv@ } - -\xydef@\curveSTYLE@{\xycurve@@}% default style -\xydef@\afterCURVEaction@{}% default after-curve action -\xydef@\@endcurve{}% -\xydef@\endcrv@@{\endcrv@\POS}% -\xydef@\pure@crv{\relax} -\DOCMODE) - - The |\@endcurve| inserted here ensures that subsequent parsing - with |\checkendcurve@| (see below) will terminate cleanly. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The |\crvs| object has restricted functionality with choice of styles and -is always used for curves only. -It has a single braced argument which can be used to set curve styles. -Its main use is for re-typesetting different portions of the same curve, -for example the subsegments of a curved arrow/path segment. - -This is done by first examinining |\bstartPLACE@|. -If |\relax| or undefined, then the curve is set using |\@crv@| to -decide the style. If |\bstartPLACE@| is |\empty| then the curve is fully -processed as a connection but nothing is actually typeset; this is used -by curved arrows where the curve is first set as ``invisible'' before -breaks and labels are processed. -When |\bstartPLACE@| contains a number, normally within the range 0 to 1, -this is interpreted as a <place> along a curved connection that has already -been established. No typesetting may occur before this <place>. - -In this case the control point information is discarded since the curve -can be recovered using |\splinereset@|. The current $p$ and $c$ are no -longer the endpoints of the curve but are <pos>itions along the curve -between which the typesetting should occur. -The value of |\bstartPLACE@| is typically a <place> along the curve -which is within the <pos> at $p$. It is used to help locate the edge of -this <pos> where typesetting should commence. -Similarly |\bendPLACE@| is typically a <place> along the curve -which is within the <pos> at $c$. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xywarnifdefined\crv@normaltemplate -\xywarnifdefined\crv@othertemplate -\xywarnifdefined\crv@specialtemplate@@ -{\xyuncatcodes \catcode`\@=11 \catcode`\#=6 - \gdef\crv@normaltemplate#1{{}{~**#1\xy@@crvaddstack@}} - \gdef\crv@othertemplate#1{{}{~*=<2\jot>{}~**#1\xy@@crvaddstack@}} - \gdef\crv@specialtemplate@@#1{{}{~**\dir{#1}\xy@@crvaddstack@}} -} - -\xydef@\crvs#1#{\hbox \bgroup \def\pure@crv{\relax}\crvs@{#1}}% -\xydef@\crvi#1#{\hbox \bgroup \def\pure@crv{\relax}\invisbreaks@ \crvs@{#1}}% - -\xydef@\crvs@#1{\DN@{\initshape@ \@crv@{#1}}% - \def\crv@defaultshape{-}% - \ifx\bstartPLACE@\relax \else - \ifx\bstartPLACE@\empty \Invisible@true \else -\splinetrace@{bstartPLACE@=\bstartPLACE@, bendPLACE@=\bendPLACE@}% - \DN@{\let\xy@@crvaddstack@=\xy@@samecurve@ - \let\saveshape@=\savesame@ - \let\savectrlptsnum@=\relax - \let\startxycurve@=\recovercurve@ - \crv@cnt@=\xycrvptsnum@\relax \@crv@{#1}}% - \fi \fi \next@ } - - - -\xydef@\xy@@samecurve@{\xyFN@\checkendcurve@} -\xydef@\savesame@{\egroup } -\xydef@\recovercurve@{% - \crv@cnt@=\xycrvptsnum@ \splinereset@ \recovercv@end - \ifx\bendPLACE@\relax \def\bendPLACE@{1}\fi - \ifdim\zz@\R@c \ifdim\zz@\L@c \ifdim\zz@\D@c \ifdim\zz@\U@c - \Edge@c={\zeroEdge}\fi\fi\fi\fi - \edef\cv@end{\cfromthec@}\edef\cv@start{\cfromthep@}} - -\xydef@\recovercv@end{\count@=\ptsnum@\relax\advance\count@\@ne - \edef\tmp@{\the\count@}\csname cv@\tmp@\endcsname}% - -\xydef@\crvSTYLE@@{} -\expandafter\xydef@\expandafter\crv@defaultshape\expandafter{\addDASH@{}} -\xydef@\crv@noobject{\Invisible@true} - -\xydef@\@crv@#1#2{\DN@{#1#2}% - \ifx\next@\empty \edef\next@{\crv@defaultshape}% - \ifx\bstartPLACE@\empty \xdef\crvSTYLE@@{{\crv@defaultshape}}\fi - \else - \ifx\bstartPLACE@\empty \gdef\crvSTYLE@@{#1{#2}}\fi - \fi - \ifx\next@\empty \crv@noobject \DN@{\crv@{}{\xy@@crvaddstack@}}% - \else\def\tmp@{-}\ifx\next@\tmp@ \DN@{\crv@{}{\xy@@crvaddstack@}}% - \else\def\tmp@{=}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir{=}}}% - \else\def\tmp@{2-}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir{2.}}}% - \else\def\tmp@{3-}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir{3.}}}% - \else\def\tmp@{--}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@specialtemplate@{--}}% - \else\def\tmp@{==}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir2{--}}}% - \else\def\tmp@{2--}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir2{--}}}% - \else\def\tmp@{3--}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir3{--}}}% - \else\def\tmp@{.}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@specialtemplate@{.}}% - \else\def\tmp@{:}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir{:}}}% - \else\def\tmp@{2.}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@normaltemplate{\dir{:}}}% - \else\def\tmp@{..}\ifx\next@\tmp@ - \DN@{\expandafter\crv@\crv@specialtemplate@{.}}% - \else - \DN@{\expandafter\crv@\crv@othertemplate{\dir#1{#2}}}% - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next@} - -\xylet@\crv@specialtemplate@=\crv@specialtemplate@@ -\xydef@\crv@special#1{} -\DOCMODE) - -\BUG: this should use a |\Step@@| method to get the spacing for dotting; this -will eliminate the need for templates\dots - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\begin{figure*}[tp] -\begin{syntax} -% - \multispan{3}{{\tt\string\curve}<modifier>|{|<curve-object><poslist>|}|\hfil} - & construct curved connection -\cr -% -\noalign{\nobreak\smallskip\nobreak\hrule\nobreak\smallskip\nobreak} -% - <modifier> - &\iss & <empty> - & zero or more modifiers possible; default is |~C| -\cr - &\orr & |~|<curve-option> <modifier> - & set <curve-option> -\cr -% -\noalign{\smallskip} -% - <curve-option> - &\iss & |p|\orr|P|\orr|l|\orr|L|\orr|c|\orr|C| - & ??!^[show only] control points (|p|=points), - joined by lines (|l|=lines), or curve only (|c|=curve) -\cr -% - &\orr & |pc|\orr|pC|\orr|Pc|\orr|PC| - & show ??!^[control points] ??!^[and curve] -\cr -% - &\orr & |lc|\orr|lC|\orr|Lc|\orr|LC| - & show ??!^[lines joining] control points ??!^[and curve] -\cr -% - &\orr & |cC| - & plot curve twice, with and without specified formatting -\cr -% -\noalign{\smallskip} -% - <curve-object> - &\iss & <empty> - & use the appropriate default style -\cr -% - & \orr & |~*|<object> <curve-object> - & specify the ??!^[``drop'' object] and ??!^[maybe more] -\cr -% - & \orr & |~**|<object> <curve-object> - & specify ??!^[``connect'' object] and ??!^[maybe more] -\cr -% -\noalign{\smallskip} -% - <poslist> - &\iss & <empty> \orr\ <pos> <delim> <poslist>\kern-15pt - & \kern20pt list of positions for control points -\cr -% - &\orr & |~@| \orr\ |~@| <delim> <poslist> - & add the current ??!^[stack] to the control points -\cr -% -\noalign{\smallskip} -% - <delim> - & \iss & {\tt\&} - & allowable delimiter -\cr -% -\end{syntax} -\caption{Syntax for curves.} -??=[f.curve] -\vfil -\end{figure*} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Parsing:} - -Two separate parsers are required: one for |\curve...|, the other for the -contents of |{...}|. - -Set |\curveSTYLE@| to be the default of |\xycurve@@| then examine -the following tokens to see if this must be changed. - - Set |\curveSTYLE@| to be the default of |\xycurve@@| then examine - the following tokens to see if this must be changed. - -"Procedure": If the first token of |#1| (from |\crv@|) is |~| then - a letter should follow, determining how to set the style. - If instead it is an active control sequence then issue - a warning message, but let it do its thing anyway. - However |\parsecurve@| is a normal thing to encounter, - so no warning is required. - Currently a single letter without the |~| will be recognised, - but two-letter combinations definitely need the |~|. - -\DOCMODE( -\xydef@\parseCURVE@{\def\curveSTYLE@{\xycurve@@}\def\afterCURVEaction@{}% - \xyFN@\parseCURVE@@} -\xydef@\parseCURVE@@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\parseCURVE@@}% gobble spaces - \else\ifx ~\next \DN@ ~{\xy@~{}\xyFN@\setcurveSTYLE@@}% - \else\ifx\parsecurve@\next\DN@{}% - \else\ifcat\active\noexpand\next\DN@{\xyactive@Warning}% - \else\ifcat a\noexpand\next\DN@##1{\xytilde@Warning\setcurveSTYLE@{##1}% - \xyFN@\parseCURVE@@}% - \else\DN@{}\fi\fi\fi\fi\fi \next@ }% -\DOCMODE) - - Options are normally specified using |~|. - Sometimes this can be safely omitted; if such a case is - encountered then a warning message is issued advising to use |~|. - This nicety may be removed in future versions. - -\DOCMODE( -\xydef@\xyactive@Warning{\xywarning@{expandable control sequences should - not be here, results are unpredictable in diagrams.}}% (2) -\xydef@\xytilde@Warning{Please use ~ to set curve style.}% (3a) -\DOCMODE) - - Examine the next token to see if it determines a curve style. - Currently only |p|, |l| and |c| are recognised, along with - the uppercase variants |P|, |L| and |C|. - When one of these letters is encountered, set |\curveSTYLE@| - and keep examining tokens with |\setafterCURVEaction@|. - -\DOCMODE( -\xydef@\setcurveSTYLE@#1{\xyFN@\setcurveSTYLE@@#1} -\xydef@\setcurveSTYLE@@{% - \ifx\next p\def\curveSTYLE@{\xyc@trlpts@@}% - \DN@ p{\xyFN@\setafterCURVEaction@}% - \else\ifx\next P\def\curveSTYLE@{\xyc@trlpts@}% - \DN@ P{\xyFN@\setafterCURVEaction@}% - \else\ifx\next l\def\curveSTYLE@{\xyc@vxhull@@}% - \DN@ l{\xyFN@\setafterCURVEaction@}% - \else\ifx\next L\def\curveSTYLE@{\xyc@vxhull@}% - \DN@ L{\xyFN@\setafterCURVEaction@}% - \else\ifx\next c\def\curveSTYLE@{\xycurve@@}% - \DN@ c{\xyFN@\setafterCURVEaction@}% - \else\ifx\next C\def\curveSTYLE@{\xycurve@@}% - \DN@ C{\xyFN@\setafterCURVEaction@}% - \else \DN@##1{\xywarning@{unknown curve style ##1}\xyFN@\parseCURVE@@}% - \fi\fi\fi\fi\fi\fi \next@ } -\DOCMODE) - - |\setafterCURVEaction@| examines tokens to see if a 2-letter - combination is being specified; e.g. |pc|, |lC|, etc. - Alternatively another |~| can set a new specification. - -\DOCMODE( -\xydef@\setafterCURVEaction@{% - \ifx\next~\DN@~{\xyFN@\setcurveSTYLE@@}% - \else\ifcat a\noexpand\next\DN@{\setafterCURVEaction@@}% - \else\DN@{\xyFN@\parseCURVE@@}% - \fi\fi \next@} -\DOCMODE) - - Currently the only 2-letter specifications have either - |c| or |C| as the 2nd letter. - -\DOCMODE( -\xydef@\setafterCURVEaction@@{% - \ifx\next c\DN@ c{% - \def\afterCURVEaction@{\noexpand\endcurve\noexpand\xy@curve@}% - \xyFN@\parseCURVE@@ }% - \else\ifx\next C\DN@ C{% - \def\afterCURVEaction@{\noexpand\endcurve\noexpand\xy@curve@@}% - \xyFN@\parseCURVE@@ }% - \else \DN@##1{\xywarning@{unknown after-curve action ##1}% - \xyFN@\parseCURVE@@ }% - \fi\fi \next@ } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - When |\parsecurve@| is encountered, this signifies the end - of this part of the parsing. The only active control - sequence that should be encountered legitimately here is - |\@endcurve|, which signifies that the <poslist> is - empty and default styles are required. Otherwise assume we - the subsequent tokens are from |#2| of |\crv@|. Control - passes to |\xycurve@@| to prepare for reading the <crv-object>s - and <poslist>. - -\DOCMODE( -\xydef@\parsecurve@{\xyFN@\parsecurve@@} -\xydef@\parsecurve@@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\parsecurve@@}% - \else\ifx\next\@endcurve\DN@\@endcurve{\checkafterCURVE@}% - \else\ifcat\active\noexpand\next\DN@{\relax}% - \else\DN@{\xycurve@@}\fi\fi\fi\next@}% -\DOCMODE) - -\DOCMODE( -\xydef@\xycurve@{\begingroup\afterCURVE{\setcurve@\endgroup}\crvobjects@ - \startxycurve@\xycrvmods@} -\xydef@\xycurve@@{\afterCURVE{\setcurve@}\crvobjects@\startxycurve@ - \xycrvmods@} -\xydef@\xy@curve@{\xy@curve@@@{\splinedefaulttol@\crvobjects@}} -\xydef@\xy@curve@@{\xy@curve@@@{\resetcrvobjects@}} -\xydef@\xy@curve@@@#1{\ifx\cv@start\relax - \DN@{\xywarning@{There is no curve to plot}}. - \else\DN@{\begingroup\afterCURVE{\setcurve@\endgroup}#1\cv@end}% - \fi \next@ } -\xydef@\crvobjects@{\def\xycrvdrop@{}\def\xycrvconn@{}} -\xydef@\resetcrvobjects@{\crvobjects@} -\DOCMODE) - - These were originally provided for sophisticated-user access. - They are otherwise undocumented and may be removed. - -\DOCMODE( -\xylet@\savecurve=\xycurve@@ -\xylet@\samecurve=\xy@curve@ -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - |\xy@crvmods@| handles reading the <curve-object>s, - \ie\ the ``drop'' object and the ``connect'' object. - -\medskip -"Procedure":??_[crvob1]~Get next token.??_[crvob2]~Is it a |~|? - ??_[crvob4]~If not, exit. -??_[crvob2a]~If so, is it followed by a |*|? -??_[crvob2b]~If not, issue a message and go back to ??_[crvob1]. - Otherwise, ??_[crvob3]~is there a second |*|? -??_[crvob3a]~If not then read and store the ``drop'' object, -??_[crvob3b]~else, read and store the ``connect'' object. -When finished, in either case, ??_[crvob5]~look for further specifications. -??_[crvob3c]~An empty ``drop'' object is not allowed, so this actually -gives the default of |\zerodot|. - -\DOCMODE( -\xydef@\xycrvmods@{\xyFN@\xy@crvmods@}%?*[crvob1] - -\xydef@\xy@crvmods@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\xy@crvmods@}%gobble spaces - \else\ifx\next ~\DN@ ~{\xyFN@\xy@crvmods@@}%?*[crvob2] - \else\DN@{\xy@crvmods@@@@}\fi\fi \next@}%?*[crvob4] -\xydef@\xy@crvmods@@@@{\xyFN@\checkendcurve@}% - -\xydef@\xy@crvmods@@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\xy@crvmods@@}%gobble spaces - \else\ifx\next *\DN@ *{\xyFN@\xy@@crvmods@}%?*[crvob2a] - \else\addAT@\ifx\next\addAT@\DN@{\xyFN@\xy@@crvaddstack}% - \else\DN@{\xywarning@{badly-formed curve option}\xyFN@\xy@crvmods@}%?*[crvob2b] - \fi\fi\fi \next@}% - -\xydef@\xy@@crvmods@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\xy@@crvmods@}%gobble spaces - \else\ifx\next *\DN@ *{\xyFN@\xy@@crvmods@@}%?*[crvob3] - \else\DN@{\xy@crv@mods@@}\fi\fi \next@}%?*[crvob3a] - -\xydef@\xy@crv@mods@@#1#{\DN@##1{\xy@crvmods@@@{#1}{##1}}\next@}% -\xydef@\xy@crvmods@@@#1#2{% - \DN@{#1#2}\ifx\next@\empty \def\xycrvdrop@{ #1{\zerodot}}%?*[crvob3c] - \else \def\xycrvdrop@{ #1{#2}}\fi - \xyFN@\xy@crvmods@ }%?*[crvob5] - -\xydef@\xy@@crvmods@@#1#{\DN@##1{\xy@@crvmods@@@{#1}{##1}}\next@}%?*[crvob3b] -\xydef@\xy@@crvmods@@@#1#2{\def\xycrvconn@{ #1{#2}}\xyFN@\xy@crvmods@ }% -\DOCMODE) -% -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Parsing of the <poslist> is quite simple, recognising few special tokens: - -\begin{itemize} -\item - |\endcurve| and |\endxy| terminate reading of control points. -\item - |&|, |\\| and |\relax| delimit $<pos>$itions -\item - anything else is treated as a $<pos>$, being handled by the |\POS@| - parser. -\end{itemize} - -\DOCMODE( -\xydef@\checkendcurve@{% - \ifx\space@\next\expandafter\DN@\space{\xyFN@\checkendcurve@}%gobble spaces - \else\ifx\next\endcurve\DN@\endcurve{\clearsearchflag@\endxycurve@}% - \else\ifx\next\@endcurve\DN@\@endcurve{\checkafterCURVE@}% - \else\ifx\next\xy@@crvaddstack@\DN@{}% - \else\ifx\next\endxy\DN@{\clearsearchflag@\sloppyendcrv@}% -% \else\addAND@\ifx\next\addAND@\DN@{\clearsearchflag@\searchnextpt@}% - \else\testAND@\iffalse \DN@##1{\clearsearchflag@\searchnextpt@}% - \else\ifx ~\next\DN@ ~{\xyFN@\checkcrvtilde@}% - \else\ifx\next\relax\DN@\relax{\clearsearchflag@\searchnextpt@}% - \else\ifx\next\\\DN@\\{\clearsearchflag@\searchnextpt@}% - \else\ifx\searchflag@\relax - \DN@{\setsearchflag@\searchnextpt@}% - \else\DN@##1{\flagwarn@{##1}}\fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi \next@ } -\xydef@\searchnextpt@{\afterPOS{\xy@@\addtocrv@ \xyFN@\checkendcurve@}} -\DOCMODE) - -There could be a problem in that an invalid token would cause -an infinite loop, passing back and forth between |\checkendcurve@| -and |\POS@|. This is avoided by setting a flag |\setsearchflag@| -when the |\POS@| parser is called, not following a valid delimiter. -Encountering a valid delimiter clears the flag. If |\checkendcurve@| -is called with the flag set, a warning message is issued -and the token is skipped; the flag remains set. -Processing continues, but it is possible that the wrong number of -positions will be read; presumably there is some kind of error that -needs to be fixed anyway. - -\DOCMODE( -\xydef@\checkafterCURVE@{% - \edef\tmp@{\noexpand\xyFN@\noexpand\checkendcurve@ % - \afterCURVEaction@\noexpand\endcurve}\tmp@ } - -\xylet@\searchflag@=\relax -\xydef@\setsearchflag@{\let\searchflag@=@} -\xydef@\clearsearchflag@{\let\searchflag@=\relax} -\xydef@\flagwarn@#1{% - \ifx\next\@endcurve\DN@{\xyFN@\checkendcurve@\endcurve}% - \else\setsearchflag@\DN@{\xyFN@\checkendcurve@}% - \xywarning@{skipping invalid token \string#1\space in curve}% - \fi \next@ } -\DOCMODE) - -It is possible for the final |\endcurve| to be omitted, but only when the -next token is |\endxy|. A warning message is written to the log file, -protesting against this sloppy \TeX-ing.\smiley - -\DOCMODE( -\xydef@\sloppyendcrv@{% -\xywarning@{Please use \string\endcurve\space to end the curve.}\endxycurve@} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - Creation of the |\crv| is completed when |\endcrv@| is encountered. - At this point the usual methods |\Drop@@| and |\Connect@@| are - defined. Extra information is retained, using |\saveshape@| and - |\savecrvparams@| for the benefit of methods which treat the curve - as a connection. - -\DOCMODE( -\xydef@\endcrv@{\saveshape@ %\def\Upness@{0}% - \Edge@c={\splineEdge}\Invisible@false\Hidden@false - \edef\Drop@@{\noexpand\ifInvisible@ \setbox\z@=\copy\voidb@x - \noexpand\else - \noexpand\wdz@=\z@ - \noexpand\ht\z@=\z@ \noexpand\dp\z@=\z@ - \noexpand\splineDrop@ - \noexpand\fi }% -% - \edef\Connect@@{% - \noexpand\setbox\z@=\noexpand\box\lastobjectbox@ - \noexpand\wdz@=\z@ - \noexpand\ht\z@=\z@ \noexpand\dp\z@=\z@ - \expandafter\noexpand\pure@crv - \noexpand\ifInvisible@ \noexpand\crv@saveStyles@ \noexpand\else - \noexpand\crv@getStyles@\noexpand\styledboxz@ \noexpand\fi -% - \noexpand\ifHidden@\noexpand\else - \noexpand\ifx\noexpand\COORD@\noexpand\xymatrixCOORD@ \noexpand\else - \noexpand\X@min=\the\X@min \noexpand\X@max=\the\X@max - \noexpand\Y@min=\the\Y@min \noexpand\Y@max=\the\Y@max - \noexpand\fi \noexpand\fi - \savecrvparams@ \noexpand\crvconnect@ %\noexpand\initbreaks@ - }% - \wdz@=\z@ - \ht\z@=\z@ \dp\z@=\z@ } -\DOCMODE) - -The control names |\crvXY@pre@| and |\crvXY@post@| are used to -transfer style information passed with |\preconnect@| to subsegments. - -\DOCMODE( -\xydef@\crvXY@pre@{} -\xydef@\crvXY@post@{} - -\xydef@\crv@saveStyles@{\def\xy@style@{}% - \expandafter\def\expandafter\crvXY@pre@\expandafter{\preXY@style@}% - \expandafter\def\expandafter\crvXY@post@\expandafter{\postXY@style@}} - -\xydef@\crv@getStyles@{\def\xy@style@{}% - \gdef\preXY@style@{\crvXY@pre@}\gdef\postXY@style@{\crvXY@post@}} -\DOCMODE) - - The values of |\X@min|, |\X@max|, \etc\ are used to compute the extents - |\L@c|, |\R@c|, \etc\ of the object. This information must be maintained - after the group is closed, unless the ``hidden'' attribute is required - or we are inside a matrix construction. - - In calculating the size of the box containing the curve |\X@min|, - |\X@max|, \etc\ are initialised to describe the minimum rectangle - enclosing $p$ and $c$. At the same time we save the current scope. - -\DOCMODE( -\xydef@\initshape@{\savescope@ - \ifdim\X@c>\X@p \X@min=\X@p \X@max=\X@c \else \X@max=\X@p \X@min=\X@c \fi - \ifdim\Y@c>\Y@p \Y@min=\Y@p \Y@max=\Y@c \else \Y@max=\Y@p \Y@min=\Y@c \fi } -\DOCMODE) - - |\saveshape| is used to pass necessary information up one level of - grouping. - -\DOCMODE( -\xydef@\saveshape@{\savectrlptsnum@ - \R@c=\X@max \advance\R@c-\X@c \L@c=\X@c \advance\L@c-\X@min - \U@c=\Y@max \advance\U@c-\Y@c \D@c=\Y@c \advance\D@c-\Y@min - \edef\tmp@{\egroup \U@c=\the\U@c \D@c=\the\D@c \L@c=\the\L@c \R@c=\the\R@c - \noexpand\ifdim\noexpand\X@min>\the\X@min\noexpand\X@min=\the\X@min\noexpand\fi - \noexpand\ifdim\noexpand\Y@min>\the\Y@min\noexpand\Y@min=\the\Y@min\noexpand\fi - \noexpand\ifdim\noexpand\X@max<\the\X@max\noexpand\X@max=\the\X@max\noexpand\fi - \noexpand\ifdim\noexpand\Y@max<\the\Y@max\noexpand\Y@max=\the\Y@max\noexpand\fi - \savecrvparams@ \def\noexpand\pure@crv{\expandafter\noexpand\pure@crv}}% - \tmp@ } - -\xydef@\savecrvparams@{\crvpts@={\the\crvpts@}% - \noexpand\def\noexpand\crvconnect@{\expandafter\noexpand\crvconnect@}}% -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\splineEdge{\rectangleEdge} -\DOCMODE) - -\TODO: -This can be improved. For example, trace along the spline until an -appropriate point is found. There may be more than one such point, -so extra criteria may be required. - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\begin{notes} - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[``drop'' object] -The ``drop'' object is set once, then ``dropped'' many times at appropriately -spaced places along the curve. If directional, the direction from $p$ to $c$ -is used. -Default behaviour is to have tiny dots spaced sufficiently closely as to -give the appearance of a smooth curve. -Specifying a larger size for the ``drop'' object is a way of getting -a dotted curve (see the example in the next note). - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[``connect'' object] -The ``connect'' object is also dropped at each place along the curve. -However, if non-empty, this object uses the tangent direction at each -place. This allows a directional object to be specified, whose -orientation will always match the tangent. To adjust the spacing of -such objects, use an empty ``drop'' object of non-zero size as shown here: -% -\begin{code} -\xy (0,0)*+{A}; (50,-10)*+{B} -**\crv{~*=<4pt>{.} (10,10)&(20,0)&(40,15)} -**\crv{~*=<8pt>{}~**!/-5pt/\dir{>}(10,-20) - &(40,-15)} \endxy -\end{code} -$$\docode$$ -\displaycode -% -\noindent -When there is no ``connect'' object then the tangent calculations -are not carried out, resulting in a saving of time and memory; -this is the default behaviour. - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[maybe more] -The ``drop'' and ``connect'' objects can be specified as many times -as desired. Only the last specification of each type will actually have -any effect. (This makes it easy to experiment with different styles.) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[show only] -Complicated diagrams having several spline curves can take quite a long time -to process and may use a lot of \TeX's memory. A convenient device, -especially while developing a picture, is to show only the location of the -control points or to join the control points with lines, as a stylized -approximation to the spline curve. The <curve-option>s |~p| and |~l| are -provided for this purpose. Uppercase versions |~P| and |~L| do the same -thing but use any <curve-object>s that may be specified, whereas the -lowercase versions use plain defaults: small cross for |~p|, straight -line for |~l|. -Similarly |~C| and |~c| set the spline curve using any -specified <curve-option>s or as a (default) plain curve. - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[and curve] -Use of |~p|, |~l|, etc. is extended to enable both the curve -and the control points to be easily shown in the same picture. -Mixing upper- and lower-case specifies whether the <curve-option>s are -to be applied to the spline curve or the (lines joining) control points. -See the examples accompanying the next two notes. - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[control points] -By default the control points are marked with a small cross, -specified by |*\dir{x}|. The ``connect'' object is ignored completely. - -\begin{code} -\xy (0,0)*+{A};(50,-10)*+{B} -**\crv~pC{~*=<\jot>{.}(10,-10)&(20,15) - &(40,15)} \endxy -\end{code} -$$\docode$$ -was typeset by \dots -\displaycode - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[lines joining] -With lines connecting control points the default ``drop'' object is empty, -while the ``connect'' object is |\dir{-}| for simple straight lines. -If non-empty, the ``drop'' object is placed at each control point. -The ``connect'' object may be used to specify a fancy line style. - -\begin{code} -\xy (0,0)*+{A};(50,-10)*+{B} -**\crv~Lc{~**\dir{--}~*{\oplus} - (20,20)&(35,15)} \endxy -\end{code} -$$\docode$$ -was typeset by \dots -\displaycode - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\note??=[stack] -When a stack of <pos>itions has been established using the |@i| and |@+| -commands, these positions can be used and are appended to the <poslist>. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\xy@@crvaddstack{% - \ifx\next ~\xywarning@{there should be a poslist here, \string~@ ignored}% - \DN@{\xy@crvmods@}% - \else\DN@{\xy@@crvaddstack@}\fi \next@} - -\xydef@\xy@@crvaddstack@{\smapxy@@\addtocrv@ \xyFN@\checkendcurve@} - -\xydef@\checkcrvtilde@{% - \addAT@\ifx\next\addAT@\DN@{\xy@@crvaddstack@}% - \else\xywarning@{invalid token after ~, ignored}% - \DN@##1{\xyFN@\checkendcurve@}% - \fi \next@ } -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\end{notes} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Spline Methods} - -Each |\curve| has to set the sliding abilities. -This is done by a call to |\crvconnect@@| which gives values to -the methods |\Creset@@|, |\Cshavep@|, etc. -These values depend on the style of the curve itself. - -\DOCMODE( -\xydef@\crvconnect@@{% - \def\Creset@@{\crvreset@}% - \def\Cshavep@@{\crvshavep@}% - \def\Cshavec@@{\crvshavec@}% - \def\Cslidep@@{\crvslidep@}% - \def\Cslidec@@{\crvslidec@}% - \def\Calong@@{\crvalong@}% - \def\Cintercept@@{\crvintercept@}% - \def\Cbreak@@{\crvbreak@}% - \def\Clast@@{\crvlast@}% -} -\DOCMODE) - -When straight lines are required \dots - -\DOCMODE( -\xydef@\straitconnect@{\crvconnect@@ - \let\crvreset@=\straitreset@ - \let\crvshavep@=\straitshavep@ - \let\crvshavec@=\straitshavec@ - \let\crvslidep@=\straitslidep@ - \let\crvslidec@=\straitslidec@ - \let\crvalong@=\straitalong@ - \let\crvintercept@=\straitintercept@ - \let\crvbreak@=\straitbreak@ - \let\crvlast@=\straitlast@ -} -\DOCMODE) - -These are the actual methods used for a sequence of straight segments. - -\DOCMODE( -\xydef@\straitreset@{\the\crvpts@ - \edef\xycrvptsnum@{\csname ptsnum@\endcsname}% - \def\segmentnum@{0}} -\xydef@\straitslidep@{\setupDirection@ii \noCslidep@@ } -\xydef@\straitslidec@{\setupDirection@ii \noCslidec@@ } - -\xydef@\straitshavep@{% - \expandafter\ifnum\xycrvptsnum@>\z@ - \def\segmentnum@{0}% - \csname cv@1\endcsname - \resetDirection@ \setupDirection@ii - \fi \noCshavep@@ } - -\xydef@\straitshavec@{% - \expandafter\ifnum\xycrvptsnum@>\z@ - \expandafter\count@@\xycrvptsnum@\relax - \bgroup \csname cv@\number\count@@\endcsname - \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ - \edef\segmentnum@{\xycrvptsnum@}% - \resetDirection@ \setupDirection@ii - \fi \noCshavec@@ } - -\xydef@\straitalong@#1{% - \ifdim#1\p@<\z@ - \xywarning@{parameter value #1 is negative, using 0}% - \cfromp@ \def\PLACEf@{{0}}% - \else - \dimen@=#1\p@ \count@=\dimen@ \divide\count@\p@ - \expandafter\count@@\xycrvptsnum@\relax \advance\count@@\@ne - \advance\dimen@\segmentnum@\p@ - \advance\count@\segmentnum@\relax - \def\segmentnum@{0}% - \ifnum\count@@<\count@ - \xywarning@{parameter value #1 too large, using \the\count@@}% - \count@=\count@@ \advance\count@\m@ne \edef\PLACEf@{{1}}% - \else - \advance\dimen@-\count@\p@ - \ifdim\zz@\dimen@\ifnum\count@>\z@ - \advance\count@\m@ne \advance\dimen@\p@ \fi\fi - \edef\PLACEf@{{\expandafter\removePT@\the\dimen@}}% - \fi - \ifnum\count@=\z@\else \bgroup - \csname cv@\number\count@\endcsname - \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ - \fi - \advance\count@\@ne - \ifnum\count@<\count@@ -\splinetrace@{find place \the\dimen@\space along straight segment - \the\count@}% - \csname cv@\number\count@\endcsname - \fi - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p - \fi \expandafter\noCalong@@\PLACEf@ \czeroEdge@ } -\DOCMODE) - -\DOCMODE( -\xydef@\straitintercept@{\noCintercept@@} -\xydef@\straitbreak@{\straightCbreak@@} -\xydef@\straitlast@{\straightClast@@} -\DOCMODE) - -When curved segments are required \dots - -\DOCMODE( -\xydef@\splineconnect@{% - \let\crvreset@=\splinereset@ - \let\crvshavep@=\splineshavep@ - \let\crvshavec@=\splineshavec@ - \let\crvslidep@=\splineslidep@ - \let\crvslidec@=\splineslidec@ - \let\crvalong@=\splinealong@ - \let\crvintercept@=\splineintercept@ - \let\crvbreak@=\splinebreak@ - \let\crvlast@=\splinelast@ -} -\DOCMODE) - -These are the actual methods. - -{\em Reset} the spline parameters: -\begin{description} -\item[|\xycrvptsnum@|:] expands to a control sequence, whose name -incorporates the correct scoping level, giving the number of control points. - -\item[|\the\crvpts@|:] -reads the control point locations and other information from a token list. - -\item[|\xysplineparams@|:] -set to a control sequence name, incorporating the correct scoping level, -which will allow access to the Be\'zier control points for each -spline segment, when required. - -\item[|\xysplineedges@|:] -set to a control sequence name, incorporating the correct scoping level, -which gives the spline parameters of the edges of objects at $p$ and $c$; - -\item[|\segmentnum@|:] reset to $0$. - -\item[|\splinecorrect@p| and |\splinecorrect@c|:] reset to $0$ -until changed by a |\Cshavep@| or |\Cshavec@|. - -\item[|\splinelength@|:] reset to $0$ until changed by a |\Cshavep@|, -|\Cshavec@| or |\Calong@|; this is needed by |\Cshavep@| and |\Cshavec@| -to quickly locate where to slide from, especially when it is necessary -to slide across more than a single spline segment. - -\item[|\splineplace@|:] reset to $.5$. -\end{description} - -\DOCMODE( -\xydef@\splinereset@{\the\crvpts@ - \edef\xycrvptsnum@{\csname ptsnum@\endcsname}% - \edef\xysplineparams@{% - \expandafter\noexpand\csname params@\endcsname}% - \edef\xysplineedges@{% - \expandafter\noexpand\csname edges@\endcsname}% - \def\segmentnum@{1}\def\splinecorrect@p{0}\def\splinecorrect@c{0}% - \splinelength@=\z@ \def\splineplace@f{.5}% -} -\DOCMODE) - -{\em Shaving} to the appropriate edge. -This is simply a matter of reading the stored edge information -and storing the appropriate value in |\splinecorrect@p| -or |\splinecorrect@c|. The difficult part is to construct the -correct control sequence name and then to extract the correct -part of the text in its expansion. - -\DOCMODE( -\xydef@\splineshavep@{\begingroup - \edef\xysplineedges@{% - \expandafter\noexpand\csname edges@\endcsname}% - \expandafter\expandafter\expandafter\getsplineedges@safe\xysplineedges@ @@% - \edef\tmp@{\noexpand\removePT@\the\dimen5}% - \edef\tmp@{\endgroup - \noexpand\def\noexpand\splinecorrect@p{\tmp@}}\tmp@ - \setupDirection@ii } - -\xydef@\splineshavec@{\begingroup - \edef\xysplineedges@{% - \expandafter\noexpand\csname edges@\endcsname}% - \expandafter\expandafter\expandafter\getsplineedges@safe\xysplineedges@ @@% - \dimen@=-\dimen7\relax \advance\dimen@\p@ -%% \getcrvsegsnum@ \advance\dimen@\count@\p@ - \edef\tmp@{\noexpand\removePT@\the\dimen@}%\W@{**shave**<\tmp@>***}% - \edef\tmp@{\endgroup - \noexpand\def\noexpand\splinecorrect@c{\tmp@}}\tmp@ - \setupDirection@ii } - -\xydef@\splineslidep@#1{\enter@{\pfromthep@}% - \begingroup \splinealong@@{0}{#1}+\splineslidep@@@ - \setupDirection@ii \leave@ }% - -\xydef@\splineslidep@@@{% - \d@X=\dimen5 \d@Y=\dimen7 \edef\tmp@{\postfind@}\tmp@ \dimen@=\splineval@ - \expandafter\count@\xycrvptsnum@\relax - \ifnum\count@>\tw@ \advance\count@\m@ne - \advance\dimen@\segmentnum@\p@ \advance\dimen@-\p@ - \fi - \edef\tmp@{\endgroup \endgroup - \noexpand\def\noexpand\xysplineval@{\the\splineval@}% - \noexpand\def\noexpand\splinecorrect@p{\expandafter\removePT@\the\dimen@}% -\splinetrace@{slide = \the\splinelength@}% - \X@c=\dimen@i \Y@c=\dimen3 % something may be wrong here!! - \d@X=\the\d@X \d@Y=\the\d@Y % - \noexpand\def\noexpand\segmentnum@{\segmentnum@}}\tmp@ } - -\xydef@\splineslidec@#1{\enter@{\pfromthep@}% - \begingroup - \expandafter\splinealong@@\PLACEf@{#1}+\splineslidec@@@ - \setupDirection@ii \leave@ } - -\xydef@\splineslidec@@@{% - \d@X=\dimen5 \d@Y=\dimen7 \edef\tmp@{\postfind@}\tmp@ \dimen@=\splineval@ - \expandafter\count@\xycrvptsnum@\relax - \ifnum\count@>\tw@ \advance\count@\m@ne - \advance\dimen@\segmentnum@\p@ \advance\dimen@-\p@ - \dimen@=-\dimen@ \advance\dimen@\count@\p@ - \else \dimen@=-\dimen@ \advance\dimen@\p@ \fi %\W@{**slide**<\the\dimen@>***}% -%% splinecorrect@c is probably wrong here!! - \edef\tmp@{\endgroup \endgroup - \noexpand\def\noexpand\xysplineval@{\the\splineval@}% - \noexpand\def\noexpand\splinecorrect@c{\expandafter\removePT@\the\dimen@}% -\splinetrace@{slide = \the\splinelength@; correct@c=\noexpand\splinecorrect@c}% - \X@c=\dimen@i \Y@c=\dimen3 % - \d@X=\the\d@X \d@Y=\the\d@Y % - \noexpand\def\noexpand\segmentnum@{\segmentnum@}}\tmp@ } - -\xydef@\checkslidemore@#1{% - \dimen@ii=-#1\relax\ifdim\dimen@ii<\z@\multiply\dimen@ii\m@ne\fi - \dimen@=-\splinelength@ \advance\dimen@\dimen@ii\relax - \ifdim\dimen@<\z@\dimen@ii=-\dimen@\else\dimen@ii=\dimen@\fi - \ifdim\dimen@ii<.2\p@\DN@{\splineslidec@@ \leave@}%%%% ? - \else \splinetrace@{not found yet, \the\dimen@ii\space still to go}% - \dimen@ii=#1\relax\ifdim\dimen@ii<\z@\multiply\dimen@\m@ne\fi - \DN@{\expandafter\splineslidemore@\expandafter{\the\dimen@}}\fi - \next@}% - -\xydef@\splineslidemore@#1{% - \expandafter\count@\segmentnum@\relax - \ifdim#1<\z@\advance\count@\m@ne\dimen@=\p@ - \else\advance\count@\@ne\dimen@=\z@\fi - \ifnum\count@<\@ne - \expandafter\splinesegment@\expandafter{\segmentnum@}% - \DN@{\xywarning@{cannot slide beyond start of curve}% - \spline@find{\z@}{\z@}{}\splineslidec@@ \leave@ }%%%% ? - \else \expandafter\count@@\xycrvptsnum@\relax\advance\count@@\m@ne - \expandafter\ifnum\count@@<\count@\relax - \expandafter\splinesegment@\expandafter{\segmentnum@}% - \DN@{\xywarning@{cannot slide beyond end of curve}% - \spline@find{\p@}{\z@}{}\splineslidec@@ \leave@ }%%%%% ? - \else - \edef\segmentnum@{\the\count@}% - \expandafter\splinesegment@\expandafter{\segmentnum@}% -\splinetrace@{sliding onto segment \segmentnum@}% - \expandafter\spline@find\expandafter{\the\dimen@}{#1}{}% - \DN@{\checkslidemore@{#1}}% - \fi\fi \next@ } - -\xydef@\splineslidec@@{% - \dimen@=\splineval@ \advance\dimen@\segmentnum@\p@\advance\dimen@-\p@ - \edef\tmp@{\endgroup - \noexpand\def\noexpand\xysplineval@{\the\dimen@}% -\splinetrace@{slide = \the\splinelength@}% - \X@c=\the\dimen@i \Y@c=\the\dimen3 \d@X=\the\dimen5 \d@Y=\the\dimen7 \postfind@ - \noexpand\def\noexpand\segmentnum@{\segmentnum@}}\tmp@ - \setupDirection@ii} -\DOCMODE) - -The method |\splinealong@#1| finds places along the curve, when |#1| is -given as a factor, normally between 0 and 1. The location of the edges -of the objects at $p$ and $c$ are stored in |\splinecorrect@p| and -|\splinecorrect@c|. -These are the places found if the factor is either 0 or 1. -If an edge is non-zero then it is actually possible to move to points inside -that edge by specifying a factor less than 0 or greater than 1. - -\DOCMODE( -\xydef@\splinealong@#1{\def\postfind@{}\splinealong@@{#1}\z@+% - \splineslidec@@ - \dimen@=\xysplineval@\relax - \count@=\xycrvptsnum@\relax \ifnum\count@>\@ne \advance\count@\m@ne\fi - \ifnum\count@>\@ne \dimen@nth\count@\dimen@ - \fi \edef\bthisPLACE@{\expandafter\removePT@\the\dimen@}% -\splinetrace@{bthisPLACE@=\bthisPLACE@}}% -\DOCMODE) - -The parameter |#2| in |\splinealong@@#1#2#3| allows for a subsequent slide -through a given <dimen> along the curve, from the place specifed by the -factor in |#1|. - -The information supplied in |#1| must be converted to the segment number and -parameter value of the specified point. These will be calculated and stored -temporarily in |\count@| and |dimen@| before the values are passed respectively -to |\splinesegment@| which chooses the segment, and |\spline@find| to locate -the point on this segment. - -To do the calculation, first we correct for the parameter values of the edges - of the objects at the end-points, which are stored in |\splinecorrect@p| and -|\splinecorrect@c|. If the resulting number $x$ is not an integer then -|\count@| is set to $1+\floor{x}$ while |\dimen@| becomes $(x-\floor{x})|\p@|$. -If $x$ is an integer: $x=0$ gives |\count@=1| and |\dimen@=\z@|, -otherwise $|\count@|=x$ and |\dimen@=\p@|. - -\DOCMODE( -\xydef@\splinealong@@#1#2#3{% - \edef\tmp@{#1}\relax \dimen@ii\tmp@\p@ -%% \getcrvsegsnum@ -%% \dimen@=-\count@\p@ - \dimen@=-\p@ - \expandafter\advance\expandafter\dimen@\splinecorrect@p\p@ - \expandafter\advance\expandafter\dimen@\splinecorrect@c\p@ - \edef\tmp@{#1}\relax \dimen@=-\tmp@\dimen@ \relax - \expandafter\advance\expandafter\dimen@\splinecorrect@p\p@ - \getcrvsegsnum@ \multiply \dimen@ by\count@\relax -\splinetrace@{actual:\the\dimen@; f:\the\dimen@ii; p:\splinecorrect@p, c:\splinecorrect@c}% - \count@=\dimen@ \divide\count@\p@ \DN@{\relax}% - \def\tmp@{\relax}\ifx\next@\tmp@ - \expandafter\ifnum\xycrvptsnum@<\count@ - \xywarning@{parameter value #1 too large}% - \DNii@{\relax}\DN@{\begingroup}% - \else - \edef\xysplineval@{\the\dimen@}% - \advance\dimen@-\count@\p@ - \ifdim\dimen@=\z@ -\splinetrace@{find knot point \the\count@}% - \ifnum\count@=\z@ \count@=\@ne \else \dimen@=\p@ \fi - \else \advance\count@\@ne -\splinetrace@{find point \the\dimen@\space on spline segment \the\count@}% - \fi - \edef\segmentnum@{\the\count@}% - \edef\next@{\begingroup\noexpand\splinesegment@{\the\count@}}% - \edef\nextii@{% - \noexpand\spline@find{\the\dimen@}{#2}{}\noexpand\checksplinefind@{#2}}% - \ifx>#3\relax - \edef\nextii@{% - \noexpand\spline@find{\the\dimen@}{#2}#3\noexpand\checksplinefind@{#2}}% - \else\ifx-#3\relax \ifdim\dimen@>\z@\relax \ifdim\dimen@<\p@ - \dimen@=-\dimen@ \advance\dimen@\p@ - \edef\nextii@{\noexpand\splinereverse@ - \noexpand\spline@find{\the\dimen@}{#2}{}\noexpand\checksplinefind@{#2}}% - \fi\fi - \else\ifx<#3\relax \ifdim\dimen@>\z@\relax \ifdim\dimen@<\p@ - \dimen@=-\dimen@ \advance\dimen@\p@ - \edef\nextii@{\noexpand\splinereverse@ - \noexpand\spline@find{\the\dimen@}{#2}#3\noexpand\checksplinefind@{#2}}% - \fi\fi - \fi\fi\fi - \fi\fi \expandafter\next@\nextii@ } -\DOCMODE) - - This macro checks whether the required sliding has been carried out, -or whether it is necessary to continue sliding along the next segment. - -\DOCMODE( -\xydef@\checksplinefind@#1{% - \dimen@ii=#1\relax \dimen@=\splinelength@ - \ifdim\dimen@ii=\z@\DN@{}% - \else - \ifdim\dimen@ii<\z@\advance\dimen@\dimen@ii - \else\advance\dimen@-\dimen@ii\fi - \ifdim\dimen@<\z@\multiply\dimen@\m@ne\fi - \ifdim\dimen@<.2\p@\DN@{}% - \else - \count@=\segmentnum@\relax - \ifdim\dimen@ii<\z@\advance\dimen@ii\splinelength@ - \ifnum\count@>\@ne\advance\count@\m@ne - \edef\next@{\noexpand\splinesegment@{\the\count@}% - \noexpand\spline@find\p@{\the\dimen@ii}{}% - \noexpand\checksplinefind@{\the\dimen@ii}}% - \else - \xywarning@{cannot slide \the\dimen@ii\space before start}% - \DN@{\splinesegment@\@ne \spline@find\z@\z@{}}\fi - \else\advance\dimen@ii-\splinelength@ - \count@@=\numcontrolpts - \ifnum\count@<\count@@ \advance\count@\@ne - \edef\next@{\noexpand\splinesegment@{\the\count@}% - \noexpand\spline@find\z@{\the\dimen@ii}{}% - \noexpand\checksplinefind@{\the\dimen@ii}}% - \else - \xywarning@{cannot slide \the\dimen@ii\space beyond end}% - \DN@{\splinesegment@{\the\count@@}\spline@find\p@\z@{}}\fi - \fi - \fi\fi \next@ } -\DOCMODE) - - -\paragraph*{Breaks} -% -Typesetting breaks in curves is quite involved. -The |\bstartPLACE@| and |\bendPLACE@| are used to hold parameter -values for the positions of the beginning and end of a segment, -respectively, when known. The default values of |\relax| indicate -that these values need to be found, usually from the start- and -end-edges of the curve. The value of |\empty| for |\bstartPLACE@| -is used initially with a new curved connection, to set up all its -parameters --- no typesetting takes place. This is used by curved -arrows to set up the connection before places can -be found for any breaks. - -\DOCMODE( -\xydef@\resetbreaks@{% - \let\bstartPLACE@=\relax \let\bthisPLACE@=\empty - \let\bendPLACE@=\relax \let\bprevPLACE@=\relax} - -\xydef@\invisbreaks@{\resetbreaks@ \let\bstartPLACE@=\empty} -\xydef@\crvresetbreaks@{\resetbreaks@ \let\bstartPLACE@=\relax } - -\xydef@\initbreaks@{\xy@@{\ifx\bstartPLACE@\relax - \def\bstartPLACE@{0}\def\bendPLACE@{1}\else - \ifx\bstartPLACE@\empty\def\bstartPLACE@{0}\def\bendPLACE@{1}% - \fi\fi}} - -\xydef@\lastbreaks@{\ifx\bprevPLACE@\relax \def\bstartPLACE@{0}% - \else \expandafter \bprevPLACE@ \fi - \let\bprevPLACE@\relax \let\bendPLACE@\relax} - -\xylet@\bstartPLACE@\relax -\xylet@\bendPLACE@\relax -\xylet@\bprevPLACE@\relax -\xydef@\bthisPLACE@{1} -\DOCMODE) - -These are called in the actual setting of curved sub-segments. - -\DOCMODE( -\xydef@\splinebreak@{% -\splinetrace@{***new break*** this:\bthisPLACE@ }% - \ifx\bthisPLACE@\empty\def\bendPLACE@{1}% - \else\edef\bendPLACE@{\bthisPLACE@}\let\bthisPLACE@\empty\fi -%\xystatus@{BR1}% - \ifx\bprevPLACE@\relax\def\bstartPLACE@{0}\else\expandafter\bprevPLACE@\fi - \edef\bprevPLACE@{\def\noexpand\bstartPLACE@{\bendPLACE@}\pfromthec@}% -\splinetrace@{splineBREAK: \bstartPLACE@ <> \bendPLACE@}% -%\xystatus@{BR}% - \edef\cv@brend{\cfromthec@}% - \edef\cv@brstart{\cfromthep@}% - \expandafter\connect\expandafter\crvs\crvSTYLE@@{}% ? optimise - \let\cv@brend=\relax - \let\cv@brstart=\relax -\splinetrace@{**break done**}% -} - -\xydef@\splinelast@{\splinereset@ \lastbreaks@ %\splinetracing -\splinetrace@{splineLAST}% -%\xystatus@{LA}% - \edef\cv@brend{\cfromthec@}% - \edef\cv@brstart{\cfromthep@}% - \expandafter\connect\expandafter\crvs\crvSTYLE@@{}% ? optimise - \let\cv@brend=\relax - \let\cv@brstart=\relax -\splinetrace@{**last done**}% - \resetbreaks@} -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Intersection with a curved connection} -Just as the intersection of two lines (??g[xy.doc:intercept]) can be found, -so can the intersection of a straight line with a curved connection, -or the intersection of a curve with a straight connection. - -\begin{code} -\xy*+{A}="A";p+/r5pc/+(0,15)*+{B}="B" - ,p+<1pc,3pc>*+{C}="C" - ,"A"+<4pc,-1pc>*+{D}="D",{\ar@/_/"C"} - ,?!{"A";"B"**@{-}}*++{\oplus} -\endxy \quad \xy - *+{A}="A";p+/r5pc/+(0,15)*+{B}="B", - ,p+<1pc,3pc>*+{C}="C" - ,"A"+<4pc,-1pc>*+{D}="D","A";"B"**@{-} - ,?!{"D",{\ar@/_/"C"}}*++{\oplus} -\endxy -\end{code} -$$\docode$$ -\displaycode - -When the line separates the end-points of a curve an intersection can always -be found. If there is more than one then that occurring earliest along the -curve is the one found. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Presume the end-points of the spline segment are at $(X_p,Y_p)$ and -$(X_c,Y_c)$ with $(L_p,U_p)$ and $(R_p,D_p)$ as two points on the line. -Then the macro |\xysidesofinterval@| returns 3 pieces of information. -\begin{itemize} -\item |\next| expands to 2 characters, each from $\{+,-,0\}$ - indicating which side of, or on, the line lies either end-point; -\item |\this@| expands to either $+$ or $-$ indicating which - end is closer to the line, returning $+$ if equi-distant; -\item |\howclose@| contains a non-negative <num> indicating the distance - to the nearest end-point. -\end{itemize} - -\DOCMODE( -\xydef@\splineNointercept@{\enter@{\pfromthep@}% - \begingroup \splinereset@ \csname cv@0\endcsname \swap@ - \count@=\ptsnum@ \advance\count@\@ne \csname cv@\the\count@\endcsname - \edef\tmp@{\endgroup \X@origin=\the\X@p \Y@origin=\the\Y@p - \R@c=\the\d@X \U@c=\the\d@Y}\tmp@ - \loop@ - \dimen@=\ifdim\R@c<\z@-\fi\R@c - \advance\dimen@ \ifdim\U@c<\z@-\fi\U@c - \ifdim\dimen@>10\p@ - \advance\R@c \ifdim\R@c<\z@-\fi 16sp \divide\R@c\KK@ - \advance\U@c \ifdim\U@c<\z@-\fi 16sp \divide\U@c\KK@ - \repeat@ - \intersect@ \leave@} - -\xydef@\splineintercept@{\Hidden@true\Invisible@true\splineintercept@i} - -\xydef@\splineintercept@i{\enter@{\pfromthep@}\begingroup - \R@p=\X@c \L@p=\X@p \d@X=\R@p \advance\d@X-\L@p - \D@p=\Y@c \U@p=\Y@p \d@Y=\D@p \advance\d@Y-\U@p - \dimen@nth\KK@\d@X \edef\sd@X{\expandafter\removePT@\the\d@X}% - \dimen@nth\KK@\d@Y \edef\sd@Y{\expandafter\removePT@\the\d@Y}% - \dimen@=\sd@Y\L@p \advance\dimen@-\sd@X\U@p - \edef\sideOffset@{\the\dimen@}\def\closestseg@{1}% - \let\crvconnect@@=\relax \crvconnect@ - \let\spline@end=\splinef@end - \def\spline@start{\bgroup \def\prevnext@{+-}% - \def\splinerec@{\let\splinerec@=\splineIrec@ \splineinterceptTest@}% - \def\splinedecast@{\let\splinedecast@=\splinedecast@@ - \def\splineadvance@{\splineIadvance@@}\splinedecast@@}% - \def\splineadvance@{\intercepthull@}% -% \def\splinepoint@{\splineIpt@@}% - \global\let\splinepoint=\splineIpt@@ - \global\let\splinegoal@=\splinef@pt - \global\let\splinefinish@=\splinefinish@@}% - \begingroup \splineIsegment@ - \splinesetparams@ \splined@@ \def\postfind@{}\splineIplace@ - \setupDirection@ii \leave@ } - - -\xydef@\splineIplace@{% - \d@X=\dimen5 \d@Y=\dimen7 \dimen@=\splineval@ - \expandafter\count@\xycrvptsnum@\relax - \ifnum\count@>\tw@ \advance\count@\m@ne %\advance\count@\m@ne - \advance\dimen@\segmentnum@\p@ \advance\dimen@-\p@ - \dimen@nth\count@\dimen@ % \divide\dimen@\count@ - \fi \edef\tmp@{\endgroup \endgroup - \def\noexpand\PLACEf@{{\expandafter\removePT@\the\dimen@}}% - \X@c=\dimen@i \Y@c=\dimen3 % - \d@X=\the\d@X \d@Y=\the\d@Y }\tmp@ -\splinetrace@{PLACE = \PLACEf@:(\the\X@c, \the\Y@c)}% - \expandafter\edef\expandafter\bthisPLACE@\PLACEf@ - } - -\xydef@\splineIrec@{\splineinterceptTest@ } - -\xydef@\squineIpt@{\edef\tmp@{\endgroup - \def\noexpand\prevnext@{\next}\begingroup}\tmp@ } -\xydef@\squineIadvance@{\edef\tmp@{\endgroup - \def\noexpand\prevnext@{\next}\def\noexpand\howclose@{\howclose@}}% - \tmp@ \splineadvance@@\begingroup} - -\xydef@\cubicIpt@{\edef\tmp@{\endgroup - \def\noexpand\prevnext@{\next}\begingroup}\tmp@ } -\xydef@\cubicIadvance@{\edef\tmp@{\egroup - \def\noexpand\prevnext@{\next}\def\noexpand\howclose@{\howclose@}}% - \tmp@ \splineadvance@@\bgroup} - -\xydef@\splineIsegment@{\DN@{\splinesegment@\@ne}% - \ifx\splinesegment@\squinesegment@\else - \ifx\splinesegment@\cubicsegment@\else\DN@{\findIsegment@}% - \fi\fi\next@} - -\xydef@\findIsegment@{\expandafter\count@\xycrvptsnum@ \count@@\z@ - \loop@ \advance\count@@\@ne \bgroup - \expandafter\splinesegment@\expandafter{\the\count@@}% - \xysidesofinterval@ - \findIsegment@i \repeat@ - \expandafter\dimen@\prevhowclose@ \relax - \ifdim\dimen@=\z@ \edef\closestseg@{\the\count@@}\fi - \expandafter\splinesegment@\expandafter{\closestseg@}} - -\xydef@\findIsegment@i{% - \expandafter\ifx\next \expandafter\findIsegment@ii - \else\expandafter\findIsegment@x\fi \next@ } - -\xydef@\findIsegment@ii{\expandafter\count@\xycrvptsnum@ \relax - \advance\count@\m@ne \ifnum\count@>\segmentnum@\relax - \expandafter\findIsegment@y\else\expandafter\findIsegment@x\fi} - -\xydef@\findIsegment@x{% - \edef\next@{\egroup\def\noexpand\next{\next}% - \def\noexpand\prevhowclose@{\prevhowclose@}% - \def\noexpand\closestseg@{\closestseg@}\noexpand\iffalse}} - -\xydef@\findIsegment@y{% - \edef\next@{\egroup\def\noexpand\next{\next}% - \def\noexpand\prevhowclose@{\prevhowclose@}% - \def\noexpand\closestseg@{\closestseg@}\noexpand\iftrue}} - -\xydef@\xysidesofinterval@{\bgroup - \L@p=\sd@X\Y@p \advance\L@p-\sd@Y\X@p \advance\L@p\sideOffset@ - \U@p=\sd@X\Y@c \advance\U@p-\sd@Y\X@c \advance\U@p\sideOffset@ - \def\this@{}\ifdim\L@p>\almostz@ \ifdim\U@p>\almostz@ \def\next{++}\else - \ifdim\U@p<-\almostz@ \def\next{+-}\else\def\next{+0}\def\this@{-}\fi\fi - \else\ifdim\L@p<-\almostz@ \ifdim\U@p>\almostz@ \def\next{-+}\else - \ifdim\U@p<-\almostz@ \def\next{--}\else\def\next{-0}\def\this@{+}\fi\fi - \else \ifdim\U@p>\almostz@ \def\next{0+}\else - \ifdim\U@p<-\almostz@ \def\next{0-}\else\def\next{00}\def\this@{+}\fi\fi - \fi\fi - \ifx\this@\empty - \L@p=\ifdim\L@p<\z@-\fi\L@p \U@p=\ifdim\U@p<\z@-\fi\U@p - \ifdim\L@p<\U@p \edef\howclose@{\the\L@p}\def\this@{-}% - \else \edef\howclose@{\the\U@p}\def\this@{+}\fi - \else\def\howclose@{0.0pt}\fi -\splinetrace@{\next:\this@:\howclose@;\the\splineval@:% - (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c)}% - \ifdim\howclose@<\prevhowclose@\relax - \edef\tmp@{\egroup\def\noexpand\this@{\this@}\def\noexpand\next{\next}% - \def\noexpand\howclose@{\howclose@}\def\noexpand\prevhowclose@{\howclose@}% - \def\noexpand\closestseg@{\segmentnum@}}% -\splinetrace@{closest yet: \howclose@, in segment \segmentnum@}% - \else - \edef\tmp@{\egroup\def\noexpand\this@{\this@}\def\noexpand\next{\next}% - \def\noexpand\howclose@{\howclose@}}% - \fi \tmp@ } - -\xydef@\splineinterceptTest@{% - \xysidesofinterval@ \DN@{\splineadvance@}% - \DNii@{0.0pt}\ifx\howclose@\nextii@ \DN@{\splineclosest@}% - \else\expandafter\ifx\next \expandafter\ifx\prevnext@ - \ifx\next\prevnext@\else\DN@{\X@c=\X@p \Y@c=\Y@p - \splinefinishf@}\fi\fi - \else \DN@{\splinedecast@}\fi\fi - {\splinefar@false \splinenear@\X@p\X@c\Y@p\Y@c - \ifsplinefar@ \aftergroup\next@ - \else\aftergroup\splineclosest@ -\splinetrace@{too close: (\the\X@p,\the\Y@p)::(\the\X@c,\the\Y@c)}% - \fi}} - -\xydef@\splineclosest@{%\global\advance\splineval@-.5\splinedepth@ - \expandafter\ifx\this@-\relax - \X@c=\X@p \Y@c=\Y@p \global\advance\splineval@-\splinedepth@ - \fi \splinefinishf@ }% -\DOCMODE) - -When the line misses the convex hull of the curve's control points -it is still possible to get the point of closest approach. - -\DOCMODE( -\xydef@\squinetestcvxhull@{\begingroup -\splinetrace@{hull: closest in segment \closestseg@}% - \expandafter\splinesegment@\ifx\undefined\closestseg@\@ne\else\closestseg@\fi - \X@c=\L@c \Y@c=\U@c \xysidesofinterval@ - \expandafter\ifx\next \expandafter\splineoutsidehull@@ - \else \expandafter\splineinsidehull@\fi} - -\xydef@\cubictestcvxhull@{\begingroup - \expandafter\splinesegment@\ifx\undefined\closestseg@\@ne\else\closestseg@\fi - \X@c=\L@c \Y@c=\U@c \xysidesofinterval@ - \expandafter\ifx\next \expandafter\cubictestcvxhull@i - \else \expandafter\splineinsidehull@\fi} - -\xydef@\cubictestcvxhull@i{%\begingroup - \X@c=\R@c \Y@c=\D@c \xysidesofinterval@ - \expandafter\ifx\next \expandafter\splineoutsidehull@@ - \else \expandafter\splineinsidehull@\fi} - - -\xydef@\xysidesofhull@{\bgroup - \L@p=\sd@X\Y@p \advance\L@p-\sd@Y\X@p \advance\L@p\sideOffset@ - \U@p=\sd@X\Y@c \advance\U@p-\sd@Y\X@c \advance\U@p\sideOffset@ - \L@p=\ifdim\L@p<\z@-\fi\L@p \U@p=\ifdim\U@p<\z@-\fi\U@p - \ifdim\L@p<\U@p \edef\howclose@{\the\L@p}\def\this@{-}% - \else \edef\howclose@{\the\U@p}\def\this@{+}\fi - \ifx\splinedecast@\squinedecast@ \D@c=\U@c \R@c=\L@c \fi - \L@p=\sd@X\U@c \advance\L@p-\sd@Y\L@c \advance\L@p\sideOffset@ - \L@p=\ifdim\L@p<\z@-\fi\L@p - \expandafter\if\this@-% - \ifdim\L@p<\prevhowclose@ \def\next{-+}\else \def\next{--}\fi - \else - \ifdim\L@p<\howclose@ \def\next{-+}\else - \U@p=\sd@X\D@c \advance\U@p-\sd@Y\R@c \advance\U@p\sideOffset@ - \U@p=\ifdim\U@p<\z@-\fi\U@p - \ifdim\U@p<\howclose@ \def\next{+-}\else \def\next{++}\fi - \fi\fi - \edef\tmp@{\egroup\def\noexpand\this@{\this@}\def\noexpand\next{\next}% - \def\noexpand\howclose@{\howclose@}}\tmp@ } -\DOCMODE) - -This is for straight connections intercepting with a curve. -It requires a redefinition of |\PLACE@intercept@| to recognise -that the intercept is with a curved connection. - -\DOCMODE( -\def\PLACE@intercept@#1{% - \xy@@{\enter@{\pfromthep@\basefromthebase@}\begingroup}% - \xy@@ix@{#1}\xy@@{\plainxy@ \def\Creset@@{}% - \expandafter\POS\the\toks9\relax - \DNii@{\crvreset@}\ifx\nextii@\Creset@@ \edef\next@{\endgroup - \def\noexpand\xyinterceptpts@{\the\crvpts@}% - \X@c =\the\X@c \Y@c=\the\Y@c \X@p=\the\X@p \Y@p=\the\Y@p - \noexpand\CCintercept@@ }% - \else \edef\next@{\endgroup - \X@c =\the\X@c \Y@c=\the\Y@c \X@p=\the\X@p \Y@p=\the\Y@p - \noexpand\Cintercept@@ }% - \fi \next@ \leave@}% - \PLACE@@} - -\xydef@\CCintercept@@{\splineSintercept@} -\xydef@\splineSintercept@{\enter@{\pfromthep@}\begingroup - \Creset@@ \edef\connect@pts{\cfromthec@ \pfromthep@}% - \xyinterceptpts@ \splinereset@ \connect@pts \splineintercept@ - \edef\next@{\endgroup \cfromthec@ \DirectionfromtheDirection@ }% - \next@ \let\xyinterceptpts@=\empty \leave@} -\DOCMODE) - -\TODO: -If both connections are curves, only the line joining the end-points -of the first connection is used. Find a way to do better than this. - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -If the line does not separate the end-points then there may be no -intersection with the curve. If there is one then either the line is -tangential or necessarily there will also be at least one other intersection. -A message $$|perhaps no curve intersection, or many.|$$ -is written to the log-file, but a search for an intersection will still be -performed and a ``sensible'' place found on the curve. -In the usual case of a single quadratic or cubic segment, the place nearest -the line is found and the tangent direction is established. - -The following examples show this, and show how to get the place on the line -nearest to the curve. - -\begin{code} -\xy *+{A}="A";p+/r5pc/+(0,15)*+{B}="B", - ,p-<.5pc,2pc>*+{C}="C","A"+<6pc,-.5pc> - ,*+{D}="D","A",{\ar@/_25pt/"B"} - ,?!{"C";"D"**@{-}}*\dir{x}="E" - ,+/_2pc/="F";"E"**@{-},?!{"C";"D"} - ,*{\otimes}\endxy\qquad\xy - *+{A}="A";p+/r5pc/+(0,15)*+{B}="B", - ,p-<.5pc,2pc>*+{C}="C" - ,"A"+<7pc,.5pc>*+{D}="D","A" - ,{\ar@/_40pt/"B"},?!{"C";"D"**@{-}} - ,*{\otimes}\endxy -\end{code} -$$\docode$$ -\displaycode - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The warning message, that no intersection may exist, always occurs inside -a grouping so it can safely switch itself off for deeper levels. - -\DOCMODE( -\xydef@\nointerceptwarning@{\let\nointerceptwarning@=\relax - \xywarning@{perhaps no curve intersection, or many. }} - -\xydef@\intercepthull@{\nointerceptwarning@ - \expandafter\def\expandafter\prevnext@\expandafter{\next}% - \splinetestcvxhull@} -\DOCMODE) - -When the line meets the convex hull of the current control points, -then a closer point exists inside the current portion of the curve. -We must ``decast'' to find it, after storing the closest value known -so far, within |\prevhowclose@|. - -\DOCMODE( -\xydef@\splinetestcvxhull@{\begingroup - \X@c=\L@c \Y@c=\U@c \splinetrace@{hull:}\xysidesofinterval@ - \expandafter\ifx\next \expandafter\splineoutsidehull@@ - \else \expandafter\splineinsidehull@\fi} - -\xydef@\splineinsidehull@{\edef\tmp@{\endgroup - \def\noexpand\howcvxclose@{\howclose@}% - \noexpand\interceptinsidehull@}\tmp@ } - -\xydef@\interceptinsidehull@{\edef\prevhowclose@{\howclose@}% - \splinedecast@@ } -\DOCMODE) - -If the line does not cross into the convex hull, then we use -the distance from the control points to determine whether or not -there can be a closer point. The value of |\prevhowclose@| -indicates the best so far, while |\howcvxclose@| temporarily -holds the distance to the closest control point. When this is -nearer then there will be a closer point on the curve. - -\DOCMODE( -{\xdef\next{\the\maxdimen}} -\xylet@\prevhowclose@=\next - -\xydef@\splineoutsidehull@{\edef\tmp@{\endgroup - \def\noexpand\howcvxclose@{\howclose@}% - \noexpand\interceptoutsidehull@}\tmp@} -\xylet@\splineoutsidehull@@=\splineoutsidehull@ - -%\xydef@\interceptoutsidehull@{\dimen@=\howcvxclose@ \relax -% \ifdim\dimen@<\howclose@ \relax -% \ifdim\howclose@<\prevhowclose@\relax \edef\prevhowclose@{\howclose@}\fi -% \DN@{\begingroup\splinedecast@@ \endgroup}% -% \else\ifdim\howclose@>\prevhowclose@ \relax \DN@{\splineHadvance@}% -% \else \DN@{\splineHadvance@ }\fi\fi \next@ } -\xydef@\interceptoutsidehull@{\dimen@=\howcvxclose@ \relax -% \global\splineval@=\z@ -\splinetrace@{OUTSIDE HULL: \the\dimen@ : (\howclose@)(\prevhowclose@)}% - \let\splinedecast@=\splinedecast@@ - \let\splinerec@\splineHnear@test - \let\splineadvance@\splineIadvance@@ - \splinedecast@@ } - -\xydef@\splineHnear@test{% - \xysidesofhull@ \DN@{\splinedecast@}% - \ifdim\howclose@<\prevhowclose@\edef\howclose@{\prevhowclose@}\fi - \expandafter\if\this@-% - \expandafter\ifx\next\DN@{\splineclosest@}\fi - \else - \expandafter\ifx\next\DN@{\splineadvance@}\fi - \fi - {\splinefar@false \splinenear@\X@p\X@c\Y@p\Y@c - \ifsplinefar@ \aftergroup\next@ - \else\aftergroup\splineclosest@ -\splinetrace@{too close: (\the\X@p,\the\Y@p)::(\the\X@c,\the\Y@c)}% - \fi}} -\DOCMODE) - -For cubic segments it is necessary to look at both control-points -off the curve and compare their distances; hence the use of -|\prevhowcvxclose@|, initially set to |\maxdimen|. - -\DOCMODE( -\xydef@\cubicoutsidehull@{\edef\tmp@{\endgroup - \def\noexpand\howcvxclose@{\howclose@}}\tmp@ - \edef\prevhowcvxclose@{\howcvxclose@}\begingroup - \X@p=\R@c \Y@p=\D@c \splinetrace@{hullii:}\xysidesofinterval@ - \expandafter\ifx\next \expandafter\cubicoutsidehull@i - \else \expandafter\cubicinsidehull@\fi} - -\xydef@\cubicinsidehull@{\edef\tmp@{\endgroup - \def\noexpand\howclose@{\howclose@}}\tmp@ - \cubicoutsidehull@ii } - -\xydef@\cubicoutsidehull@i{\edef\tmp@{\endgroup - \def\noexpand\howcvxclose@{\howclose@}}\tmp@ - \dimen@=\prevhowcvxclose@\relax - \ifdim\dimen@<\howcvxclose@ \relax - \edef\howcvxclose@{\the\dimen@}\expandafter\interceptoutsidehull@ - \else \expandafter\cubicoutsidehull@ii\fi } - -\xydef@\cubicoutsidehull@ii{% - \def\splineadvance@{\splineadvance@@}% - \def\splinepoint\endgroup{\endgroup -% \global\let\splinepoint=\splinepoint@ - \global\let\splinepoint=\relax - \def\splineadvance@{\intercepthull@}}% - \splinedecast@@ }% -\DOCMODE) - -This macro |\splineHadvance@| is used at the end of a |\splinedecast@| -in order to pass information from out of a subsegment, to help decide -whether there is any point in further searching. - -\DOCMODE( -\xydef@\splineHadvance@{\futurelet\next@\splineHadvance@i} -\xydef@\splineHadvance@i{\ifx\next@\endgroup - \expandafter\splineHadvance@x\else\expandafter\splineclosest@\fi} - -\xydef@\splineHadvance@x{\edef\tmp@{\endgroup - \def\noexpand\prevhowclose@{\prevhowclose@}% - \def\noexpand\prevnext@{\next}\def\noexpand\howcvxclose@{\howclose@}}% - \tmp@ \dimen@=\prevhowclose@ \relax - \ifdim\dimen@<\howclose@ \relax \DN@{\splineclosest@\begingroup}% - \else\ifdim\howcvxclose@=\dimen@\DN@{\splineclosest@\begingroup}% - \else\DN@{\splineadvance@@\begingroup}\fi\fi \next@ } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Miscellaneous features} -% -The command |\clearcurve| was originally provided to discard the curve -information, and return to the graphics state before the curve was read, -if this is ever found to be necessary. This will probably be removed. - -\DOCMODE( -\xydef@\xyclearcrv@{\cv@end\cv@restore\loop@ - \expandafter\let\csname cv@\number\crv@cnt@\endcsname\relax - \ifnum\crv@cnt@>0\advance\crv@cnt@\m@ne\repeat@ - \let\cv@start=\relax \let\cv@end=\relax \let\cv@restore=\relax \POS} -\xylet@\clearcurve=\xyclearcrv@ -\DOCMODE) - -\TODO: -Define an |\extendcurve| as a <postcurve> which allows the curve -to be continued smoothly past the endpoint $c$. - -A macro can be used within the modifier, to provide different labels -at each control point. For example\dots - -\begin{code} -\newcount\cptlabel\global\cptlabel=0 -\def\nextcptlabel{\global\advance\cptlabel 1 % - \number\cptlabel} -\xy (0,0)*+{A}; (50,-10)*+{B} -**\crv~Pc{~*{\nextcptlabel}(10,-10) - &(20,15)&(30,-15)&(40,15)} \endxy -\end{code} -$$\docode$$ -\displaycode - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Two control sequences are provided to access the control points. -Firstly |\numcontrolpts| returns the number of them, -while |\xycontrolpt|<num> sets $c$ to be the particular control point. -Here <num> must be a single digit, grouped integer \eg\ |{-15}| -or count register containing a numerical value. -If larger than |\numcontrolpts| then $c$ becomes the end-point of the curve, -while if zero it becomes the starting point. -A negative value sets both $p$ and $c$ to be the starting point, -whereas other values leave $p$ unchanged. - -\DOCMODE( -\xylet@\numcontrolpts=\xynumctrlpts@ - -\xydef@\xycontrolpt@#1{{% - \ifnum#1<\z@\aftergroup\cv@restore\aftergroup\cv@start - \else - \expandafter\count@\xycrvptsnum@\relax \advance\count@\@ne - \ifnum#1>\count@ \ifx\cv@end\relax - \expandafter\aftergroup\csname cv@\number#1\endcsname - \else\aftergroup\cv@end\fi - \else - \expandafter\ifx\csname cv@\number#1\endcsname\relax - \ifnum#1=\z@\aftergroup\cv@start\else\aftergroup\cv@end\fi - \else\expandafter\aftergroup\csname cv@\number#1\endcsname - \fi\fi\fi}}% -\xylet@\xycontrolpt=\xycontrolpt@ -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Storing control point locations:} - -Upon starting to read the control points for a curve, -first set the counter |\crv@cnt@| to be zero. -Store the position of $p$ and $c$ and the current base in control sequences -|\cv@start|, |\cv@end| and |\cv@restore| for later retrieval and to -reinstate the current graphics state. |\cv@start| is a little more -complicated in order to retain the existing value of $p$. - -\DOCMODE( -\xydef@\startxycurve@@{\crv@cnt@=\z@ - \edef\cv@start{\cfromthep@}% - \ifdim\zz@\R@c \ifdim\zz@\L@c \ifdim\zz@\D@c \ifdim\zz@\U@c - \Edge@c={\zeroEdge}\fi\fi\fi\fi - \edef\cv@end{\cfromthec@}% - \edef\cv@restore{\pfromthep@\basefromthebase@}} -\xylet@\startxycurve@=\startxycurve@@ - -\xylet@\cv@start=\relax -\xylet@\cv@end=\relax -\xylet@\cv@restore=\relax -\xydef@\readxycurve@{\startxycurve@\xycrvmods@} -\xylet@\readxycurve=\readxycurve@ -\DOCMODE) - - -The position of each control point is stored as the expansion -of a control sequence whose name encodes its place within the $<poslist>$. -Expanding this control sequence sets $c$ to be the appropriate position. - -\DOCMODE( -\xydef@\addtocrv@{\advance\crv@cnt@\@ne - \edef\tmp@{% - \expandafter\noexpand\csname cv@\number\crv@cnt@\endcsname}% - \expandafter\edef\tmp@{\cfromthec@}% - \edef\tmp@{\noexpand\addtocrvpts@{\noexpand\def - \expandafter\noexpand\tmp@{\X@c=\the\X@c \Y@c=\the\Y@c }}}\tmp@ - \edef\xycrvptsnum@{\the\crv@cnt@}% -} -\DOCMODE) -% use of |\xycrvptsnum@| here is not desirable, but it works. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Alternate curve styles:} - -\DOCMODE( -\xydef@\xycrvdrop@{ {\zerodot}} -\xydef@\xycrvconn@{} - -\xydef@\xyc@trlpts@{\def\xycrvdrop@{ \dir{x}}\def\xycrvconn@{}% - \afterCURVE{\savecrvobjects@\xyctrlpts@}\readxycurve@} -\xydef@\xyc@trlpts@@{% - \afterCURVE{\savecrvobjects@\def\xycrvdrop@{ \dir{x}}% - \def\xycrvconn@{}\xyctrlpts@}\readxycurve@} -\xydef@\xyc@vxhull@{\def\xycrvdrop@{ {}}% - \edef\xycrvconn@{ \noexpand\dir{\addDASH@{}}}% - \afterCURVE{\savecrvobjects@\xycvxhull@}\readxycurve@} -\xydef@\xyc@vxhull@@{% - \afterCURVE{\savecrvobjects@\def\xycrvdrop@{ {}}% - \edef\xycrvconn@{ \noexpand\dir{\addDASH@{}}}\xycvxhull@}\readxycurve@} -\xylet@\controlpts=\xyc@trlpts@ -\xylet@\convexhull=\xyc@vxhull@ -\xydef@\savecrvobjects@{\bgroup - \expandafter\toks@\expandafter{\xycrvdrop@}% - \expandafter\toks@ii\expandafter{\xycrvconn@}% - \edef\tmp@{\egroup\noexpand\def\noexpand\resetcrvobjects@{% - \noexpand\def\noexpand\xycrvdrop@{\the\toks@}% - \noexpand\def\noexpand\xycrvconn@{\the\toks@ii}% - }}\tmp@} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -There is the potential to do many other things here, by using |\afterCURVE|, -once the list of control points has been read. - -\DOCMODE( -\xydef@\afterCURVE#1{\def\afterCURVE@{#1}} -\xydef@\endxycurve@{\cv@end\savectrlptsnum@ - \expandafter\def\csname params@\endcsname{\the\crvpts@}% - \cv@restore\afterCURVE@\POS} -\xylet@\endcurve=\endxycurve@ -\DOCMODE) - -In fact this is essentially how |\controlpts| and |\convexhull| -were interfaced before extensions were added to change styles. - -\begin{code} -\def\controlpts{\afterCURVE{\xyctrlpts}% - \readxycurve} -\def\convexhull{\afterCURVE{\xycvxhull}% - \readxycurve} -\end{code} -\displaycode - -\noindent -The real work is done by |\xyctrlpts| and |\xycvxhull|. -At the point when these macros are expanded the graphics state has the -restored $p$ and $c$ to their original values, -\ie\ the end-points of the curve. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{|\controlpts|:} - -This macro visits in order each of the control points dropping the requisite -object. The connection style is not used and the direction does not change. -For a loop-counter we use |\count@@@|. - -\DOCMODE( -\xydef@\xyctrlpts@{\cv@end \cv@restore - \def\crvconnect@{\straitconnect@}% - \ifnum\crv@cnt@>\z@ - \count@@@=\@ne \DN@{\loop@\xycontrolpt@{\count@@@}\relax - \expandafter\xycvxhulldrop@\xycrvdrop@ - \ifnum\crv@cnt@>\count@@@\advance\count@@@\@ne\repeat@ - \cv@end \cv@restore }% - \else\DN@{\relax}\fi \next@ } -\xylet@\xyctrlpts=\xyctrlpts@ -\DOCMODE) - -The token list |\crvpts@| stores the following information: -current scope ||, location of $p$ and $c$, -number of control points |\crv@cnt@| and their locations. -It does this by storing |\def|s for control sequence names, -depending on the scope, which expand to this information. -Thus by executing |\the\crvpts@| at the right level, -the information is conveniently recovered via control sequences which -do not conflict with anything else, and whose names can be reconstructed. - -\DOCMODE( -\xydef@\addtocrvpts@#1{\crvpts@=\expandafter{\the\crvpts@#1}} -\DOCMODE) - -\DOCMODE( -\xydef@\savescope@{\crvpts@={}% - \edef\tmp@{\expandafter\noexpand\csname cv@0\endcsname}% - \edef\tmp@{\noexpand\addtocrvpts@{\noexpand\def - \expandafter\noexpand\tmp@{\X@c=\the\X@p \Y@c=\the\Y@p}}}% - \tmp@ } - -\xydef@\savectrlptsnum@{% - \advance\crv@cnt@\@ne \edef\tmp@{% - \expandafter\noexpand\csname cv@\number\crv@cnt@\endcsname}% - \edef\tmp@{\noexpand\addtocrvpts@{\noexpand\def - \expandafter\noexpand\tmp@{\X@c=\the\X@c \Y@c=\the\Y@c}}}\tmp@ - \advance\crv@cnt@\m@ne - \edef\tmp@{\expandafter\noexpand\csname ptsnum@\endcsname}% - \edef\tmp@{\noexpand\addtocrvpts@{% - \noexpand\def\expandafter\noexpand\tmp@{\number\crv@cnt@}}}% - \tmp@ } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Convex Hull:} - -This macro visits in order each of the control points dropping the requisite -object. With the previous as $p$ and the current one as $c$, a connection -is set in the requisite style. For a loop-counter we use |\count@@@|. - -Use a group |{\expandafter\POS\xycrvconn@}| else the |\loop@| gets upset. -This does not affect the size of the \Xy-picture, since the dropped objects -are not similarly shrouded. - -Also used for the trivial case where there are no control points, hence -a straight line between $p$ and $c$ is what is requested. - -\DOCMODE( -\xydef@\xycvxhull@{\cv@end \cv@restore - \addtocrvpts@{\def\crvconnect@{\straitconnect@}}% - \def\crvconnect@{\straitconnect@}% - \ifnum\crv@cnt@>\z@ - \count@@@=\@ne\relax \DN@{\loop@\xycontrolpt@{\count@@@}\relax - \expandafter\xycvxhulldrop@\xycrvdrop@ - {\expandafter\connect\xycrvconn@{}}\pfromc@ - \ifnum\crv@cnt@>\count@@@\relax \advance\count@@@\@ne\repeat@ - \cv@end }% - \else - \ifx\empty\xycrvconn@ - \edef\xycrvconn@{\noexpand!C\noexpand\dir{\addDASH@{}}}\fi - \DN@{\relax}\fi \next@ - {{\expandafter\connect\xycrvconn@{}}}% - \cv@end \cv@restore } -\xylet@\xycvxhull=\xycvxhull@ - -\xydef@\xycvxhulldrop@#1#{\drop@{#1}} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{Spline constructions} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The control sequence |\xysplineparams@| provides a way to access a control -sequence name that is unique to the current \Xy-pic scope. -This control sequence will be used to store the parameters which determine -the spline curve. Similarly |\xysplineedges@| will be used to store the -parameter values and lengths (along the squine) to the locations where -the spline crosses the edge of the objects at the ends $p$ and $c$. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\savespline@{% -\splinetrace@{savespline@:}% -% \edef\endspline@{\endgroup - \edef\endspline@{\endgroup - \savesplineparams@ \savesplinerefs@ - \X@min=\the\X@min\relax \X@max=\the\X@max\relax - \Y@min=\the\Y@min\relax \Y@max=\the\Y@max\relax - \ifInvisible@\noexpand\Invisible@true - \else\noexpand\Invisible@false\fi - }\endspline@ - \edef\tmp@{\noexpand\addtocrvpts@{\savesplineparams@}}\tmp@ - \xycontrolpt@\z@ \cv@end } - -\xydef@\savesplineparams@{% - \noexpand\def\expandafter\noexpand\xysplineedges@{\xysplineedges@}} - -\xydef@\savesplinerefs@{% - \noexpand\def\noexpand\xysplineparams@{% - \expandafter\noexpand\xysplineparams@}% - \noexpand\def\noexpand\xysplineedges@{% - \expandafter\noexpand\xysplineedges@}% -} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -One new box register is required, for the object used to actually -set the curve, \dots - -\DOCMODE( -\xynew@{box}\splinebox@ -\DOCMODE) - -\dots\ and 4 dimen registers ... - -\DOCMODE( -\xynew@{dimen}\splineval@ -\DOCMODE) -\dots\ which is for tracking the natural spline parametrization; - -\DOCMODE( -\xynew@{dimen}\splinedepth@ -\DOCMODE) -\dots\ which is for tracking he depth of the recursive algorithms; - -\DOCMODE( -\xynew@{dimen}\splinetol@ -\DOCMODE) -\dots\ which contains the tolerance for the spline, -(this can probably be shifted to an ordinary macro); - -\DOCMODE( -\xynew@{dimen}\splinelength@ -\DOCMODE) -\dots\ which accumulates a measure of the length along a spline curve. -(Currently this is not being used, as most things can be done -satisfactorily using the spline parametrization only.) - - -Some new conditionals are also required. These are for testing whether -successive places on the squine are sufficiently close together, -and whether the objects should be placed or not. - -\DOCMODE( -\xynew@{if}\ifsplinefar@ -\xynew@{if}\ifsplineplot@ % to plot points or not -\DOCMODE) - -Provide some tracing ability, for debugging. - -\DOCMODE( -\xydef@\splinetracing{\let\splinetrace@=\W@} -\xydef@\splineignore@#1{} -\xylet@\splinetrace@=\splineignore@ -\DOCMODE) - -\medskip - -The parameters for the current section of the spline are stored indirectly -in |\xysplineparams@|, while information concerning the places where the -spline crosses the edges of objects at $p$ and $c$ is stored indirectly in -|\xysplineedges|. -A control sequence |\readsplineparams@| is used to extract this information. -Each spline type must provide a |\getsplineparams@| which -puts the information into easily usable form. - -\DOCMODE( -\xydef@\readsplineparams@{% - \expandafter\expandafter\expandafter\getsplineparams@\xysplineparams@ - \expandafter\expandafter\expandafter\getsplineedges@safe\xysplineedges@ @@} - -\xydef@\getsplineedges@safe#1@@{\DN@{#1}% - \ifx\next@\empty \DN@{\getsplineedges@.0pt;0.0pt,0.0pt;0.0pt,}% - \else \DN@{\getsplineedges@safe@#1@@}\fi \next@} - -\xydef@\getsplineedges@safe@#1;#2,#3@@{\DN@{#3}% -\splinetrace@{getsplineedges@safe}% - \ifx\next@\empty \DN@{\getsplineedges@#1;#2,0.0pt;0.0pt,}% - \else \DN@{\getsplineedges@#1;#2,#3}\fi \next@} -\DOCMODE) - -The edge locations are stored as $x.y$ -where $x+1$ = spline-segment number and -$y$ or $1-y$ = parameter value of the start, resp. finish, -in the segment $x+1$. - -\DOCMODE( -\xydef@\getsplineedges@#1;#2,#3;#4,{% - \global\dimen@i=#1\global\dimen5=#2\relax - \dimen@=#3\multiply\dimen@\m@ne \advance\dimen@\splinelength@ - \global\dimen3=\dimen@ - \dimen@=#4\relax - \ifdim\dimen@>\p@ \xywarning@{edge out-of-range: \the\dimen@}% - \count@=\dimen@ \divide\count@\p@ - \advance\dimen@-\count@\p@ \multiply\dimen@\m@ne - \advance\dimen@ \count@\p@ \advance\dimen@\p@ -\splinetrace@{\the\dimen@}% - \else - \multiply\dimen@\m@ne \advance\dimen@\p@ - \fi - \global\dimen7=\dimen@ } -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\noindent Sometimes \TeX\ will run short of memory when many curves are -used without a backend with special support for curves. In that case -the following commands, that obey normal \TeX\ groupings, may be -helpful: -% -\begin{defs1} -|\SloppyCurves| \cr -|\splinetolerance{|<dimen>|}| \cr -\end{defs1} -\noindent\unskip -% -allow adjustment of the tolerance used to typeset curves. The first sets -tolerance to .8pt, after which |\splinetolerance{0pt}| resets to -the original default of fine curves. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Some useful methods for accurate division by integers. - -\DOCMODE( -\xydef@\dimen@half{% - \advance\dimen@ \ifdim\dimen@<\z@-\fi 1sp \divide\dimen@\tw@} - -\xydef@\halve@dimen#1{\dimen@=#1\relax \dimen@half #1=\dimen@} - -\xydef@\dimen@nth#1#2{\dimen@=#2\relax \dimen@ii=#1sp % - \advance\dimen@ \ifdim\dimen@<\z@-\fi.5\dimen@ii - \divide\dimen@ by#1\relax #2=\dimen@} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Before constructing the curve we first examine the ``drop'' object, -setting it in an |\xybox|. The size of this object determines the -spacing of objects placed along the curve, via the {\em tolerance\/} -of the spline. This determines the maximum separation of places at -which objects will be dropped; \ie\ when two adjacent places would -be separated by more than this amount, the spline algorithm -constructs another place on the curve intermediate between these two. - -\noindent{\bf Note: } Alter the spline tolerance by adjusting the size -of the ``drop'' object. In particular, a dotted line can be achieved by -setting an empty object with non-zero size. If the size is zero then the -default tolerance is used. Initially this is .4pt; it may be altered -using |\splinetolerance|<dimen>, where <dimen> must be greater than -zero, else the initial tolerance is reset. - -\DOCMODE( -\xydef@\splinetolerance@#1{\dimen@=#1\relax - \ifdim\dimen@>\z@ \splinetol@=\dimen@ - \else\splinetol@=.4\p@\fi} - -\xylet@\splinedefaulttol@=\relax - -\xydef@\splinetolerance#1{\splinetolerance@{#1}% - \edef\splinedefaulttol@{\splinetol@=\the\splinetol@}} - -\splinetolerance\z@ - -\xydef@\SloppyCurves{\splinetolerance{.8\p@}} - -\xydef@\xylowtolerance@{\splinedefaulttol@ - \ifdim\splinetol@<\p@ \divide\splinetol@\tw@ \fi} -\DOCMODE) - -Similarly examine the ``connect'' object. If none has been specified -then there is no need to calculate the tangent direction at each -place along the curve. This saves on both time and memory requirement. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -"Procedure": -(1)~If |\xycrvdrop@| is empty, define |\splinedrop@| to expand -to |\copy\zerodotbox@|, thus creating a curve constructed from small dots. -Otherwise (2a)~set the |\splinebox@| with the specified object and -(2b)~use |\copy\splinebox@| as the expansion of |\splinedrop@|. -(3)~Set |\splinetol@| to be $\sqrt2\times$ maximum of width and -height+depth of the box. - -If |\xycrvconn@| is empty~(4)~then |\splineconn@| is set to |\relax|. -(5)~Otherwise it is necessary to reset the direction at each -place along the curve before dropping the object specified -by |\xycrvconn@|. - -\DOCMODE( -\xywarnifdefined\splinedrop@ -\xydef@\setstdsplinedrop@{% - \setbox\splinebox@=\hbox\bgroup - \setboxz@h{\expandafter\object\xycrvdrop@{}}% - \splinedefaulttol@ \dimen@=\wd\z@ \dimen@ii=\ht\z@ \advance\dimen@ii\dp\z@ - \ifdim\dimen@ii>\dimen@ \dimen@=\dimen@ii \fi \dimen@=1.4142\dimen@ - \ifdim\dimen@>\splinetol@ \splinetol@=\dimen@\else\dimen@=\splinetol@\fi - \dimen@=.5\wd\z@ - \ht\z@=\z@ \dp\z@=\z@ \wd\z@=\z@ \kern-\dimen@ \Drop@@ \kern\dimen@ - \edef\tmp@{\egroup \splinetol@=\the\splinetol@ - \ifInvisible@\noexpand\Invisible@true - \else\noexpand\Invisible@false\fi}\tmp@ - \edef\splinedefaulttol@{\splinetol@=\the\splinetol@}% - \def\splinedrop@{\copy\splinebox@\splineextra@@}} - -\xywarnifdefined\splineconn@ -\xydef@\stdsplineconn@{{\setsplinedir@ % %(5) - \setboxz@h\bgroup\expandafter\object\xycrvconn@{}% - \edef\tmp@{\egroup\L@c=\the\L@c \R@c=\the\R@c \D@c=\the\D@c \U@c=\the\U@c - \noexpand\def\noexpand\Drop@@}\expandafter\tmp@\expandafter{\Drop@@}% - \setboxz@h{\kern-\L@c \boxz@}% - \ht\z@=\z@ \dp\z@=\z@ \wd\z@=\z@ \Drop@@}} - -\xydef@\setcrvobjects@{\setstdsplinedrop@ \def\splineconn@{\stdsplineconn@}} -\xylet@\splineextra@@=\relax -\DOCMODE) - -\DOCMODE( -\xydef@\splinenear@#1#2#3#4{{\d@X=#1\advance\d@X-#2% - \ifdim\d@X<\z@ \d@X=-\d@X\fi - \ifdim\splinetol@<\d@X \aftergroup\splinefar@true - \else \d@Y=#3\advance\d@Y-#4\ifdim\d@Y<\z@ \d@Y=-\d@Y\fi - \ifdim\splinetol@<\d@Y\aftergroup\splinefar@true - \else \xydist@\d@X\d@Y - \ifdim\splinetol@<\dimen@ \aftergroup\splinefar@true - \else - \ifdim\dimen@<.1\splinetol@\aftergroup\splinetooclose@\fi - \fi\fi\fi}} - -\xydef@\splineadvance@@{\global\advance\splineval@\splinedepth@} -\DOCMODE) - -This stops objects being placed too close together along the spline. -It is necessary at the beginning of a segment with a non-zero edge. -Otherwise, with a large |\splinetolerance@|, the accuracy of the -place-finding mechanism results in being so deep in the tree that -objects placed at every level on the way up would be much too close. - -\DOCMODE( -\xydef@\splinetooclose@{\aftergroup\aftergroup\aftergroup\splinetooclose@@} -\xydef@\splinetooclose@@{\def\splineplotpt@{\relax}} -\DOCMODE) - -Each place along the curve is tested according to a |\splinetest@|. -Normally this is for visibility according to the extent of the objects -at the end-points of the curve. -When an edge is crossed then the |\splinecontinue| routine is called -to decide how the behaviour may change e.g. whether the recursion -should continue or exit to the top of the existing tree. - -\DOCMODE( -\xydef@\splinepoint@@{% -\splinetrace@{P@:(\the\X@c,\the\Y@c)::\the\splineval@;\the\splinedepth@}% - {\splinetest@\ifsplineplot@\relax\else\aftergroup\splinecontinue\fi}} - -\xydef@\splinepoint@{% - {\splinetest@\ifsplineplot@\aftergroup\splinecontinue\fi}} -\xylet@\splinepoint=\splinepoint@ - -\xydef@\splinecontinue@{% - \global\let\splinepoint=\splinepoint@@ - \global\let\splinecontinue=\splinecontinue@@} -\xydef@\splinecontinue@@{% - \global\let\splinepoint=\splinepoint@ - \global\let\splinecontinue=\relax} -\xylet@\splinecontinue=\splinecontinue@ - -\DOCMODE) - -Points where segments join lie at the top of the recursive tree. -They are tested directly against the objects at the endpoints, -in order to decide whether or not they are visible. - -\DOCMODE( -\xydef@\splineknotpoint@{{\X@p=\X@c \Y@p=\Y@c \cv@start - \the\Edge@c\@ne \ifInside@\else\aftergroup\splineknotpoint@@\fi}}% -\xydef@\splineknotpoint@@{{\X@p=\X@c \Y@p=\Y@c \cv@end - \the\Edge@c\@ne \ifInside@\else \aftergroup\splinepoint\fi}}% - -\xylet@\firstsplinepoint@=\splineknotpoint@ -\xylet@\lastsplinepoint@= \splineknotpoint@ -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -This routine is used to find where the spline crosses -the edges of the objects at $p$ and $c$. -First (1)~ we set up the tests which will determine when -the edge has been crossed. Then commence the scan.~(2) - -\DOCMODE( -\xydef@\splined@@@{% -\splinetrace@{finding end types}% -\splinetrace@{bstartPLACE@:\bstartPLACE@; bendPLACE@:\bendPLACE@}% - \DN@{\splinescan@}\ifx\bstartPLACE@\empty - \ifx\bendPLACE@\relax\def\bendPLACE@{1}\fi - \else\ifx\bstartPLACE@\relax - \else\ifx\bstartPLACE@\undefined - \else - \DN@{\splinescanbreak@}\ifx\bendPLACE@\relax\def\bendPLACE@{1}\fi - \DNii@{0}\ifx\bstartPLACE@\nextii@ - \DNii@{1}\ifx\bendPLACE@\nextii@\DN@{}% -% \else\DNii@{0.0}\ifx\bendPLACE@\nextii@\DN@{}\fi - \fi\fi % use the saved values - \fi\fi\fi \next@ }% %(2) - -\xydef@\splineStarttest@{{\X@p=\X@c \Y@p=\Y@c \cv@start \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}}% -\xydef@\splineEndtest@{{\X@p=\X@c \Y@p=\Y@c \cv@end \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}}% - -\xydef@\splineBreakStarttest@{{\X@p=\X@c \Y@p=\Y@c \cv@brstart \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}}% - -\xydef@\splineBreakEndtest@{{\X@p=\X@c \Y@p=\Y@c \cv@brend \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}}% -% \ifInside@\aftergroup\splineplot@true\else\aftergroup\splineplot@false\fi}}% - -\xylet@\splineStarttest=\splineStarttest@ -\xylet@\splineEndtest=\splineEndtest@ - -\xydef@\splineSlowStarttest{{\X@p=\X@c \Y@p=\Y@c \cv@start \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@maybe@@\else\aftergroup\splineplot@true\fi}}% -\xydef@\splineSlowEndtest{{\X@p=\X@c \Y@p=\Y@c \cv@end \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@maybe@@\else\aftergroup\splineplot@true\fi}}% -\xydef@\splineplot@maybe{\splineplot@false}% -\xylet@\splineplot@maybe@@=\splineplot@maybe -\DOCMODE) - -(3)~Start a new group and bind some macros appropriate -to finding the starting edge. -(4)~start the spline algorithm, using a small tolerance. -(5)~Close the group, thus removing the bindings of~(3). -(6)~Record the information, which has been stored globally. -(7)~Do the same for the ending edge. -(8)~Clear the global information. -After this, set the curve as usual.~(9) - -\DOCMODE( -\xydef@\splinescan@{\bgroup% - \expandafter\def\xysplineedges@{\z@;\z@,\z@;\z@,}% - \bgroup \cv@start - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% - \ifx\next@\nextii@ \gdef\splineedges@{\z@;\z@,}% - \else\aftergroup\splinestartScan@\fi - \egroup \relax - \bgroup \cv@end - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% - \ifx\next@\nextii@ - \getcrvsegsnum@ \edef\segmentnum@{\the\count@}% - \splineval@=\z@ \splineRecordEndValue@ - \else\aftergroup\splineendScan@\fi - \egroup \egroup - \expandafter\testsplineedges@\splineedges@;,@@% - \expandafter\edef\xysplineedges@{\splineedges@}% %(6) - \global\let\splineedges@=\relax % %(8) -\splinetrace@{edge params: \xysplineedges@}}% - -\xydef@\testsplineedges@#1;#2,#3;#4,#5@@{% - \DN@{#5}\ifx\next@\empty - \DNii@{#4}\ifx\nextii@\empty - \xynoedgespline@{end}\def\splineedges@{#1;#2,\z@;\z@,}\fi - \DNii@{#2}\ifx\nextii@\empty - \xynoedgespline@{start}\def\splineedges@{\z@;\z@,\z@;\z@,}\fi - \fi } -\xydef@\xynoedgespline@#1{\xywarning@{#1 edge of spline not found}}% - -\xydef@\splinestartScan@{\bgroup % %(3) -\splinetrace@{scan for start}% - \global\let\splineadvance@=\splineadvance@@ %(3) - \let\spline@start=\splinefindStart@ %(3) - \let\spline@end=\spline@end@@ %(3) - \let\splinefinish@=\splinefinish@@ - \let\splinewhich=\relax - \global\splinelength@=\z@ -% \let\splinerec@=\splineSrec@ - \def\splinerec@{\let\splinerec@=\splineSrec@ \splinedecast@@}% - \edef\splineedges@{}% - \expandafter\let\xysplineedges@\relax -% \bgroup - \xylowtolerance@ \splined@@ - \ifx\splineedges@\empty\expandafter\splineslowScan@\fi - \ifx\splineedges@\relax\expandafter\splinenostart@\fi - \egroup }% %(4) - -\xydef@\splineslowScan@{% - \let\splineStarttest=\splineSlowStarttest - \let\splinescanStarttest=\relax - \def\splinerec@{\let\splinerec@=\splineSrec@ \splinedecast@@}% - \splined@@ } - -\xydef@\splineslowEnd@{% - \global\let\splineEndtest=\splineSlowEndtest - \let\splinescanEndtest=\relax - \def\splinerec@{\let\splinerec@=\splineErec@ \splinedecast@@}% - \splined@@ } - -\xydef@\splinenostart@{% - \def\segmentnum@{1}\splinelength@=\z@ \splineval@=\z@ - \xynoedgespline@{start}\splineRecordValue@ } - -\xydef@\splineendScan@{\bgroup % %(3)<----------- - \bgroup % %(7) -\splinetrace@{scan for end}% - \global\let\splineadvance@=\splineadvance@@ - \let\spline@start=\splinefindEnd@ - \let\spline@end=\spline@end@@ - \let\splinefinish@=\splinefinish@@ - \let\splinewhich=\relax - \global\splinelength@=\z@ -% \let\splinerec@=\splineErec@ - \global\let\splineEndtest=\splineEndtest@ - \def\splinerec@{\let\splinerec@=\splineErec@ \splinedecast@@}% - \expandafter\def\expandafter\prevedges@\expandafter{\splineedges@}% - \xylowtolerance@ \splined@@ - \ifx\splineedges@\prevedges@\expandafter\splineslowScan@\fi - \egroup \egroup} - -\xydef@\splinescanbreak@{% -\splinetrace@{SCANBREAK}% - \gdef\breakedges@{}% - \DN@{0}\ifx\next@\bstartPLACE@ - \DN@{\bgroup \def\tmp@####1;####2,####3;####4,{% - \global\splineval@=####2\relax}% - \expandafter\expandafter\expandafter\tmp@\xysplineedges@ - \def\segmentnum@{1}\splineRecordBreakValue@ \egroup}% - \else - \bgroup \cv@start - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% - \ifx\next@\nextii@ \aftergroup\splinezerostart - \else\aftergroup\splinewidestart\fi - \egroup - \fi \next@ - \DN@{1}\ifx\next@\bendPLACE@ - \DN@{\bgroup \def\tmp@####1;####2,####3;####4,{% - \global\splineval@=####4\relax}% - \expandafter\expandafter\expandafter\tmp@\xysplineedges@ -%% \multiply\splineval@\m@ne \advance\splineval@\p@ -%% \def\segmentnum@{1} - \getcrvsegsnum@ \edef\segmentnum@{\the\count@}% - \global\multiply\splineval@\count@ - \splineRecordEndBreakValue@ \egroup}% - \else - \bgroup \cv@end - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% - \ifx\next@\nextii@ \aftergroup\splinezeroend - \else\aftergroup\splinewideend\fi - \egroup - \fi \next@ - \expandafter\def\expandafter - \xybreakedges@\expandafter{\breakedges@}% %(6) - \global\let\breakedges@=\relax % %(8) -\splinetrace@{break params: \xybreakedges@::\bstartPLACE@--\bendPLACE@}% - \expandafter\let\xysplineedges@\xybreakedges@ } - -\xydef@\getcrvsegsnum@{% sets \count@ - \count@=\ptsnum@\relax \ifnum\count@>\@ne\advance\count@\m@ne\fi} - -\xydef@\splinezerostart{\DN@{\bgroup -\splinetrace@{splinezerostart:}% - \dimen@=\bstartPLACE@\p@ - \global\splineval@=\dimen@ - \splineRecordBreakValue@ \egroup }} - -\xydef@\splinezeroend{\DN@{\bgroup -\splinetrace@{splinezeroend:}% - \dimen@=\bendPLACE@\p@ - \multiply\dimen@\m@ne \advance\dimen@\p@ - \def\segmentnum@{0}\global\splineval@=\dimen@ - \splineRecordEndBreakValue@ \egroup }} - -\xydef@\splinewidestart{\DN@{\bgroup - \splinetrace@{scan for start}% - \let\splinefbcontinue@=\breakstartcontinue@ - \let\splinef@pt=\splinef@breakpt - \let\splinef@end=\break@start - \edef\tmp@{{\bstartPLACE@}}% - \expandafter\splinealong@@\tmp@\z@>\endgroup\egroup }} - -\xydef@\splinewideend{\DN@{\bgroup - \splinetrace@{scan for wide end}% - \let\splinefbcontinue@=\breakendcontinue@ - \let\splinef@pt=\splinef@breakpt - \let\splinef@end=\break@end - \edef\tmp@{{\bendPLACE@}}% - \expandafter\splinealong@@\tmp@\z@<\endgroup\egroup }} - - -\xydef@\splineSrec@{{% -\splinetrace@{v=\the\splineval@ + d=\the\splinedepth@ : - (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c):Srec }% - \splineStarttest - \ifsplineplot@ - \ifdim\splinedepth@<.0001\p@ \aftergroup\splinefinish@ - \global\advance\splineval@ .5\splinedepth@ - \else\aftergroup\splinedecast@@ \fi - \else \aftergroup\splineadvance@ \fi}} - -\xydef@\splinefindStart@@{\bgroup \bgroup - \expandafter\expandafter\expandafter\getsplineparams@\xysplineparams@ - \global\let\splineadvance@=\splineadvance@@ - \global\let\splinepoint=\relax - \let\splinegoal@=\splineRecordValue@ \global\dimen5=\z@ - {\X@c=\X@p \Y@c=\Y@p \splinescanStarttest }%% first test initial point. -} - -\xydef@\splinefindStart@{% - \expandafter\crv@cnt@\xycrvptsnum@\relax - \ifnum\crv@cnt@>\tw@ - \crv@cnt@=\@ne \splineplot@false \splinesegment@{\crv@cnt@}% - {\splineStarttest %% test end of segment. - \ifsplineplot@\aftergroup\splineplot@true\fi}% - \ifsplineplot@ \else \searchforStartsegment@ \fi - \splinesegment@{\crv@cnt@}% -\splinetrace@{start is in segment \segmentnum@}% - \else \splinesegment@\@ne \fi - \splineplot@false \splinefindStart@@ -} -\DOCMODE) - -This finds the first spline segment whose endpoint is beyond the edge of -the object. - -\DOCMODE( -\xydef@\searchforStartsegment@{\splineplot@true\loop@ - \advance\crv@cnt@\@ne - \expandafter\count@\xycrvptsnum@\relax - \ifnum\count@=\crv@cnt@\expandafter\splineplot@false - \else - \splinesegment@{\crv@cnt@}{\splineStarttest - \ifsplineplot@\aftergroup\splineplot@false - \else\aftergroup\splineplot@true\fi }% - \fi \ifsplineplot@\repeat@ -} -\DOCMODE) - -Finding the end is similar, but the spline is searched in reverse order. - -\DOCMODE( -\xydef@\splinefindEnd@@{\bgroup \bgroup - \expandafter\expandafter\expandafter\getsplineparams@\xysplineparams@ -\splinetrace@{params:\xysplineparams@}% - \splinereverse@@ -\splinetrace@{params:\xysplineparams@}% - \global\let\splineadvance@=\splineadvance@@ - \global\let\splinepoint=\splinescanEndtest - \let\splinegoal@=\splineRecordEndValue@ \global\dimen5=\z@ - {\X@c=\X@p \Y@c=\Y@p \splinescanEndtest }%% first test initial point. -} - -\xydef@\splinereverse@@{\splinereverse@@@} -\xydef@\splinereverse@@@{% - \def\postspline@{\d@X=-\d@X \d@Y=-\d@Y}% - \dimen@ii=\X@c \X@c=\X@p \X@p=\dimen@ii - \dimen@ii=\Y@c \Y@c=\Y@p \Y@p=\dimen@ii - \global\dimen5=-\dimen5\relax - \global\advance\dimen5\splinelength@ } -\xydef@\postspline@{} - -\xydef@\splineErec@{{% - \dimen@=\splineval@ \advance\dimen@\splinedepth@ % -\splinetrace@{ER (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c);;; -\the\dimen@,\the\splinedepth@}% - \splineEndtest - \ifsplineplot@ - \ifdim\splinedepth@<.0001\p@ \aftergroup\splinefinish@ -% \global\advance\splineval@ .5\splinedepth@ - \else\aftergroup\splinedecast@@ \fi - \else \aftergroup\splineadvance@ \fi}} - -\xydef@\splinefindEnd@{% - \expandafter\crv@cnt@\xycrvptsnum@\relax - \ifnum\crv@cnt@>\tw@ - \advance\crv@cnt@\m@ne - \splineplot@false \splinesegment@{\crv@cnt@}% - {\X@c=\X@p \Y@c=\Y@p \splineEndtest %% test end of segment. - \ifsplineplot@\aftergroup\splineplot@true\fi }% - \ifsplineplot@ - \else \searchforEndsegment@ \fi - \splinesegment@{\crv@cnt@}% -\splinetrace@{end is in segment: \segmentnum@ }% - \else \splinesegment@\@ne \fi - \splineplot@false\splinefindEnd@@ -} -\xydef@\searchforEndsegment@{\splineplot@true\loop@ - \advance\crv@cnt@\m@ne - \ifnum\crv@cnt@=\z@\expandafter\splineplot@false - \else - \splinesegment@{\crv@cnt@}{\X@c=\X@p \Y@c=\Y@p \splineEndtest - \ifsplineplot@\aftergroup\splineplot@false - \else\aftergroup\splineplot@true\fi}% - \fi \ifsplineplot@\repeat@ -} -\DOCMODE) - -These are the tests, to determine when the edge-point has been found. - -\DOCMODE( -\xydef@\splinescanStarttest{% -\splinetrace@{SST (\the\X@c,\the\Y@c); \the\splinelength@, \the\splineval@}% - {\splineplot@false\splineStarttest - \ifsplineplot@\expandafter\splinefinish@\fi}} - -\xydef@\splinescanEndtest{% -\splinetrace@{SET (\the\X@c,\the\Y@c); \the\splinelength@, \the\splineval@}% - {\splineplot@false\splineEndtest - \ifsplineplot@\expandafter\splinefinish@\fi}} -\DOCMODE) - -\DOCMODE( -\xydef@\splineBrec@{{% - \dimen@=\splineval@ \advance\dimen@\splinedepth@ % -\splinetrace@{BR (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c);;; -\the\dimen@,\the\splinedepth@}% - \splineEndtest - \ifsplineplot@ \aftergroup\splineadvance@ \else - \ifdim\splinedepth@<.0001\p@ \aftergroup\splinefinish@ -% \global\advance\splineval@ .5\splinedepth@ - \else\aftergroup\splinedecast@@ \fi \fi}} - -\xydef@\splineBSrec@{{% -\splinetrace@{SR (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c);;; -\the\dimen@,\the\splinedepth@:SR}% - \splineStarttest - \ifsplineplot@ - \ifdim\splinedepth@<.0001\p@ \aftergroup\splinefinish@ - \global\advance\splineval@ .5\splinedepth@ - \else \advance\splineval@\splinedepth@ - \splinetest@ \advance\splineval@-\splinedepth@ - \ifsplineplot@\aftergroup\splineadvance@ - \else\aftergroup\splinedecast@@\fi - \fi - \else - \global\advance\splineval@\splinedepth@ - \aftergroup\splinefinish@ \fi }} - -\xydef@\splineBErec@{{% - \dimen@=\splineval@ \advance\dimen@\splinedepth@ % -\splinetrace@{BE (\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c);;; - \the\dimen@,\the\splinedepth@}% - \splineEndtest - \ifsplineplot@ - \ifdim\splinedepth@<.0001\p@ \aftergroup\splinefinish@ - \global\advance\splineval@ .5\splinedepth@ - \else \advance\splineval@\splinedepth@ - \splinetest@ \advance\splineval@-\splinedepth@ - \ifsplineplot@\aftergroup\splineadvance@ - \else\aftergroup\splinedecast@@\fi - \fi - \else - \ifdim\splinedepth@<\p@ \global\advance\splineval@\splinedepth@ \fi - \aftergroup\splinefinish@ \fi }} - -\xydef@\splinef@breakpt#1{% gobbles |\splinecancel| - \ifdim\splineval@>\z@ -\splinetrace@{found: val=\the\splineval@;(\the\X@c,\the\Y@c)}% - \else -\splinetrace@{found: val=\the\splineval@;(\the\X@p,\the\Y@p)}% - \fi \splinefbcontinue@ } - -\xydef@\splinef@pt@@{% - \ifdim\splineval@>\z@ -\splinetrace@{found: val=\the\splineval@;c:(\the\X@c,\the\Y@c)}% - \global\dimen@i=\X@c \global\dimen3=\Y@c - \else -\splinetrace@{found: val=\the\splineval@;p:(\the\X@p,\the\Y@p)}% - \fi - \setsplinedir@ \global\dimen5=\d@X \global\dimen7=\d@Y - \global\splineval@=\splineval@ - \aftergroup\splinefocus@ } - -\xydef@\findbreakwarning@#1{% - \xywarning@{#1 of break not found: bSTART=\bstartPLACE@, bEND=\bendPLACE@}% - \DN@{#1}\def\DNii@{start}\ifx\next@\nextii@\splineRecordBreakValue@ - \else\splineRecordEndBreakValue@\fi\egroup}% - -\xydef@\breakstartcontinue@{\bgroup \cv@start -%\xystatus@{SS}% - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% - \ifx\next@\nextii@ \aftergroup\breakstartfound@ - \else \aftergroup\breakstartcontinue@i\fi \egroup }% - -\xydef@\breakstartcontinue@i{% -\splinetrace@{move to start edge, from (\the\X@c,\the\Y@c): val=\the\splineval@ }% -% \global\let\splinetest@=\splineStarttest - \global\let\splineEndtest=\splineBreakStarttest@ - \global\let\splinetest@=\splineBreakStarttest@ -% \global\let\splinerec@=\splineSrec@ - \gdef\splinerec@{\global\let\splinerec@=\splineSrec@ \splinedecast@@}% - \global\let\splinepoint=\relax - \global\let\spline@end=\checkfoundSbreak@ -% \global\let\splinegoal@=\splineRecordBreakValue@ - \global\let\splinegoal@=\splineRecordSBreakValue@ - \global\let\splinefinish@=\splinefinish@@ } - -\xydef@\breakstartfound@{% -\splinetrace@{found start edge, at (\the\X@c,\the\Y@c): val=\the\splineval@ }% - \global\let\splinetest@=\splineStarttest - \gdef\splinerec@{\splinegoal@ \global\let\splinerec@=\splinefinish@ }% - \global\let\splinepoint=\relax - \global\let\spline@end=\relax %\checkfoundSbreak@ - \global\let\splinegoal@=\splineRecordBreakValue@ - \global\let\splinefinish@=\splinefinish@@ - } - -\xydef@\checkfoundSbreak@{% - \ifnum\xycrvptsnum@<\thr@@\DN@{\findbreakwarning@{start}}% - \else\DN@{\searchBreakSsegment@}\fi \next@ }% - -\xydef@\searchBreakSsegment@{% - \crv@cnt@=\segmentnum@ \DN@{}\count@=\crv@cnt@ - \DNii@{}\ifnum\splineval@=\z@ \ifnum\crv@cnt@=\@ne - \ifnum\xycrvptsnum@=\@ne\count@=\z@\DNii@{\egroup}\fi - \else \DN@{\egroup}\fi - \else \ifnum\splineval@=\m@ne - \else \advance\crv@cnt@\@ne \fi \fi - \ifnum\crv@cnt@=\xycrvptsnum@\relax - \ifnum\xycrvptsnum@>\tw@ \DNii@{\egroup}\fi - \DN@{\expandafter\splineRecordBreakValue@\nextii@}% - \else - \DN@{\splinesegment@{\crv@cnt@}\splinesetparams@ - \splined@@ \egroup}% - \fi \next@ } - -\xydef@\checkfoundEbreak@{% - \ifnum\xycrvptsnum@<\thr@@\DN@{\findbreakwarning@{end}}% - \else\DN@{\searchBreakEsegment@}\fi \next@ }% - -\xydef@\searchBreakEsegment@{% - \crv@cnt@=\segmentnum@ \DN@{}\count@=\crv@cnt@ - \DNii@{}\ifnum\splineval@=\z@ \ifnum\crv@cnt@=\@ne - \ifnum\xycrvptsnum@=\@ne\count@=\z@\DNii@{\egroup}\fi - \else\DN@{\egroup}\fi - \else \advance\crv@cnt@\m@ne \fi - \ifnum\count@=\z@ -% \ifnum\crv@cnt@=\z@ - \ifnum\xycrvptsnum@>\tw@ \splineval@=\m@ne\p@ - \DNii@{\egroup}\fi - \DN@{\expandafter\splineRecordEndBreakValue@\nextii@}\else - \DN@{\splinesegment@{\crv@cnt@}\splinereverse@ - \readsplineparams@ \splined@@ \egroup}% - \fi \next@ } - -\xydef@\break@start{\egroup \egroup -\splinetrace@{scan for start}% - \global\let\splineadvance@=\splineadvance@@ %(3) - \let\spline@start=\splinefindBStart@ %(3) - \let\spline@end=\egroup - \let\splinefinish@=\splinefinish@@ - \let\splinewhich=\relax - \global\let\splineadvance@=\splineadvance@@ - \global\let\splinepoint=\relax - \let\splinegoal@=\splineRecordBreakValue@ - \global\dimen5=\z@ \global\splinelength@=\z@ - \let\splinerec@=\splineSrec@ - \def\breakedges@{}% - \bgroup \bgroup \splined@@ } - -\xydef@\splinefindBStart@{\bgroup -% \global\splineval@=\z@ \global\splinedepth@=.5\p@} - \global\splineval@=\z@ \splinedepth@=.5\p@} - -\xydef@\breakendcontinue@{\bgroup - \edef\tmp@{\X@p = \the\X@c \Y@p=\the\Y@c}\cv@end\tmp@ % <--- irrelevant ? - \expandafter\DN@\expandafter{\the\Edge@c}\DNii@{\zeroEdge}% -%\xystatus@{EE}% - \ifx\next@\nextii@ \aftergroup\breakendfound@ - \else\aftergroup\breakendcontinue@i\fi \egroup }% - -\xydef@\breakendcontinue@i{% -\splinetrace@{move to end edge, from (\the\X@c,\the\Y@c): val=\the\splineval@ }% -% \global\let\splinetest@=\splineEndtest - \global\let\splineEndtest=\splineBreakEndtest@ - \global\let\splinetest@=\splineBreakEndtest@ - \gdef\splinerec@{\global\let\splinerec@=\splineErec@\splinedecast@@}% - \global\let\splinepoint=\relax - \global\let\spline@end=\checkfoundEbreak@ -% \global\let\splinegoal@=\splineRecordEndBreakValue@ - \global\let\splinegoal@=\splineRecordEBreakValue@ - \global\let\splinefinish@=\splinefinish@@ - \splinerec@ } - -\xydef@\splineRecordEBreakValue@{%\getcrvsegsnum@ -\splinetrace@{\the\count@\space segments, \the\splineval@}% -% \ifnum\segmentnum@>\z@ \dimen@=\segmentnum@\p@ \else \dimen@=\p@\fi -% \advance\dimen@-\splineval@\relax -% \ifnum\count@>\@ne \divide\dimen@\count@\fi -% \global\splineval@=\dimen@ - \splineRecordEndBreakValue@ } - -\xydef@\splineRecordSBreakValue@{\getcrvsegsnum@ - \dimen@=\splineval@ - \advance\dimen@\segmentnum@\p@ \advance\dimen@-\p@ - \dimen@nth\count@\dimen@ - \global\splineval@=\dimen@ \def\segmentnum@{1}% - \splineRecordBreakValue@ } - -\xydef@\breakendfound@{% -\splinetrace@{found end edge, at (\the\X@c,\the\Y@c): val=\the\splineval@ }% - \global\let\splinetest@=\splineEndtest - \gdef\splinerec@{\splinegoal@ \global\let\splinerec@=\splinefinish@}% - \global\let\splinepoint=\relax - \global\let\spline@end=\relax %\checkfoundEbreak@ - \global\let\splinegoal@=\splineRecordEndBreakValue@ - \global\let\splinefinish@=\splinefinish@@ } - - -\xydef@\break@end{\egroup \egroup - \global\let\splineadvance@=\splineadvance@@ - \let\spline@start=\splinefindBEnd@ - \let\spline@end=\egroup - \let\splinefinish@=\splinefinish@@ - \let\splinewhich=\relax - \global\let\splineadvance@=\splineadvance@@ - \global\let\splinegoal@=\splineRecordEndBreakValue@ - \global\splinelength@=\z@ - \let\splinerec@=\splineErec@ - \global\let\splineEndtest=\splineEndtest@ - \bgroup \splined@@ } - -\xydef@\splinefindBEnd@{\bgroup\bgroup - \splinereverse@ \readsplineparams@ - \global\splineval@=\z@ } -\DOCMODE) - -This appends the new information to that currently stored in the control -sequence referenced by |\xysplineparams@|. It is temporarily stored -globally in |\splineparams@|, to be later transferred to -(the c.s. referenced by) |\xysplineparams@| when at the appropriate -level of groupingl. - -\DOCMODE( -\xydef@\splineRecordValue@{% - \ifx\unknown\segmentnum@\relax - \else - \getcrvsegsnum@ - \dimen@=\splineval@ \advance\dimen@ \segmentnum@\p@ - \advance\dimen@-\p@ \dimen@nth\count@\dimen@ - \global\splineval@=\dimen@ - \fi - \xdef\splineedges@{\splineedges@\the\splinelength@;\the\splineval@,}% -\splinetrace@{found edge: \splineedges@}} - -\xydef@\splineRecordEndValue@{% - \ifx\unknown\segmentnum@\relax - \else - \getcrvsegsnum@ - \dimen@=\splineval@ \advance\dimen@ \count@\p@ - \advance\dimen@-\segmentnum@\p@ \dimen@nth\count@\dimen@ - \global\splineval@=\dimen@ - \fi - \xdef\splineedges@{\splineedges@\the\splinelength@;\the\splineval@,}% -\splinetrace@{found edge: \splineedges@}} - -\xydef@\splineRecordBreakValue@{% - \ifx\unknown\segmentnum@\relax - \else\expandafter\advance\expandafter\splineval@\segmentnum@\p@ - \count@=\segmentnum@\relax - \ifnum\count@>0 \advance\splineval@-\p@ \fi\fi -% \ifx\breakedges@\relax\relax\else\ifx\breakedges@\empty\else -% \ifdim\splineval@<\p@\ifdim\splineval@>\z@ -% \expandafter\testbreakedges@\breakedges@ @% -% \fi\fi\fi\fi - \xdef\breakedges@{\breakedges@\the\splinelength@;\the\splineval@,}% - \global\let\spline@end=\egroup -\splinetrace@{found break edge: \breakedges@}} - -\xydef@\splineRecordEndBreakValue@{% - \ifx\unknown\segmentnum@\relax - \else\count@=\segmentnum@\relax \ifnum\count@=\z@ - \else \getcrvsegsnum@ - \count@@=\count@ \advance\count@@-\segmentnum@\relax - \dimen@=\splineval@ \advance\dimen@ \count@@\p@ - \dimen@nth\count@\dimen@ - \global\splineval@=\dimen@ - \fi\fi -% \multiply\splineval@\m@ne \advance\splineval@\p@ % <---------- !!! - \ifdim\splineval@<\z@ \relax\splineval@=\z@ \fi - \ifx\breakedges@\relax\relax\else\ifx\breakedges@\empty\else - \ifdim\splineval@<\p@\relax \ifdim\splineval@>\z@ - \expandafter\testbreakedges@\breakedges@ @% - \fi\fi\fi\fi - \xdef\breakedges@{\breakedges@\the\splinelength@;\the\splineval@,}% - \global\let\spline@end=\egroup -\splinetrace@{found break edge: \breakedges@}} - -\xydef@\testbreakedges@#1;#2,#3@{\bgroup \dimen@=#2\relax - \advance\dimen@\splineval@ \advance\dimen@-\p@ -\splinetrace@{testbreak: #1;#2,#3@ \the\splineval@::\the\dimen@}% - \DN@{\egroup}\ifdim\dimen@>\z@ - \edef\next@{\egroup\def\noexpand\breakedges@{#1;1pt,#3}}% - \else\ifdim\zz@\dimen@ - \edef\next@{\egroup\def\noexpand\breakedges@{#1;1pt,#3}}% - \fi \fi \next@ } - -\xydef@\splineRecordBreakEValue{% - \ifdim\splineval@>\z@ - \splineval@=-\splineval@ \advance\splineval@\p@ \fi - \splineRecordBreakValue@ }% -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Use the following distance approximation: - -$$ -dist = \cases{ -dX + .5 dY/dX dY & if $dY/dX dY \lt (\sqrt2-1)\times dX $\cr -{3\sqrt2\over4} dX + {\sqrt2\over4} dY/dX dY -& if $(\sqrt2-1)\times dX \lt dY/dX dY \lt dX $\cr -}$$ -and similarly, interchanging $dY$ and $dX$ when $dY \gt dX$. - -$\sqrt2 \approx 1.41422$,\ -$(\sqrt2)/2 \approx 0.70711$,\ -$(\sqrt2)/4 \approx 0.353555$,\ -$3(\sqrt2)/4 \approx 1.060665$ - -\DOCMODE( -\xydef@\xydist@#1#2{\ifdim#1>#2\relax - \quotient@@\tmp@#2#1\expandafter\dimen@ii\tmp@#2\relax - \ifdim\dimen@ii>.41422#1\relax - \dimen@=1.060665#1\advance\dimen@ .353555\dimen@ii\relax - \else \dimen@=#1\advance\dimen@.5\dimen@ii\fi - \else - \quotient@@\tmp@#1#2\expandafter\dimen@ii\tmp@#1\relax - \ifdim\dimen@ii>.41422#2\relax - \dimen@=1.060665#2\advance\dimen@ .353555\dimen@ii\relax - \else \dimen@=#2\advance\dimen@.5\dimen@ii\fi - \fi} -\DOCMODE) - -\DOCMODE( -\xydef@\splineDadvance@{\splineadvance@@ - \expandafter\splineDadvance@@\splineDadvance@@@} -\xydef@\splineDadvance@@#1#2#3#4{% - {\d@X=#1\advance\d@X-#2\ifdim\d@X<\z@ \d@X=-\d@X\fi - \d@Y=#3\advance\d@Y-#4\ifdim\d@Y<\z@ \d@Y=-\d@Y\fi - \xydist@\d@X\d@Y - \global\advance\splinelength@\dimen@ -\splinetrace@{d=(\the\d@X,\the\d@Y): v=\the\splineval@: l=\the\splinelength@}% -}} -\DOCMODE) - -\DOCMODE( -\xydef@\spline@end@{\lastsplinepoint@ \egroup \egroup - \ht\z@=\z@ \dp\z@=\z@ \wdz@=\z@ \boxz@}% -\gdef\splinetest@{\splineplot@true} -\xydef@\spline@end@@{\egroup \egroup} -\DOCMODE) - - - ...value for |\splinerec@| for the fast find... - -\DOCMODE( -\xydef@\splinefrec@{{% - \advance\splineval@\splinedepth@ -\splinetrace@{F:(\the\X@p,\the\Y@p);(\the\X@c,\the\Y@c);; -\the\splineval@;\the\splinedepth@}% - \ifdim\dimen5=\splineval@ \aftergroup\splinefinishf@ - \else \dimen@=\dimen5\advance\dimen@-\splineval@ - \ifdim\dimen@<\z@ \dimen@=-\dimen@ \fi - \ifdim\dimen@<.0001\p@ \aftergroup\splinefinishf@ - \else - \ifdim\dimen5<\splineval@\aftergroup\splinedecast@@ - \else \aftergroup\splineadvance@ - \fi\fi\fi}} - -\xydef@\splinefinishf@{\global\advance\splineval@\splinedepth@ - \splinefinish@}% -\DOCMODE) - -The macro |\spline@find#1#2| attempts to finds a specific point on a single -spline segment. - |#1| is the parameter value, in the range [0,1] on that segment; - |#2| is a <dimen> denoting how much further to slide along the segment. -It really only checks whether |#2| has a negative value before passing the -information to |\spline@@find#1#2|, which does the actual search. - -If |#2| is negative then the spline segment is searched in the reverse direction, -starting at its endpoint. -This is done by reversing the order of the control points, hence the parameter -value found as $x$ implies that we really want $1-x$ on the un-reversed segment. -Similarly the resulting vaules for |\d@X| and |\d@Y| must be negated. -The instructions to do this are loaded into a macro |\postfind@| which is expanded -once the search has been completed. -For an unreversed segment |\postfind@| expands to |{}|. - -\DOCMODE( -\xydef@\spline@find#1#2#3{% -\splinetrace@{spline@find #1 #2 #3}% - \readsplineparams@ - \global\let\splinefinish@=\splinefinish@@ - \global\let\splinegoal@=\splinef@pt - \global\let\splinepoint=\relax - \dimen@=#1\relax\dimen@ii=#2\relax - \ifdim\dimen@ii=\z@ \def\postfind@{}% - \else\def\postfind@{}% - \ifdim\dimen@ii<\z@ \splinereverse@ - \readsplineparams@ -\splinetrace@{reverse orientation: (\the\X@p,\the\Y@p),(\the\X@c,\the\Y@c)}% - \dimen@=#1\relax\dimen@ii=#2\relax - \multiply\dimen@\m@ne \advance\dimen@\p@ \multiply\dimen@ii\m@ne - \def\postfind@{\d@X=-\the\d@X \d@Y=-\the\d@Y \noexpand\reversesplineval@}% - \fi\fi - \expandafter\splinetrace@\expandafter{\xysplineparams@}% - \edef\next@{\noexpand\spline@@find{\the\dimen@}{\the\dimen@ii}{#3}}% - \next@ } - -\xydef@\reversesplineval@{\splineval@=-\splineval@ \advance\splineval@\p@ } -\DOCMODE) - - - -\DOCMODE( -\xydef@\spline@@find#1#2#3{% -\splinetrace@{spline@@find #1 #2 #3}% - \let\splinerec@=\splinefrec@ - \global\let\splineadvance@=\splineadvance@@ - \dimen5=#1\relax - \ifdim #2=\z@\relax - \ifdim #1=\z@\relax \bgroup - \let\splined@@=\spline@@knot - \global\splineval@=\m@ne\p@ - \else\ifdim #1=\p@\relax \bgroup - \let\splined@@=\spline@@knot - \global\splineval@=\z@ - \else - \global\splineval@=\z@ - \global\let\splineadvance@=\splineadvance@@ - \DN@{#3}\ifx\next@\empty \setsplinetest@\splineval@>{#1}{}% - {{\ifdim\splineval@=\dimen5\aftergroup\splineplot@false\fi}}% - \else\DNii@{>}\ifx\next@\nextii@ - \setsplineundertest@\splineval@>{#1}{}{}% - \let\splinerec@=\splineBSrec@ - \else\DNii@{<}\ifx\next@\nextii@ - \setsplineundertest@\splineval@>{#1}{}{}% - \let\splinerec@=\splineBErec@ - \else\xywarning@{unknown find-mode: #3}\fi\fi\fi - \fi\fi - \else - \global\splineval@=\z@ - \def\splineslidetest@@{% - \setsplinetest@\splinelength@<{#2}{}{}}% - \let\splinefinish@=\splinefcontinue@ - \fi - \let\spline@end=\splinef@end - \let\splinepoint@=\relax - \splinelength@=\z@ - \def\spline@start{\bgroup\xylowtolerance@}% - \splined@@ } - -\xydef@\spline@@knot{% - \let\setsplinedir@=\setsplineknotdir@ - \splinesetparams@\spline@start -% \global\splinedepth@=\p@ - \splinedepth@=\p@ - \global\dimen@i=\X@p \global\dimen3=\Y@p - \splinefinishf@ \spline@end \egroup } - -\xydef@\splinefcontinue@{% -\splinetrace@{sliding... from (\the\X@c,\the\Y@c): val=\the\splineval@ }% - \global\let\splinerec@=\splinerec@@ - \global\splinelength@=\z@ - \global\splineval@=\splineval@ - \global\let\splinepoint=\splinefindtest@ - \global\let\splinegoal@=\splinef@pt - \global\let\splineadvance@=\splineDadvance@ - \global\let\splinefinish@=\splinefinish@@ - \splineslidetest@@ - } - -\xydef@\splinefindtest@{% -\splinetrace@{SFT (\the\X@c,\the\Y@c); \the\splinelength@, \the\splineval@}% - {\splineplot@false\splinetest@ - \ifsplineplot@\expandafter\splinefinishf@\fi}} - -\def\setsplineundertest@#1#2#3#4#5{% -\splinetrace@{setsplineundertest@: #1,#2,#3,#4,#5,}% - \DNii@{\gdef\splinetest@}% - \DN@##1\next{\def\tmp@{{\splineplot@false - \ifdim#1#2##1\relax #4\else\splineplot@true#5\fi }}}% - \next@#3\relax\next - \expandafter\nextii@\tmp@ } - -\xydef@\splinef@end{\edef\tmp@{\egroup\splinelength@=\the\splinelength@}\tmp@} -\xydef@\splinef@pt{% - \ifdim\splineval@>\z@ -\splinetrace@{found: val=\the\splineval@;c:(\the\X@c,\the\Y@c)}% - \global\dimen@i=\X@c \global\dimen3=\Y@c - \else -\splinetrace@{found: val=\the\splineval@;p:(\the\X@p,\the\Y@p)}% - \fi - \setsplinedir@ \global\dimen5=\d@X \global\dimen7=\d@Y - \global\splineval@=\splineval@ - \aftergroup\splinefocus@ } -\DOCMODE) - -\DOCMODE( -\def\setsplinetest@#1#2#3#4#5{% - \DNii@{\gdef\splinetest@}% - \DN@##1\next{\def\tmp@{{\splineplot@false \ifdim#1#2##1\relax - #4\else\splineplot@true#5\fi}}}% - \next@#3\relax\next - \expandafter\nextii@\tmp@ }% -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\splinefocus@{% - \d@X=\dimen5\relax \d@Y=\dimen7\relax \setsplinedir@ } - -\xydef@\splinesegment@#1{} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -There are some extra hooks. - -\DOCMODE( -\xydef@\xyprecurve@{} -\xydef@\xypostcurve@{} -\DOCMODE) - -\DOCMODE( -\xydef@\splineset@{% -\splinetrace@{splineset@:}% - \ifx\bstartPLACE@\empty %\splinetrace@{invisible curve}% - \DN@{\xyprecurve@ - \edef\tmp@{\egroup \X@max=\the\X@max \X@min=\the\X@min - \Y@max=\the\Y@max \Y@min=\the\Y@min}\tmp@ \xypostcurve@ }% - \else - \DN@{\xyprecurve@ \xysplinespecialcases@ - \edef\tmp@{\egroup \X@max=\the\X@max \X@min=\the\X@min - \Y@max=\the\Y@max \Y@min=\the\Y@min}\tmp@ \xypostcurve@ }% - \fi - \next@ } -\DOCMODE) - -For the actual setting, provide hooks which will allow -alternative back-ends to be used in the special cases. - -\DOCMODE( -\xydef@\xysplinespecialcases@{% - \ifx\empty\xycrvdrop@ - \ifx\empty\xycrvconn@ \DN@{\splinesolid@}% - \else \DN@{ \dir{-}}\ifx\next@\xycrvconn@ \DN@{\splinesolid@}% - \else \DN@{ \dir 2{-}}\ifx\next@\xycrvconn@ \DN@{\splinedoubled@}% - \else \DN@{ \dir{=}}\ifx\next@\xycrvconn@ \DN@{\splineribboned@}% - \else \DN@{ \dir {2.}}\ifx\next@\xycrvconn@ \DN@{\splinedoubled@}% - \else \DN@{ \dir 3{-}}\ifx\next@\xycrvconn@ \DN@{\splinetrebled@}% - \else \DN@{ \dir {3.}}\ifx\next@\xycrvconn@ \DN@{\splinetrebled@}% - \else \DN@{ \dir{--}}\ifx\next@\xycrvconn@ \DN@{\splinedashed@}% - \else \DN@{ \dir{.}}\ifx\next@\xycrvconn@ \DN@{\splinedotted@}% - \else \DN@{ \dir{:}}\ifx\next@\xycrvconn@ \DN@{\splinedbldotted@}% - \else \ifdim\splinetol@>\z@ \else \splinedefaulttol@ \fi - \DN@{\splineset@@}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \else - \DN@{\splineset@@}% - \fi \ifInvisible@\DN@{}\fi \next@ } -\DOCMODE) - -The special cases are handled just like the normal case except -However the control sequence names provide a place for -rebinding to accomodate alternative back-ends. - -\DOCMODE( -\xydef@\splinesolid@{\setbox\splinebox@=\zerodot \def\xycrvdrop@{ }% - \def\xycrvconn@{}\splineset@@} - -\xydef@\splinedoubled@{\splinedefaulttol@\def\xycrvdrop@{ }\def\splinedrop@{}% - \def\xycrvconn@{!C\dir2{.}}\splineset@@} - -\xydef@\splineribboned@{\splinedefaulttol@\def\xycrvdrop@{ }\def\splinedrop@{}% - \def\xycrvconn@{!C\dir{:}}\splineset@@} - -\xydef@\splinetrebled@{\splinedefaulttol@\def\xycrvdrop@{ }\def\splinedrop@{}% - \def\xycrvconn@{!C\dir3{.}}\splineset@@} - -\xydef@\splinedashed@{\splinetol@=1.5pc \def\xycrvdrop@{ }%+=<10pt>[o]{}}% - \def\splinedrop@{}\edef\xycrvconn@{\noexpand!C\noexpand\dir{\addDASH@{}}}% - \splineset@@} - -\xydef@\splinedotted@{\setbox\splinebox@=\zerodot \def\xycrvdrop@{ }% - \splinetol@=1.5\jot \def\xycrvconn@{}\splineset@@} - -\xydef@\splinedbldotted@{\def\xycrvdrop@{ }\def\splinedrop@{}% - \splinetol@=1.5\jot \def\xycrvconn@{!C\dir{:}}\splineset@@} - -\DOCMODE) - -This establishes the test appropriate to actually setting -the spline curve. Global definitions are used. -This may not always be necessary!! - -\BUG: the |7.5pt| below should be the |\Step@@| method to be included. - -\DOCMODE( -\xydef@\splineset@@{% - \readsplineparams@ - \ifx\xycrvdrop@\empty \splinetol@=7.5\p@ - \def\splinedefaulttol@{\splinetol@=7.5\p@}\def\splinedrop@{}% - \else\edef\splinedefaulttol@{\splinetol@=\the\splinetol@}\fi - \ifx\xycrvconn@\empty \def\splineconn@{}\fi -\splinetrace@{set the curve: >\the\dimen5, <\the\dimen7}% - \global\let\splineadvance@=\splineadvance@@ - \let\splinerec@=\splineTrec@ - \def\splineStarttest{\splinetest@}% - \global\let\splinepoint=\relax %6 - \let\spline@start=\spline@start@ - \let\spline@end=\spline@end@ %5 - \ifdim\dimen7=\p@ - \gdef\splinecontinue{\splinesetting@ - \global\let\splinetest@=\splineplot@true}% - \else - \ifdim\dimen7=\tw@\p@ -%% \ifdim\bendPLACE@\p@=\z@ \emptyspline@ \else - \ifdim\bendPLACE@\p@=\p@ %\emptyspline@ - \fi %%\fi - \else - \xdef\splinecontinue{\noexpand\setsplinetest@ - \splineval@>{\the\dimen7}{\noexpand\splinebreakcancel@}{}% - \noexpand\splinesetting@ }% - \fi\fi - \ifdim\dimen7>\z@ \DN@{\splinesetting@\splinecontinue}% - \ifdim\zz@{\dimen5}% - \else - \edef\next@{\noexpand\setsplinetest@ - \splineval@<{\the\dimen5}{}% - {\noexpand\expandafter\noexpand\splinecontinue}% - \noexpand\splinesetting@ }% - \fi - \else\DN@{\dimen5=\p@}\fi % ifdim\dimen7=\z@ - \next@ -% - \ifdim\dimen5=\p@\DN@{}\else\DN@{\splined@@}\fi \next@ - } - -\xydef@\emptyspline@{\xywarning@{empty curve subsegment}% -\splinetrace@{bstartPLACE@=\bstartPLACE@, bendPLACE@=\bendPLACE@, - empty segment}% - \gdef\splinecontinue{\splinesetting@ - \global\let\splinetest@=\splineplot@false - \global\dimen5=\z@ }} -\DOCMODE) - -|\splineTrec@| is the initial value for |\splinerec@| when a spline -is being set. It descends the tree of places on the spline (1) until the -required parameter value is found (2a) or is sufficiently close (2b). -At this point call |\splinesetting@| and |\splinecontinue| to -setup, and proceed with, the actual type-setting. - -\DOCMODE( -\xydef@\splineTrec@{{% - \advance\splineval@\splinedepth@ % (1) - \ifdim\dimen5=\splineval@ % (2a) - \aftergroup\splinecontinue % (3) - \else \dimen@=\dimen5\advance\dimen@-\splineval@ - \ifdim\dimen@<\z@ \dimen@=-\dimen@ \fi - \ifdim\dimen@<.001\p@ % possibly too high ? % (2b) - \aftergroup\splinecontinue % (3) - \else - \ifdim\dimen5<\splineval@\aftergroup\splinedecast@@ % (1) - \else \aftergroup\splineadvance@ % (1) - \fi\fi\fi}} -\DOCMODE) - -Setting the curve uses the current |\splinerec@@| and -sets |\splinepoint| to |\splineplotpt@| to cause objects to be typeset. -This must be done via a |\gdef| rather than a |\global\let| -since it is sometimes necessary to omit the object when it would -be too close, see |\splinetooclose@|. - -\DOCMODE( -%\xydef@\splinesetting@{\xyFN@\splinesetting@@} -\xydef@\splinesetting@{\splinesetting@@} - -\xydef@\splinesetting@@{% -\splinetrace@{splinesetting@@:}% - \ifdim\splinedepth@=\z@ \splinedepth@=\p@ \fi - \ifdim\splinedepth@=\p@ - \def\splinerec@{\global\let\splinerec@=\splinerec@@\splinedecast@@}% - \else \global\let\splinerec@=\splinerec@@ \fi - \gdef\splinepoint{\splineplotpt@}} -\DOCMODE) - -This handles, for each point of the curve, -whether to place an <object> or horizontal glue. - -\DOCMODE( -\xydef@\splineplotpt@{{\global\advance\dimen@i-\X@c - \splinetest@ \DN@{\splineglue@}\ifsplineplot@ -% \splineStarttest@ \ifsplineplot@ -% \splineEndtest@ \ifsplineplot@ - \DN@{\dosplineplotpt@}% -% \fi\fi - \fi \next@ \global\dimen@i=\X@c \global\dimen3=\Y@c }} - -\xydef@\splineglue@{\hglue-\dimen@i -\splinetrace@{N:(\the\X@c,\the\Y@c);;\the\dimen@i;\the\dimen3% - ,\the\splinelength@,\the\splineval@,\the\splinedepth@}} - -\xydef@\dosplineplotpt@{\ifdim\dimen@i<\z@ - \raise\Y@c\hbox to-\dimen@i{\hfill\splinedrop@}% - \else \kern-\dimen@i\raise\Y@c\hbox{\splinedrop@}\fi - \ifx\splineconn@\relax\else\raise\Y@c\hbox{% - \setboxz@h{\splineconn@}\Drop@@}\fi -\splinetrace@{P:(\the\X@c,\the\Y@c);;\the\dimen@i;\the\dimen3 - ,\the\splinelength@,\the\splineval@,\the\splinedepth@}} -\DOCMODE) - -These handle the ``cleaning up'' after a point on the curve has been located. - -\DOCMODE( -\xydef@\splinefinish@@{\postspline@ \splinegoal@ \splinecancel@ } - -\xydef@\splinecancel@{% - \global\let\splinerec@=\relax - \global\let\splinepoint=\relax - \global\let\splinecontinue=\relax -% \global\let\splinedecast@@=\relax - \global\let\splinedecast@=\relax - } - -\xydef@\splinebreakcancel@{\bsplinecancel@ \splinecancel@} -\xydef@\bsplinecancel@{\gdef\lastbspline@{\leave@\leave@}% - \global\let\middlebspline@=\lastbspline@ } - -\xydef@\splinegoal@{\ifdim\splineval@>\z@ - \global\dimen@i=\X@c \global\dimen3=\Y@c \fi - \global\splineval@=\splineval@ \global\splinelength@=\splinelength@ -% \setsplineTangent@ } - \splinesetdir@ } - -\xylet@\splinefinish@\splinefinish@@ -\xylet@\splinewhich\splineDwhich@ - -\xydef@\squinewhich@{% - \ifdim\dimen5>\squinelength % \X@c=\L@c \Y@c=\D@c - \d@X=\X@c \d@Y=\Y@c \advance\d@X-\L@c \advance\d@Y-\U@c - \advance\squineval-\squinedepth - \else \X@c=\X@p \Y@c=\Y@p \advance\squineval-\squinedepth - \d@X=\L@c \d@Y=\U@c \advance\d@X-\X@p \advance\d@Y-\Y@p \fi - \d@X=-\d@X \d@Y=-\d@Y %%% hack which works. - \squinefinish} -\xydef@\squineDwhich@{% - \ifdim\dimen5>\squinelength % \X@c=\L@c \Y@c=\D@c - \d@X=\X@c \d@Y=\Y@c \advance\d@X-\L@c \advance\d@Y-\U@c - \else \X@c=\X@p \Y@c=\Y@p \advance\squineval-\squinedepth - \d@X=\L@c \d@Y=\U@c \advance\d@X-\X@p \advance\d@Y-\Y@p \fi - \d@X=-\d@X \d@Y=-\d@Y %%% hack which works. - \squinefinish} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsubsection{B\'ezier quadratic splines --- squines} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\xyquadbezier@{% - \global\let\splinerec@=\relax - \addtocrvpts@{\def\crvconnect@{\squineconnect@}}% - \xyquadmethods@ \let\splinesegment@=\squinesegment@ - \begingroup\setcrvobjects@ \xysplineparams@ \splined@@@ - \bgroup \setupsquine@ \squined@ \splineset@ \savespline@ } - -\xydef@\xyquadmethods@{% - \def\crvconnect@{\squineconnect@}% - \def\splinereverse@@{\splinereverse@@@}% - \let\getsplineparams@=\getsquineparams@ - \let\spline@start@=\squine@start@ - \let\splinedecast@@=\squinedecast@ - \let\splinerec@@=\squinerec@ - \let\splined@@=\squined@@ - \let\splineIpt@@=\squineIpt@ - \let\splineIadvance@@=\squineIadvance@ - \let\splineinfo@=\squineinfo@ - \let\setsplinedir@=\setsquinedir@ - \let\splinetestcvxhull@=\squinetestcvxhull@ - \let\setsplineknotdir@=\setsquineknotdir@ - \let\splinereverse@=\squinereverse@ - \let\splineDadvance@@@=\squineDadvance@@@ - \let\splinesetparams@=\squinesetparams@ - \let\splineplot@maybe@@=\squineplot@maybe -} - -\xydef@\squineconnect@{\splineconnect@ \crvconnect@@ - \let\splinesegment@=\squinesegment@ }% - -\xydef@\squinesegment@#1{\xyquadmethods@ \def\segmentnum@{1}% - \setupsquine@ \squined@ } - -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Use the registers |\A@| and |\B@| to store the coordinates of the -single control point. The whole curve lies within the convex -polygon with vertices at $p$, $(p+a)/2$, $(c+a)/2$ and $c$ -where $a$ denotes the control point. Set |\X@max|, |\X@min|, |\Y@max| -and |\Y@min| to be the extremes of the coordinates of these 4 points. -There may not actually be any point on the curve achieving these -extremes, but certainly we get pretty close. - -\DOCMODE( -\xydef@\setupsquine@{% - \xycontrolpt@\z@ \X@p=\X@c \Y@p=\Y@c - \xycontrolpt@\@ne \A@=\X@c \B@=\Y@c - \xycontrolpt@\tw@ - \ifdim \A@>\X@max - \dimen@=\X@p\advance\dimen@\A@ \dimen@half - \ifdim \dimen@>\X@max \X@max=\dimen@ \fi - \dimen@=\X@c\advance\dimen@\A@ \dimen@half - \ifdim \dimen@>\X@max \X@max=\dimen@ \fi - \else \ifdim \A@<\X@min - \dimen@=\X@p\advance\dimen@\A@ \dimen@half - \ifdim \dimen@<\X@min \X@min=\dimen@ \fi - \dimen@=\X@c\advance\dimen@\A@ \dimen@half - \ifdim \dimen@>\X@min \X@min=\dimen@ \fi - \fi\fi - \ifdim \B@>\Y@max - \dimen@=\Y@p\advance\dimen@\B@ \dimen@half - \ifdim \dimen@>\Y@max \Y@max=\dimen@ \fi - \dimen@=\Y@c\advance\dimen@\B@ \dimen@half - \ifdim \dimen@>\Y@max \Y@max=\dimen@ \fi - \else \ifdim \B@<\Y@min - \dimen@=\Y@p\advance\dimen@\B@ \dimen@half - \ifdim \dimen@<\Y@min \Y@min=\dimen@ \fi - \dimen@=\Y@c\advance\dimen@\B@ \dimen@half - \ifdim \dimen@>\Y@min \Y@min=\dimen@ \fi - \fi\fi } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The algorithm used for computing coordinates of points on quadratic -B\'ezier splines is essentially that used by D. E. Knuth in -|picmac.tex|\cite{picmac} (aka |gpxmac.tex|). -It is a recursive de Casteljau algorithm of the ``divide and conquer'' type. -(In Knuth's macros these types of curves were -given the name ``squines''. This explains some of the control -sequence names used here.) - -The differences from Knuth's algorithm are simply to allow -more of the available information to be used at points along the spline. -In particular the tangent direction can be calculated and tests can be -performed to decide when to break out of the algorithm, rather than -letting it run its full course. - -\DOCMODE( -\xydef@\squinedecast@{\halve@dimen\splinedepth@ %\divide\splinedepth@\tw@ - \R@c=\L@c \advance\L@c\X@p \halve@dimen\L@c %\divide\L@c\tw@ - \advance\R@c\X@c \halve@dimen\R@c %\divide\R@c\tw@ - \A@=\L@c \advance\A@\R@c \halve@dimen\A@ %\divide\A@\tw@ - \D@c=\U@c \advance\U@c\Y@p \halve@dimen\U@c %\divide\U@c\tw@ - \advance\D@c\Y@c \halve@dimen\D@c %\divide\D@c\tw@ - \B@=\U@c \advance\B@\D@c \halve@dimen\B@ %\divide\B@\tw@ - \begingroup \X@c=\A@ \Y@c=\B@ \splinerec@ \endgroup - \begingroup \X@c=\A@ \Y@c=\B@ \splinepoint \endgroup - \X@p=\A@ \L@c=\R@c \Y@p=\B@ \U@c=\D@c \splinerec@} - -\xydef@\squinerec@{{\splinefar@false \splinenear@\X@p\X@c\Y@p\Y@c - \ifsplinefar@ \aftergroup\squinedecast@ - \else \aftergroup\splineadvance@ \fi}} - -\xydef@\squineDadvance@@@{\X@p\L@c\Y@p\D@c} - -\xydef@\squineplot@maybe{{\X@p=\L@c \Y@p=\U@c \cv@start \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The tangent direction is computed from the displacement to the ``recursive'' -control point. - -\DOCMODE( -\xydef@\setsquinedir@{% - \d@X=\X@c \advance\d@X-\L@c \d@Y=\Y@c \advance\d@Y-\U@c - \dimen@=\ifdim\d@X<\z@-\fi\d@X \ifdim\dimen@<.02\p@ - \dimen@=\ifdim\d@Y<\z@-\fi\d@Y \ifdim\dimen@<.02\p@ - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p \fi\fi - \ifdim\X@c=\X@p \ifdim\Y@c=\Y@p - \d@X=\L@c \advance\d@X-\X@p \d@Y=\U@c \advance\d@Y-\Y@p \fi\fi - \setupDirection@ii } - -\xydef@\setsquineknotdir@{% - \ifdim\zz@\splineval@ \expandafter \setsquinezerodir@ - \else\expandafter \setsquinedir@ \fi } - -\xydef@\setsquinezerodir@{% - \d@X=\L@c \advance\d@X-\X@p \d@Y=\U@c \advance\d@Y-\Y@p - \ifdim\zz@\d@X \ifdim\zz@\d@Y - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p - \fi\fi \setupDirection@ii } -\DOCMODE) - -We need a way to access the information in |\splineparams|. - -\DOCMODE( -\xydef@\getsquineparams@#1,#2,#3,#4,#5,#6,#7,{% - \splinelength@=#1\relax\X@p=#2\relax\Y@p=#3\relax - \A@=#4\relax\B@=#5\relax\X@c=#6\relax\Y@c=#7\relax -} -\xydef@\squineinfo@{% -\expandafter\removePT@\the\X@c\space -\expandafter\removePT@\the\Y@c\space -\expandafter\removePT@\the\A@\space -\expandafter\removePT@\the\B@\space -\expandafter\removePT@\the\X@p\space -\expandafter\removePT@\the\Y@p\space -\expandafter\removePT@\the\dimen5\space\space -\expandafter\removePT@\the\dimen7\space - }% -\xydef@\squinereverse@{\readsplineparams@ - \expandafter\edef\xysplineparams@{\the\splinelength@,% - \the\X@c,\the\Y@c,\the\A@,\the\B@,\the\X@p,\the\Y@p,}}% -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Start the picture by (1)~setting a box, as usual. -(2)~Initialize global variables; these must be global since they are -used to store information which must be preserved outside the grouping -which is vital to the recursive nature of the algorithm. -(3)~Move horizontally to the starting point at $p$. -(4)~Begin by handling the starting point; \ie\ decide whether it is to be -plotted or not. - -\DOCMODE( -\xydef@\squine@start@{\setboxz@h\bgroup % %(1) - \global\splinelength@=\z@ \global\dimen@i=\z@ \global\dimen3=\z@ % %(2) - \kern\X@p % %(3) - {\squinesetparams@ \X@c=\X@p \Y@c=\Y@p \firstsplinepoint@ % %(4) - }\bgroup } - -\xydef@\squinesetparams@{% - \global\dimen@i=\X@p \global\dimen3=\Y@p - \L@c=\A@ \U@c=\B@ \R@c=\L@c \D@c=\U@c }% - -\xydef@\squined@{% - \expandafter\edef\xysplineparams@{% - \the\z@,\the\X@p,\the\Y@p,\the\A@,\the\B@,\the\X@c,\the\Y@c,}} - -\xydef@\squined@@{% -% \global\splinedepth@=\p@ - \splinedepth@=\p@ - \global\splineval@=\z@ - \global\dimen@i=\X@p \global\dimen3=\Y@p - \spline@start - \ifx\splinerec@\relax \let\splinerec@=\squinerec@\fi - \L@c=\A@ \U@c=\B@ \R@c=\L@c \D@c=\U@c - \splinerec@ \spline@end } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsubsection{B\'ezier cubic splines} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -\xydef@\xycubicbezier@{% - \addtocrvpts@{\def\crvconnect@{\cubicconnect@}}% - \xycubicmethods@ \let\splinesegment@=\cubicsegment@ - \begingroup \setcrvobjects@ \xysplineparams@ \splined@@@ - \bgroup \setupcubic@ \cubiced@ \splineset@ \savespline@ } - -\xydef@\xycubicmethods@{% - \def\crvconnect@{\cubicconnect@}% - \def\splinereverse@@{\cubicreverse@@}% - \let\getsplineparams@=\getcubicparams@ - \let\spline@start@=\cubic@start@ - \let\splinedecast@@=\cubicdecast@ - \let\splinerec@@=\cubicrec@ - \let\splined@@=\cubiced@@ - \let\splineIpt@@=\cubicIpt@ - \let\splineIadvance@@=\cubicIadvance@ - \let\splineoutsidehull@@=\cubicoutsidehull@ - \let\splinetestcvxhull@=\cubictestcvxhull@ - \let\splineinfo@=\cubicinfo@ - \let\setsplinedir@=\setcubicdir@ - \let\setsplineknotdir@=\setcubicknotdir@ - \let\splinereverse@=\cubicreverse@ - \let\splineDadvance@@@=\cubicDadvance@@@ - \let\splinesetparams@=\cubicsetparams@ - \let\splineplot@maybe@@=\cubicplot@maybe - } - -\xydef@\cubicconnect@{\splineconnect@ \crvconnect@@ - \let\splinesegment@=\cubicsegment@ }% - -\xydef@\cubicsegment@#1{\xycubicmethods@ \def\segmentnum@{1}% - \setupcubic@ \cubiced@ } - -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Use the registers |\A@|, |\B@|, |\dimen3| and |\dimen5| to store coordinates -of the two control points, denoted $l$ and $r$ say. The whole curve lies -within the convex polygon $p$, $(p+l)/2$, $(c+r)/2$ and $c$ where the vertices are -not necessarily in this order. Set |\X@max|, |\X@min|, |\Y@max| -and |\Y@min| to be the extremes of the coordinates of these 4 points. -There may not actually be any point on the curve achieving these -extremes, but certainly we get pretty close. - -\DOCMODE( -\xydef@\setupcubic@{% - \xycontrolpt@\z@ \X@p=\X@c \Y@p=\Y@c - \xycontrolpt@\@ne \A@=\X@c \B@=\Y@c - \xycontrolpt@\tw@ \global\dimen3=\X@c \global\dimen5=\Y@c - \xycontrolpt@\thr@@ - \adjustmaxmin@ } - -\xydef@\adjustmaxmin@{% - \ifdim \A@>\X@max \dimen@=\A@ \advance\dimen@\X@p \dimen@half - \ifdim\dimen@>\X@max \X@max=\dimen@ \fi \else - \ifdim \A@<\X@min \dimen@=\A@ \advance\dimen@\X@p \dimen@half - \ifdim\dimen@<\X@min \X@min=\dimen@ \fi \fi\fi - \ifdim \B@>\Y@max \dimen@=\B@ \advance\dimen@\Y@p \dimen@half - \ifdim\dimen@>\Y@max \Y@max=\dimen@ \fi \else - \ifdim \B@<\Y@min \dimen@=\B@ \advance\dimen@\Y@p \dimen@half - \ifdim\dimen@<\Y@min \Y@min=\dimen@ \fi \fi\fi -% - \ifdim \dimen3>\X@max \dimen@=\dimen3\advance\dimen@\X@c \dimen@half - \ifdim\dimen@>\X@max \X@max=\dimen@ \fi \else - \ifdim \dimen3<\X@min \dimen@=\dimen3\advance\dimen@\X@c \dimen@half - \ifdim\dimen@<\X@min \X@min=\dimen@ \fi \fi\fi - \ifdim \dimen5>\Y@max \dimen@=\dimen5\advance\dimen@\Y@c \dimen@half - \ifdim\dimen@>\Y@max \Y@max=\dimen@ \fi \else - \ifdim \dimen5<\Y@min \dimen@=\dimen5\advance\dimen@\Y@c \dimen@half - \ifdim\dimen@<\Y@min \Y@min=\dimen@ \fi \fi\fi -% - \dimen@=\A@ \advance\dimen@\dimen3 \dimen@half - \ifdim\dimen@>\X@max \X@max=\dimen@ - \else \ifdim\dimen@<\X@min \X@min=\dimen@ \fi\fi - \dimen@=\B@ \advance\dimen@\dimen5 \dimen@half - \ifdim\dimen@>\Y@max \Y@max=\dimen@ - \else \ifdim\dimen@<\Y@min \Y@min=\dimen@ \fi\fi -} -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The recursive algorithm for cubic B\'ezier splines is similar to the -quadratic one. Now there are two ``recursive'' control points to be -calculated upon each subdivision. - -On the $p$-side: -\begin{eqnarray*} -p_p &=& p \\ -l_p &=& (p+l)/2 \\ -r_p &=& (p+2l+r)/4 \\ -c_p &=& (p+3l+3r+c)/8 \\ -\end{eqnarray*} -while on the $c$-side -\begin{eqnarray*} -p_c &=& (p+3l+3r+c)/8 \\ -l_c &=& (l+2r+c)/4 \\ -r_c &=& (r+c)/2 \\ -c_c &=& c \\ -\end{eqnarray*} -Notice that $c_p=p_c$ and that the tangents match there. - -\DOCMODE( -\xydef@\cubicdecast@{\halve@dimen\splinedepth@ %\divide\splinedepth@\tw@ - \A@=\L@c \advance\A@\R@c \halve@dimen\A@ %\divide\A@\tw@ - \advance\R@c\X@c \halve@dimen\R@c %\divide\R@c\tw@ - \B@=\U@c \advance\B@\D@c \halve@dimen\B@ %\divide\B@\tw@ - \advance\D@c\Y@c \halve@dimen\D@c %\divide\D@c\tw@ - \advance\L@c\X@p \halve@dimen\L@c %\divide\L@c\tw@ - \advance\U@c\Y@p \halve@dimen\U@c %\divide\U@c\tw@ - \begingroup - \X@c=\R@c \advance\X@c\L@c \halve@dimen\X@c %\divide\X@c\tw@ - \advance\X@c\A@ \halve@dimen\X@c %\divide\X@c\tw@ - \Y@c=\D@c \advance\Y@c\U@c \halve@dimen\Y@c %\divide\Y@c\tw@ - \advance\Y@c\B@ \halve@dimen\Y@c %\divide\Y@c\tw@ - \R@c=\L@c \advance\R@c\A@ \halve@dimen\R@c %\divide\R@c\tw@ - \D@c=\U@c \advance\D@c\B@ \halve@dimen\D@c %\divide\D@c\tw@ - \bgroup \splinerec@ - \egroup \splinepoint \endgroup - \X@p=\L@c \advance\X@p\R@c \halve@dimen\X@p %\divide\X@p\tw@ - \advance\X@p\A@ \halve@dimen\X@p %\divide\X@p\tw@ - \L@c=\R@c \advance\L@c\A@ \halve@dimen\L@c %\divide\L@c\tw@ - \Y@p=\U@c \advance\Y@p\D@c \halve@dimen\Y@p %\divide\Y@p\tw@ - \advance\Y@p\B@ \halve@dimen\Y@p %\divide\Y@p\tw@ - \U@c=\D@c \advance\U@c\B@ \halve@dimen\U@c %\divide\U@c\tw@ - \splinerec@ } - -\xydef@\cubicrec@{{\splinefar@false \splinenear@\X@p\X@c\Y@p\Y@c - \ifsplinefar@ \aftergroup\cubicdecast@ - \else \aftergroup\splineadvance@ \fi}} - -\xydef@\cubicDadvance@@@{\X@p\X@c\Y@p\Y@c} - -\xydef@\cubicplot@maybe{{\X@p=\L@c \Y@p=\U@c \cv@start \the\Edge@c\@ne - \ifInside@\aftergroup\cubicplot@maybeii\else\aftergroup\splineplot@true\fi}} -\xydef@\cubicplot@maybeii{{\X@p=\R@c \Y@p=\D@c \cv@start \the\Edge@c\@ne - \ifInside@\aftergroup\splineplot@false\else\aftergroup\splineplot@true\fi}} -\DOCMODE) - -\DOCMODE( -\xydef@\cubiced@@{% -% \global\splinedepth@=\p@ - \splinedepth@=\p@ - \global\splineval@=\z@ - \spline@start - \global\dimen@i=\X@p \global\dimen3=\Y@p - \splinerec@ \spline@end } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The tangent direction is computed from the displacement to the ``recursive'' -control point. - -\DOCMODE( -\xydef@\setcubicdir@{% - \ifdim\splinedepth@<.001\p@\DN@{\cubiccoarsedir@}% - \else\DN@{\cubicfinedir@}\fi \next@ } - -\xydef@\cubicfinedir@{% - \d@X=\X@c \advance\d@X-\R@c \d@Y=\Y@c \advance\d@Y-\D@c - \ifdim\zz@\d@X \ifdim\zz@\d@Y - \d@X=\X@c \advance\d@X-\L@c \d@Y=\Y@c \advance\d@Y-\U@c - \ifdim\zz@\d@X \ifdim\zz@\d@Y - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p - \fi\fi \fi\fi -% \ifdim\X@c=\X@p \ifdim\Y@c=\Y@p -% \d@X=\L@c \d@Y=\U@c \advance\d@X-\X@p \advance\d@Y-\Y@p -% \ifdim\d@X=\z@ \ifdim\d@Y=\z@ -% \d@X=\R@c \d@Y=\D@c \advance\d@X-\X@p \advance\d@Y-\Y@p -% \fi\fi -% \fi\fi - \setupDirection@ii -\splinetrace@{dir:(\the\d@X,\the\d@Y),\the\Direction; depth:\the\splinedepth@}% -} - -\xydef@\cubiccoarsedir@{% - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p \setupDirection@ii - \global\dimen5=\d@X \global\dimen7=\d@Y -\splinetrace@{dir:(\the\d@X,\the\d@Y),\the\Direction; depth:\the\splinedepth@}% -} - -\xydef@\setcubicknotdir@{% - \ifdim\zz@\splineval@ \DN@{\setcubiczerodir@}% - \else \DN@{\cubicfinedir@}\fi \next@ } - -\xydef@\setcubiczerodir@{% - \d@X=\L@c \advance\d@X-\X@p \d@Y=\U@c \advance\d@Y-\Y@p - \ifdim\zz@\d@X \ifdim\zz@\d@Y - \d@X=\R@c \advance\d@X-\X@p \d@Y=\D@c \advance\d@Y-\Y@p - \ifdim\zz@\d@X \ifdim\zz@\d@Y - \d@X=\X@c \advance\d@X-\X@p \d@Y=\Y@c \advance\d@Y-\Y@p - \fi\fi \fi\fi \setupDirection@ii } -\DOCMODE) - -We need a way to access the information in |\splineparams|. - -\DOCMODE( -\xydef@\getcubicparams@#1,#2,#3,#4,#5,#6,#7,#8,#9,{% - \splinelength@=#1\relax\X@p=#2\relax\Y@p=#3\relax\L@c=#4\relax - \U@c=#5\relax\R@c=#6\relax\D@c=#7\relax\X@c=#8\relax\Y@c=#9\relax -}% -\xydef@\cubicinfo@{% -\expandafter\removePT@\the\X@p\space -\expandafter\removePT@\the\Y@p\space -\expandafter\removePT@\the\L@c\space -\expandafter\removePT@\the\U@c\space -\expandafter\removePT@\the\R@c\space -\expandafter\removePT@\the\D@c\space -\expandafter\removePT@\the\X@c\space -\expandafter\removePT@\the\Y@c\space -\expandafter\removePT@\the\dimen5\space\space -\expandafter\removePT@\the\dimen7\space - }% -\xydef@\cubicreverse@{\readsplineparams@ - \expandafter\edef\xysplineparams@{\the\splinelength@,% - \the\X@c,\the\Y@c,\the\R@c,\the\D@c,\the\L@c,\the\U@c,\the\X@p,\the\Y@p,}}% -\xydef@\cubicreverse@@{% - \splinereverse@@@ - \dimen@ii=\L@c \L@c=\R@c \R@c=\dimen@ii - \dimen@ii=\U@c \U@c=\D@c \D@c=\dimen@ii } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -Start the picture by (1)~setting a box, as usual. -(2)~Initialize global variables; these must be global since they are -used to store information which must be preserved outside the grouping -which is vital to the recursive nature of the algorithm. -(3)~Move horizontally to the starting point at $p$. -(4)~Begin by handling the starting point; \ie\ decide whether it is to be -plotted or not. - -\DOCMODE( -\xydef@\cubic@start@{\setboxz@h\bgroup % %(1) - \global\splinelength@=\z@ \global\dimen@i=\z@ \global\dimen3=\z@ % %(2) - \kern\X@p % %(3) - {\cubicsetparams@ \X@c=\X@p \Y@c=\Y@p \R@c=\X@c \D@c=\Y@c - \firstsplinepoint@ }\bgroup -} % %(4) - -\xydef@\cubicsetparams@{% - \expandafter\expandafter\expandafter\getsplineparams@\xysplineparams@ - \global\dimen@i=\X@p \global\dimen3=\Y@p } -\DOCMODE) - -\DOCMODE( -\xydef@\cubiced@{% - \expandafter\edef\xysplineparams@{\the\z@,\the\X@p,\the\Y@p - ,\the\A@,\the\B@,\the\dimen3,\the\dimen5,\the\X@c,\the\Y@c,}% - }% -\DOCMODE) - - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsubsection{B-splines} - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The cases of 3 and 4 control points have some special simplifying features. - -\DOCMODE( -\xydef@\xybspline@iii{% - \addtocrvpts@{\def\crvconnect@{\bsplineiiiconnect@}}% - \def\crvconnect@{\bsplineiiiconnect@}\xybsplinemethods@ - \let\splinesegment@=\bsplinesegment@iii - \begingroup\setcrvobjects@ \dobspline@ \savespline@ } -\xydef@\bsplineiiiconnect@{\splineconnect@ \crvconnect@@ - \let\splinesegment@=\bsplinesegment@iii }% - -\xydef@\xybspline@iv{% - \addtocrvpts@{\def\crvconnect@{\bsplineivconnect@}}% - \def\crvconnect@{\bsplineivconnect@}\xybsplinemethods@ - \let\splinesegment@=\bsplinesegment@iv - \begingroup\setcrvobjects@ \dobspline@ \savespline@ } -\xydef@\bsplineivconnect@{\splineconnect@ \crvconnect@@ - \let\splinesegment@=\bsplinesegment@iv }% -\DOCMODE) - -Now for the general case of $\ge5$ control points. - -\DOCMODE( -\xydef@\xybspline@{% -\splinetrace@{B-spline with \numcontrolpts\space control points.}% - \addtocrvpts@{\def\crvconnect@{\bsplineconnect@}}% - \def\crvconnect@{\bsplineconnect@}\xybsplinemethods@ - \let\splinesegment@=\bsplinesegment@ - \begingroup\setcrvobjects@ - \dobspline@ \savespline@ } - -\xydef@\xybsplinemethods@{% - \def\splinereverse@@{\cubicreverse@@}% - \let\getsplineparams@=\getbsplineparams@ - \let\spline@start@=\cubic@start@ - \let\splinedecast@@=\cubicdecast@ - \let\splinerec@@=\cubicrec@ -% \let\splined@@=\cubiced@@ - \let\splineIpt@@=\cubicIpt@ - \let\splineIadvance@@=\cubicIadvance@ - \let\splined@@=\bsplined@@ - \let\splineinfo@=\cubicinfo@ - \let\setsplinedir@=\setcubicdir@ - \let\setsplineknotdir@=\setcubicknotdir@ - \let\splinereverse@=\cubicreverse@ - \let\splineDadvance@@@=\cubicDadvance@@@ - \let\splinesetparams@=\cubicsetparams@ - \global\let\lastbspline@=\lastbspline@@ - \global\let\middlebspline@=\middlebspline@@ -} -\xydef@\bsplined@@{% -% \global\splinedepth@=\p@ - \splinedepth@=\p@ - \global\splineval@=\z@ - \spline@start - \global\dimen@i=\X@p \global\dimen3=\Y@p - \splinerec@ \spline@end } -\DOCMODE) - -\DOCMODE( -\xydef@\bsplineconnect@{\splineconnect@ \crvconnect@@ - \let\splinesegment@=\bsplinesegment@ }% - -\xydef@\getbsplineparams@{\getcubicparams@} - -\xydef@\dobspline@{\xysplineparams@ \scanbspline@ \firstbspline@ }% -\DOCMODE) - - Registers |\dimen3| and |\dimen5| are used globally, since the - standard local registers are already used. - -\DOCMODE( -\xydef@\firstbspline@{% - \enter@{\pfromthep@ \cfromthec@}\enter@{\cfromthec@}\bgroup - \def\segmentnum@{1}\xycontrolpt@\z@ \X@p=\X@c \Y@p=\Y@c -\splinetrace@{0: \the\X@p, \the\Y@p}% - \xycontrolpt@\@ne \A@=\X@c \B@=\Y@c -\splinetrace@{1: \the\X@c, \the\Y@c}% - \xycontrolpt@\tw@ -\splinetrace@{2: \the\X@c, \the\Y@c}% - \dimen@=\X@c \advance\dimen@\A@ \dimen@half - \global\dimen3=\dimen@ - \dimen@=\Y@c \advance\dimen@\B@ \dimen@half - \global\dimen5=\dimen@ - \xycontrolpt@{3}% -\splinetrace@{3: \the\X@c, \the\Y@c}% - \expandafter\count@\xycrvcnt@\relax %%% very important to |\relax| - \ifnum\count@=3\relax - \advance\X@c-\A@ \dimen@nth4\X@c % \divide\X@c by4 - \advance\X@c\dimen3\relax - \advance\Y@c-\B@ \dimen@nth4\Y@c % \divide\Y@c by4 - \advance\Y@c\dimen5\relax - \enter@{\X@p=\the\X@c \Y@p=\the\Y@c \crv@cnt@=\@ne\relax - \noexpand\lastbspline@ }% - \else - \advance\X@c 7\dimen3 \advance\X@c-2\A@ - \dimen@nth6\X@c % \divide\X@c by6\relax - \advance\Y@c 7\dimen5 \advance\Y@c-2\B@ - \dimen@nth6\Y@c % \divide\Y@c by6\relax - \enter@{\X@p=\the\X@c \Y@p=\the\Y@c \crv@cnt@=\@ne\relax - \noexpand\middlebspline@ }% - \fi \adjustmaxmin@ \czeroEdge@ - \bsplined@ \splineset@ \leave@ } - -\xydef@\lastbspline@@{\bgroup - \advance\crv@cnt@\@ne \edef\segmentnum@{\the\crv@cnt@}% -\splinetrace@{<: \the\X@p, \the\Y@p}% - \advance\crv@cnt@\@ne \xycontrolpt@{\crv@cnt@}% - \global\dimen3=\X@c \global\dimen5=\Y@c -\splinetrace@{\the\crv@cnt@: \the\X@c, \the\Y@c}% - \advance\crv@cnt@\m@ne \xycontrolpt@{\crv@cnt@}% -\splinetrace@{\the\crv@cnt@: \the\X@c, \the\Y@c}% - \A@=\X@c \advance\A@\dimen3 \halve@dimen\A@ % \divide\A@\tw@ - \B@=\Y@c \advance\B@\dimen5 \halve@dimen\B@ % \divide\B@\tw@ - \adjustmaxmin@ \leave@ \relax \cv@end % <--------------- -\splinetrace@{>: \the\X@c, \the\Y@c}% - \bsplined@ \splineset@ \leave@ }% -\xylet@\lastbspline@=\lastbspline@@ - -\xydef@\middlebspline@@{% - \advance\crv@cnt@\@ne \edef\segmentnum@{\the\crv@cnt@}% -\splinetrace@{<: \the\X@p, \the\Y@p}% - \bgroup - \xycontrolpt@{\crv@cnt@}\A@=2\X@c \B@=2\Y@c -\splinetrace@{\the\crv@cnt@: \the\X@c, \the\Y@c}% - \advance\crv@cnt@\@ne \xycontrolpt@{\crv@cnt@}% -\splinetrace@{\the\crv@cnt@: \the\X@c, \the\Y@c}% - \advance\A@\X@c \dimen@nth3\A@ % \divide\A@ by3 - \advance\B@\Y@c \dimen@nth3\B@ % \divide\B@ by3\relax - \advance\X@c\A@ \halve@dimen\X@c % \divide\X@c\tw@ - \advance\Y@c\B@ \halve@dimen\Y@c % \divide\Y@c\tw@ - \global\dimen3=\X@c \global\dimen5=\Y@c - \advance\crv@cnt@\@ne \xycontrolpt@{\crv@cnt@}% -\splinetrace@{\the\crv@cnt@: \the\X@c, \the\Y@c}% - \expandafter\count@\xycrvcnt@\relax - \ifnum\crv@cnt@<\count@\relax - \advance\X@c 7\dimen3\advance\X@c-2\A@ - \dimen@nth6\X@c % \divide\X@c by6\relax - \advance\Y@c 7\dimen5\advance\Y@c-2\B@ - \dimen@nth6\Y@c % \divide\Y@c by6\relax - \enter@{\X@p=\the\X@c \Y@p=\the\Y@c \crv@cnt@=\segmentnum@\relax - \noexpand\middlebspline@}% - \else - \advance\X@c-\A@ \dimen@nth4\X@c % \divide\X@c by4 - \advance\X@c \dimen3\relax - \advance\Y@c-\B@ \dimen@nth4\Y@c % \divide\Y@c by4 - \advance\Y@c \dimen5\relax - \enter@{\X@p=\the\X@c \Y@p=\the\Y@c \noexpand\lastbspline@}% - \fi \adjustmaxmin@ - \bsplined@ \splineset@ \leave@ } -\xylet@\middlebspline@=\middlebspline@@ -\DOCMODE) - -\DOCMODE( -\xydef@\scanbspline@{\splined@@@} -\DOCMODE) - -\DOCMODE( -\xydef@\bsplined@{\cubiced@ - \expandafter\ifx\xysplineedges@\relax\relax\DN@{}% - \else\DN@{\adjustbsplineedges@}\fi \next@ } - -\xydef@\adjust@forsegments@{\getcrvsegsnum@ - \ifnum\count@>\@ne -\splinetrace@{adjust for \the\count@\space segments: - \the\dimen5, \the\dimen7}% - \multiply\dimen5 by \count@\relax \dimen@=\segmentnum@\p@ - \ifnum\dimen5>\dimen@ \relax\dimen5=\p@ - \else \advance\dimen5-\segmentnum@\p@ \advance\dimen5 by\p@ \fi - \ifnum\dimen5<\z@ \relax\dimen5=\z@\relax\fi - \multiply\dimen7 by \count@\relax - \dimen@=\segmentnum@\p@ %\advance\dimen@-\segmentnum@\p@ - \ifnum\dimen7<\dimen@ \advance\dimen@-\p@ - \ifnum\dimen7>\dimen@ \advance\dimen7-\dimen@ - \else \dimen7=\z@ \fi - \else \dimen7=\p@ \fi -\splinetrace@{adjusted for \the\count@\space segments: - \the\dimen5, \the\dimen7}% - \fi} - -\xydef@\adjustbsplineedges@{\bgroup % dimen5 and dimen7 are NOT global here -\splinetrace@{** adjusting edges **}% - \readsplineparams@ \adjust@forsegments@ -% \count@@=\dimen7\divide\count@@\p@ -% \advance\dimen7-\count@@\p@ \advance\count@@\@ne -% \count@=\dimen5\divide\count@\p@ -% \advance\dimen5-\count@\p@ \advance\count@\@ne -\splinetrace@{params:\xysplineparams@}% -\splinetrace@{segment \segmentnum@:<\the\dimen5,\the\dimen7>:\xysplineedges@}% -% \expandafter\ifnum\segmentnum@=\count@ -% \else -% \expandafter\ifnum\segmentnum@<\count@\dimen5=\p@ -% \else\dimen5=\z@ \fi\fi -% \expandafter\ifnum\segmentnum@=\count@@ - \multiply\dimen7by\m@ne \advance\dimen7by\p@ -% \else -% \expandafter\ifnum\segmentnum@>\count@@\dimen5=\p@\dimen7=\p@ -% \else\dimen7=\z@ \fi\fi - \expandafter\edef\xysplineedges@{% - \noexpand\z@;\the\dimen5,\noexpand\z@;\the\dimen7,}% - \edef\tmp@{\egroup - \noexpand\def\expandafter\noexpand\xysplineedges@{\xysplineedges@}}% - \tmp@ } -\DOCMODE) - -These macros select the correct B\'ezier control points for each -segment of the spline. This is needed for finding places on the -constructed curves. - -In general there are 5 types of segment: first, second, middle, -penultimate, final. The conversion from B-spline to B\'ezier is -slightly different for each type. -For middle segments the B\'ezier control points are determined -in the following way: -\begin{eqnarray*} -X_{B_i}^{(1)} &=& {1\over3}\left( 2X^{(i)} + X^{(i+1)}\right)\\ -X_{B_i}^{(2)} &=& {1\over3}\left( X^{(i)} + 2X^{(i+1)}\right)\\ -X_{B_i}^{(0)} &=& -{1\over6}\left( X^{(i-1)} + 4X^{(i)} + X^{(i+1)}\right)\\ -&=& {1\over6}\left( X^{(i-1)} + 7X_{B_i}^{(1)} - 2X_{B_i}^{(2)}\right)\\ -X_{B_i}^{(3)} &=& -{1\over6}\left( X^{(i)} + 4X^{(i+1)} + X^{(i+2)}\right)\\ -&=& {1\over6}\left( X^{(i+2)} + 7X_{B_i}^{(2)} - 2X_{B_i}^{(1)}\right)\\ -\end{eqnarray*} - -\DOCMODE( -\xydef@\bsegment@@ii@iii{% - \xycontrolpt@{\count@@}\global\dimen3=\X@c \global\dimen5=\Y@c -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \advance\count@@\@ne \xycontrolpt@{\count@@}\A@=\X@c \B@=\Y@c - \advance\A@ by2\dimen3 \dimen@nth3\A@ % \divide\A@ by3\relax - \advance\B@ by2\dimen5 \dimen@nth3\B@ % \divide\B@ by3\relax - \dimen@=\dimen3 \advance\dimen@ by2\X@c - \dimen@nth3\dimen@ % \divide\dimen@\thr@@ - \global\dimen3=\dimen@ - \dimen@=\dimen5 \advance\dimen@ by2\Y@c - \dimen@nth3\dimen@ % \divide\dimen@\thr@@ - \global\dimen5=\dimen@ -\splinetrace@{<: \the\dimen3, \the\dimen5}% -\splinetrace@{>: \the\A@, \the\B@}% - \advance\count@@\m@ne } - -\xydef@\bsegment@@i{\bgroup - \advance\count@@\m@ne \xycontrolpt@{\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ - \advance\X@p-2\dimen3\advance\X@p by7\A@ - \dimen@nth6\X@p % \divide\X@p by6\relax - \advance\Y@p-2\dimen5\advance\Y@p by7\B@ - \dimen@nth6\Y@p % \divide\Y@p by6\relax -} - -\xydef@\bsegment@@iv{% - \advance\count@@\tw@ \xycontrolpt@{\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \advance\X@c by7\dimen3\advance\X@c-2\A@ - \dimen@nth6\X@c % \divide\X@c by6\relax - \advance\Y@c by7\dimen5\advance\Y@c-2\B@ - \dimen@nth6\Y@c % \divide\Y@c by6\relax -\splinetrace@{>>: \the\X@c, \the\Y@c }% -} -\DOCMODE) - -For the second segment the expression for $X_{B_2}^{(0)}$ is different. -Similarly the expression for $X_{B_{n-1}}^{(3)}$ is altered for the -penultimate segment. - -\begin{eqnarray*} -X_{B_2}^{(0)} &=& -{1\over4}\left( X^{(1)} + 4X_{B_2}^{(1)} - X_{B_2}^{(2)}\right)\\ -X_{B_{n-1}}^{(3)} &=& -{1\over4}\left( X^{(3)} + 4X_{B_{n-1}}^{(2)} - X_{B_{n-1}}^{(1)}\right)\\ -\end{eqnarray*} - -\DOCMODE( -\xydef@\bsegment@@ii@i{\bgroup - \advance\count@@\m@ne \xycontrolpt@{\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ - \advance\X@p-\dimen3\advance\X@p by4\A@ - \dimen@nth4\X@p % \divide\X@p by4\relax - \advance\Y@p-\dimen5\advance\Y@p by4\B@ - \dimen@nth4\Y@p % \divide\Y@p by4\relax -\splinetrace@{<<: \the\X@p, \the\Y@p}% -} -\xydef@\bsegment@@y@iv{% - \advance\count@@\tw@ \xycontrolpt@{\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \advance\X@c by4\dimen3\advance\X@c-\A@ - \dimen@nth4\X@c % \divide\X@c by4\relax - \advance\Y@c by4\dimen5\advance\Y@c-\B@ - \dimen@nth4\Y@c % \divide\Y@c by4\relax -} -\DOCMODE) - -For the first segment the first three B\'ezier control points are always -determined in the same way: -\begin{eqnarray*} -X_{B_1}^{(0)} = X^{(0)} & X_{B_1}^{(1)} = X^{(1)} - & X_{B_1}^{(2)} = {1\over2}(X_{B_1}^{(1)}+X^{(2)})\\ -\hbox{3+~segments}& - & X_{B_1}^{(3)} = {1\over6}(7X_{B_1}^{(2)} - 2X_{B_1}^{(1)} + X^{(3)})\\ -\hbox{~2~segments}& - & X_{B_1}^{(3)} = {1\over4}(4X_{B_1}^{(2)} - X_{B_1}^{(1)} + X^{(3)})\\ -\end{eqnarray*} - - -\DOCMODE( -\xydef@\bsegment@i{% - \xycontrolpt@\z@ \X@p=\the\X@c \Y@p=\the\Y@c -% \ifx\cv@start\relax -% \bgroup\csname cv@0\endcsname -% \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ -% \else\xycontrolpt@\z@ \X@p=\the\X@c \Y@p=\the\Y@c\fi -\splinetrace@{0: \the\X@p \the\Y@p}% - \xycontrolpt@\@ne -\splinetrace@{1: \the\X@c, \the\Y@c}\A@=\X@c \B@=\Y@c - \xycontrolpt@\tw@ - \dimen@=\X@c \advance\dimen@\A@ \dimen@half - \global\dimen3=\dimen@ -\splinetrace@{2: \the\X@c, \the\Y@c}% - \dimen@=\Y@c \advance\dimen@\B@ \dimen@half - \global\dimen5=\dimen@ } - -\xydef@\bsegment@i@iv{% - \xycontrolpt@{3}% -\splinetrace@{3: \the\X@c, \the\Y@c}% - \advance\X@c by7\dimen3\advance\X@c-2\A@ - \dimen@nth6\X@c % \divide\X@c by6\relax - \advance\Y@c by7\dimen5\advance\Y@c-2\B@ - \dimen@nth6\Y@c % \divide\Y@c by6\relax - } -\DOCMODE) - -The last segment is determined symmetrically from the final four -control points: -\begin{eqnarray*} -X_{B_n}^{(3)} = X^{(n+2)} & X_{B_n}^{(2)} = X^{(n+1)} - & X_{B_n}^{(1)} = {1\over2}(X_{B_n}^{(2)}+X^{(n)})\\ -\hbox{3+~segments}& - & X_{B_n}^{(0)} = {1\over6}(X^{(n-1)}-2X_{B_n}^{(2)}+7X_{B_n}^{(1)})\\ -\hbox{~2~segments}& - & X_{B_n}^{(0)} = {1\over4}(X^{(1)}-X_{B_n}^{(2)}+4X_{B_n}^{(1)})\\ -\end{eqnarray*} - -\DOCMODE( -\xydef@\bsegment@z{% - \expandafter\count@@\xycrvptsnum@ \advance\count@@\@ne - \xycontrolpt@{\the\count@@}\relax -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \advance\count@@\m@ne - \bgroup - \xycontrolpt@{\the\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \global\dimen3=\X@c \global\dimen5=\Y@c - \advance\count@@\m@ne \xycontrolpt@{\the\count@@}% -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \A@=\X@c \advance\A@\dimen3 \halve@dimen\A@ % \divide\A@\tw@ - \B@=\Y@c \advance\B@\dimen5 \halve@dimen\B@ % \divide\B@\tw@ - \edef\tmp@{\egroup \A@=\the\A@ \B@=\the\B@ \count@@=\the\count@@}% - \tmp@ } - -\xydef@\bsegment@z@i{% - \expandafter\count@@\xycrvptsnum@\relax\advance\count@@-\tw@ - \bgroup - \xycontrolpt@{\count@@}\X@p=\the\X@c \Y@p=\the\Y@c -\splinetrace@{\the\count@@: \the\X@c, \the\Y@c}% - \advance\X@p by7\A@ \advance\X@p-2\dimen3 \dimen@nth6\X@p - \advance\Y@p by7\B@ \advance\Y@p-2\dimen5 \dimen@nth6\Y@p - \edef\tmp@{\egroup \X@p=\the\X@p \Y@p=\the\Y@p}% - \tmp@ } -\DOCMODE) - -This is the switching-yard. - -\DOCMODE( -\xydef@\bsplinesegment@#1{\xybsplinemethods@ - \count@@=#1\relax - \ifnum\count@@=\@ne % first segment - \bsegment@i \bsegment@i@iv - \else\ifnum\count@@=\tw@ % second segment - \bsegment@@ii@iii \bsegment@@ii@i \bsegment@@iv -% \else\expandafter\count@\xycrvcnt@\advance\count@\m@ne - \else\expandafter\count@\xycrvptsnum@\advance\count@\m@ne - \ifnum\count@@=\count@ % last segment - \bsegment@z \bsegment@z@i - \else\advance\count@\m@ne - \ifnum\count@@=\count@ % penult. segment - \bsegment@@ii@iii \bsegment@@i \bsegment@@y@iv - \else % middle segments - \bsegment@@ii@iii \bsegment@@i \bsegment@@iv - \fi\fi\fi\fi - \expandafter\def\expandafter\segmentnum@\expandafter{\number#1}% - \bsplined@ } -\DOCMODE) - -Here are the differences for 3 control points. - -\DOCMODE( -\xydef@\bsplinesegment@iii#1{\xybsplinemethods@ -\splinetrace@{2 segments; \number#1}% - \count@@=#1\relax - \ifnum\count@@=\@ne \bsegment@i - \xycontrolpt@{3}% -\splinetrace@{3: \the\X@c, \the\Y@c}% - \advance\X@c 4\dimen3\advance\X@c-\A@ - \dimen@nth4\X@c % \divide\X@c by4\relax - \advance\Y@c 4\dimen5\advance\Y@c-\B@ - \dimen@nth4\Y@c % \divide\Y@c by4\relax - \else\ifnum\count@@=\tw@ \bsegment@z - \bgroup\xycontrolpt@{\@ne}% -\splinetrace@{1: \the\X@c, \the\Y@c}% - \edef\tmp@{\egroup \X@p=\the\X@c \Y@p=\the\Y@c}\tmp@ - \advance\X@p 4\A@ \advance\X@p-\dimen3 % - \dimen@nth4\X@p % \divide\X@p by4\relax - \advance\Y@p 4\B@ \advance\Y@p-\dimen5 % - \dimen@nth4\Y@p % \divide\Y@p by4\relax - \fi\fi - \expandafter\def\expandafter\segmentnum@\expandafter{\number#1}% - \bsplined@ } -\DOCMODE) - -Here are the differences for 4 control points. - -\DOCMODE( -\xydef@\bsplinesegment@iv#1{\xybsplinemethods@ -\splinetrace@{3 segments; \number#1}% - \count@@=#1\relax - \ifnum\count@@=\@ne \bsegment@i \bsegment@i@iv - \else\ifnum\count@@=\tw@ - \bsegment@@ii@iii \bsegment@@ii@i \bsegment@@y@iv - \else\ifnum\count@@=3\relax - \bsegment@z \bsegment@z@i %\xycontrolpt@{5}% - \fi\fi\fi - \expandafter\def\expandafter\segmentnum@\expandafter{\number#1}% - \bsplined@ } -\DOCMODE) - - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsection{Circles and Ellipses} -??=[circles+ellipses] - -\noindent Here we describe the means to a specify circles of arbitrary -radius, drawn with arbitrary line styles. When large-sized objects are -used they are regularly spaced around the circle. Similarly ellipses -may be specified, but only those having major/minor axes aligned in -the standard directions; spacing of objects is no longer regular, but -is bunched toward the narrower ends. - -Such a circle or ellipse is specified using\dots -\begin{defs1} -|\xycircle|<vector>|{|<style>|}| -\end{defs1} -\noindent -where the components of the <vector> determine the lengths of the axis -for the ellipse; thus giving a circle when equal. -The <style> can be any <conn>, as in ??g[xyarrow.doc:f.arrow] that works -with curved arrows---many do. Alternatively <style> can be any <object>, -which will be placed equally-spaced about the circle at a separation -to snugly fit the <object>s. -If <empty> then a solid circle or ellipse is drawn. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\TODO: Recognize special <style>s; e.g. |.| for dotted with |\zerodot|, -|=| for a doubled circle --- alter the radius, draw two circles; -|:| for double dotted (perhaps use |\doubled@|, |\tripled@|); -|>| and |<| for chevrons; -any others? - -To use any of these special symbols as the <object> for <style> then -enclose it within extra braces, \eg~|\xycircle<20pt>{{>}}|. - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The curves are not truly circular or elliptical, but are approximations -given by cubic B\'ezier segments. Hence the |xycurve| feature must be loaded. - -\DOCMODE( -\message{circles,} -\DOCMODE) - -The circles are constructed from four B\'ezier cubic curves, one for each -quadrant of the circle or circle. To do this it is sufficient to establish -the control points for each cubic segment. This is straightforward, using -the following ``magic number'', given a square basis such that the desired -circle is the unit circle, or rectangular basis for which the ``unit circle'' -is the desired circle. - -\DOCMODE( -\xydef@\Circmagic@@{0.5517847} -\xylet@\Circmagic=\Circmagic@@ -\xydef@\twoPi@{6.2831852} -\xydef@\fullPi@{3.1415926} -\xydef@\halfPi@{1.5707963} -\DOCMODE) - -This is the magic number, exactly given by -${1\over12}\bigl(\sqrt{385}-13\bigr)$, -that helps construct the B\'ezier cubic curve -that best approximates a quadrant of a circle. -It does so with remarkable accuracy, -differing by at most .5\% of the radius at any angle; -the average deviation along the whole quadrant being less than .13\%. -The basic <object> defined here is |\circle|. - -\DOCMODE( -\xynew@{dimen}\L@ - -\xydef@\xycircle#1#{\hbox\bgroup\afterVECTORorEMPTY{% - \xy@@{\R@=\X@c \L@=\Y@c}\xycircle@}{\xy@@{\R@=\R@c \L@=\L@c}\xycircle@}#1@} - -\xydef@\xycircle@#1@#2{% - \DN@{#1}\ifx\next@\empty\def\onlyQuad@{}\else \count@=#1\relax - \ifnum\count@<5 \advance\count@-3\relax - \ifnum\count@<\z@ \advance\count@ 4\relax\fi \edef\onlyQuad@{\the\count@}% - \else\xyerror@{illegal circle <radius>: must be <vector> or <empty>}{}\fi - \fi \xy@@{\def\circleSTYLE@{#2}}\def\circleSTYLE@{#2}\xycircle@i} - -\xydef@\xycircle@i{\hbox{\vbox{\vskip\L@ - \hbox to2\R@{\hfill \buildcircle@ \hfill}\vskip\L@ }}% - \L@c=\R@ \R@c=\R@ \D@c=\L@ \U@c=\L@ \def\Leftness@{.5}\def\Upness@{.5}% - \def\Drop@@{\styledboxz@}\def\Connect@@{\straight@\relax}\Edge@c={\circleEdge}% - \OBJECT@x} - -\xydef@\adjustMinMaxcirc@#1#2{% - \dimen@=\X@c \advance\dimen@#1\relax\ifdim\dimen@>\X@max \X@max=\dimen@\fi - \dimen@=\X@c \advance\dimen@-#1\relax\ifdim\dimen@<\X@min \X@min=\dimen@\fi - \dimen@=\Y@c \advance\dimen@#2\relax\ifdim\dimen@>\Y@max \Y@max=\dimen@\fi - \dimen@=\Y@c \advance\dimen@-#2\relax\ifdim\dimen@<\Y@min \Y@min=\dimen@\fi -} - -%\xydef@\buildcircle@{\save@ -%% \cubicCircleControls@@ -% \ifx\circleSTYLE@\empty\DN@{\solidcircle@{}}% -% \else \expandafter\DN@\expandafter{\addDASH@{}}\relax -% \ifx\next@\circleSTYLE@ \DN@{% -% \expandafter\addDASH@\expandafter{\expandafter{\addDASH@{}}}}% -% \else\DN@{\circledobjects@}\fi\fi\next@ \leave@} -\DOCMODE) - -\DOCMODE( -\xydef@\cubicCircleControls@@{\X@origin=\z@ \Y@origin=\z@ - \X@xbase=\R@ \Y@xbase=\z@ \X@ybase=\z@ \Y@ybase=\L@ - \vfromcartesian@@1,0@\czeroEdge@\idfromc@{0@c}% - \vfromcartesian@@0,1@\czeroEdge@\idfromc@{1@c}% - \vfromcartesian@@-1,0@\czeroEdge@\idfromc@{2@c}% - \vfromcartesian@@0,-1@\czeroEdge@\idfromc@{3@c}% - \vfromcartesian@@1,\Circmagic@@ @\czeroEdge@\idfromc@{1@m}% - \vfromcartesian@@\Circmagic@@,1@\czeroEdge@\idfromc@{2@m}% - \vfromcartesian@@-\Circmagic@@,1@\czeroEdge@\idfromc@{3@m}% - \vfromcartesian@@-1,\Circmagic@@ @\czeroEdge@\idfromc@{4@m}% - \vfromcartesian@@-1,-\Circmagic@@ @\czeroEdge@\idfromc@{5@m}% - \vfromcartesian@@-\Circmagic@@,-1@\czeroEdge@\idfromc@{6@m}% - \vfromcartesian@@\Circmagic@@,-1@\czeroEdge@\idfromc@{7@m}% - \vfromcartesian@@1,-\Circmagic@@ @\czeroEdge@\idfromc@{8@m}% - } - -\xydef@\doCircleQuadrant@@#1#2{\save@ \ifcase#2\relax - \doCircleQuadrant@@@{0@c}{1@m}{2@m}{1@c}{#1}\or - \doCircleQuadrant@@@{1@c}{3@m}{4@m}{2@c}{#1}\or - \doCircleQuadrant@@@{2@c}{5@m}{6@m}{3@c}{#1}\or - \doCircleQuadrant@@@{3@c}{7@m}{8@m}{0@c}{#1}\or - \doCircleQuadrant@@@{0@c}{1@m}{2@m}{1@c}{#1}\or - \doCircleQuadrant@@@{1@c}{3@m}{4@m}{2@c}{#1}\or - \doCircleQuadrant@@@{2@c}{5@m}{6@m}{3@c}{#1}\or - \doCircleQuadrant@@@{3@c}{7@m}{8@m}{0@c}{#1}\fi \leave@ } - -\xydef@\doCircleQuadrant@@@#1#2#3#4#5{% - \cfromid@{#1}\pfromc@\senter@ - \cfromid@{#2}\spushc@\cfromid@{#3}\spushc@\cfromid@{#4}% - \let\bstartPLACE@=\empty \connect@\crvs{#5}\relax\sinit@\sleave@ - \resetbreaks@} -\DOCMODE) - -The hook |\dosolidcircle@@| is provided so that back-ends may -provide an alternative method to draw the circles/ellipses. -Note that the token following |\solidcircle@| will be a group -representing the <style> to be used. - -\DOCMODE( -\xydef@\dosolidcircle@#1{% - \cubicCircleControls@@ - \doCircleQuadrant@@{#1}1 \relax\Clast@@ - \doCircleQuadrant@@{#1}2 \relax\Clast@@ - \doCircleQuadrant@@{#1}3 \relax\Clast@@ - \doCircleQuadrant@@{#1}4 \relax\Clast@@}% - -\xydef@\solidcircle@{\dosolidcircle@@} -\xylet@\dosolidcircle@@=\dosolidcircle@ -\DOCMODE) - -This places objects equally spaced around a circle, -according to angular position. - -\BUG: objects are not equally spaced around ellipses constructed this way. -To get regular spacing around ellipses, in terms or arc-length say, -is much more difficult, both theoretically and practically. - -\TODO: the size of the resulting <object> does not take into account -the size of the <object> dropped around the circle. - -\DOCMODE( -\xydef@\circledobjects@{\cubicCircleControls@@ - \setboxz@h{\expandafter\object\circleSTYLE@{}}% - \ifdim\L@>\R@ \dimen@ii=\ht\z@ \advance\dimen@ii \dp\z@ - \ifdim\zz@\dimen@ii \dimen@ii=\wdz@\fi - \else \dimen@ii=\wdz@ - \ifdim\zz@\dimen@ii \dimen@ii=\ht\z@ \advance\dimen@ii \dp\z@\fi - \fi \ifdim\zz@\dimen@ii \dimen@ii=2\jot\fi - \expandafter\dimen@\ifdim\L@>\R@ \twoPi@\L@\else \twoPi@\R@\fi - \advance\dimen@.5\dimen@ii - \count@@=\dimen@ \count@=\dimen@ii \divide\count@@\count@ - \edef\numobjects{\the\count@@}\dimen@=4\p@ - \dimen@nth\numobjects\dimen@ % \divide\dimen@\numobjects\relax - \edef\circleseparation@{\expandafter\removePT@\the\dimen@}% - \edef\circleplace@{-\circleseparation@}\placeQuadrants@}% - -\xydef@\placeQuadrants@{\DN@{\placeAllQuadrants@}% - \ifx\onlyQuad@\undefined\else\ifx\onlyQuad@\empty\else - \DN@{\expandafter\placeCircQuadrant@\expandafter{\onlyQuad@}}% - \fi\fi \next@ }% -%\def\placeQuadrants@{\placeAllQuadrants@} - -\xydef@\placeAllQuadrants@{% - \placeCircQuadrant@{1}% - \advance\dimen@-\p@\advance\dimen@-\circleseparation@\p@ - \edef\circleplace@{\expandafter\removePT@\the\dimen@}% - \placeCircQuadrant@{2}% - \advance\dimen@-\p@\advance\dimen@-\circleseparation@\p@ - \edef\circleplace@{\expandafter\removePT@\the\dimen@}% - \placeCircQuadrant@{3}% - \advance\dimen@-\p@\advance\dimen@-\circleseparation@\p@ - \edef\circleplace@{\expandafter\removePT@\the\dimen@}% - \placeCircQuadrant@{4}} - -\xydef@\placeCircQuadrant@#1{% - \let\bstartPLACE@=\relax \doCircleQuadrant@@{}#1% - \loop@ - \expandafter\dimen@\circleplace@\p@ - \advance\dimen@\circleseparation@\p@ - \edef\circleplace@{\expandafter\removePT@\the\dimen@}% - \ifdim\dimen@<\p@ \placeCircObject@ - \repeat@ } - -\xydef@\placeCircObject@{\begingroup - \crvconnect@@ \Creset@@ \Invisible@false - \expandafter\splinealong@\expandafter{\circleplace@}% - \expandafter\drop\circleSTYLE@{}\endgroup } - -\xydef@\buildcircle@{\save@ -% \cubicCircleControls@@ - \DNii@{\circledobjects@}% - \ifx\circleSTYLE@\empty\DNii@{\solidcircle@{}}% - \else \expandafter\DN@\expandafter{\addDASH@{}}\relax - \ifx\next@\circleSTYLE@ \DNii@{\solidcircle@{}}% - \else \expandafter\DN@\expandafter{\addEQ@{}}% - \ifx\next@\circleSTYLE@ - \expandafter\circletemplate@\expandafter{\addEQ@{}}{}% - \else \expandafter\DN@\expandafter{\addDASH@ 2}% - \ifx\next@\circleSTYLE@ \DNii@{\doublecircle@{}}% - \else \expandafter\DN@\expandafter{\addDASH@ 3}% - \ifx\next@\circleSTYLE@ \DNii@{\triplecircle@{}}% - \else \expandafter\expandafter\expandafter\DN@\expandafter\expandafter - \expandafter{\expandafter\addDASH@\addDASH@{}}% - \ifx\next@\circleSTYLE@ \DNii@{\dashedcircle@{}}% - \else \expandafter\expandafter\expandafter\DN@\expandafter\expandafter - \expandafter{\expandafter\addEQ@\addEQ@{}}% - \ifx\next@\circleSTYLE@ \expandafter\expandafter\expandafter - \circletemplate@\expandafter\expandafter\expandafter{% - \expandafter\addEQ@\addEQ@{}}2% - \else \expandafter\expandafter\expandafter\DN@\expandafter\expandafter - \expandafter{\expandafter\addEQ@\addEQ@2}% - \ifx\next@\circleSTYLE@ \expandafter\expandafter\expandafter - \circletemplate@\expandafter\expandafter\expandafter{% - \expandafter\addEQ@\addEQ@{}}2% - \else \expandafter\expandafter\expandafter\DN@\expandafter\expandafter - \expandafter{\expandafter\addEQ@\addEQ@3}% - \ifx\next@\circleSTYLE@ \expandafter\expandafter\expandafter - \circletemplate@\expandafter\expandafter\expandafter{% - \expandafter\addEQ@\addEQ@{}}3% - \else \expandafter\DN@\expandafter{\addDOT@{}}\relax - \ifx\next@\circleSTYLE@ \DNii@{\dottedcircle@{}}% - \else \expandafter\DN@\expandafter{\addDOT@2}\relax - \ifx\next@\circleSTYLE@ \DNii@{\dbldottedcircle@{}}% - \else \expandafter\DN@\expandafter{\addDOT@3}\relax - \ifx\next@\circleSTYLE@ \DNii@{\trpldottedcircle@{}}% - \else \DN@{:}\relax - \ifx\next@\circleSTYLE@ \DNii@{\dbldottedcircle@{}}% -% \else\DN@{\circledobjects@}% - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \nextii@ \leave@} - -\xydef@\circletemplate@#1#2{\def\circleSTYLE@{\dir#2{#1}}} -\xydef@\doublecircle@#1{% - \advance\R@-\p@ \advance\L@-\p@ \solidcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \solidcircle@{}} -\xydef@\triplecircle@#1{% - \advance\R@-2\p@ \advance\L@-2\p@ \solidcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \solidcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \solidcircle@{}} - -%\xydef@\dashedcircle@#1{\expandafter\expandafter\expandafter -% \circletemplate@\expandafter\expandafter\expandafter{% -% \expandafter\addDASH@\addDASH@{}}{}\circledobjects@ }% - -\xydef@\dottedcircle@#1{% - \expandafter\def\expandafter\circleSTYLE@\expandafter{% -% \expandafter{\addDOT@{}}}% - \zerodot@i}% - \circledobjects@} - -\xydef@\dashedcircle@#1{% - \expandafter\def\expandafter\circleSTYLE@\expandafter{\zerodash@i}% - \circledobjects@} - -\xydef@\dbldottedcircle@#1{% - \advance\R@-\p@ \advance\L@-\p@ \dottedcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \dottedcircle@{}} -\xydef@\trpldottedcircle@{% - \advance\R@-2\p@ \advance\L@-2\p@ \dottedcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \dottedcircle@{}% - \advance\R@ 2\p@ \advance\L@ 2\p@ \dottedcircle@{}} - -{\xyuncatcodes \gdef\next{=<.75\jot>{\zerodot}}} -\xylet@\zerodot@i=\next - -{\dimen0=2\xydashl@ \xyuncatcodes -\expandafter\gdef\expandafter\next\expandafter{\expandafter - =\expandafter<\the\dimen0 >_\dir{|}}} -\xylet@\zerodash@i=\next - -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\begin{code} -\xy 0;/r5pc/:*\dir{*} - ;p+(.5,-.5)*\dir{*}="c" -,**\dir{-},*+!UL{c},"c" -,*\xycircle(1,.4){++\dir{<}} -,*\xycircle(1,1){++\dir{>}} -,*\xycircle<15pt,10pt>{} -;*\xycircle<10pt>{{.}} -\endxy -\end{code} -$$\docode$$ -\displaycode - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\DOCMODE( -{\xyuncatcodes\gdef\next{--}} -\xylet@\dashcorntemp@@=\next -{\xyuncatcodes\gdef\next{.}} -\xylet@\dotcorntemp@@=\next - -\xydef@\dotcorner@#1{% - \expandafter\circleCorner@\expandafter{\dotcorntemp@@}{#1}}% -\xydef@\dashcorner@#1{% - \expandafter\circleCorner@\expandafter{\dashcorntemp@@}{#1}} - -\xydef@\circleCorner@#1#2{\setboxz@h\bgroup - \edef\next{#2\relax\R@=\the\R@\relax\L@=\R@ }% - \expandafter\xycircle@\next @{#1}% - \ifcase#2\or \setboxz@h{\lower\R@\boxz@\kern\X@c}% - \or \setboxz@h{\kern-\R@\lower\R@\boxz@\kern\R@\kern\X@c}% - \or \setboxz@h{\kern-\R@\lower\R@\boxz@\kern\R@\kern\X@c}% - \or \setboxz@h{\lower\R@\boxz@\kern\X@c}\fi - \wdz@=\R@ \ht\z@=\R@ \dp\z@=\R@ \boxz@ - } -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\subsection{Quadratic Splines} -??=[quadsplines] - -Quadratic B\'ezier splines, as distinct from cubic B\'ezier splines, -are constructed from parabolic arcs, using `control points' to determine -the tangents where successive arcs are joined. - -Various implementations of such curves exist. -The one adopted here is consistent with the |xfig| drawing utility and -\TPIC\ implementations. These have the property of beginning and ending -with straight segments, half the length to the corresponding adjacent -control-point. Furthermore the midpoint between successive control-points -lies on the spline, with the line joining the control-points being tangent -there. - -Such curves are specified, either as a <decor> or as an <object>, -using\dots -\begin{defs1} -|\qspline{|<style>|}| -\end{defs1} -\noindent -where the start and end of the curve are at $p$ and $c$ respectively. -The control-points are taken from the current stack, see~??g[xy.doc:stack]. -If this stack is empty then a straight line is constructed. - -The following example compares the quadratic spline with the gentler -curving B-spline having the same control points, using |\crvs|. -% -\begin{code} -\xy /r1.5pc/:,+<5pc,3pc>*+{P};p -@(,+(2,2)*{+}@+, +(2,-2)*{+}@+ -,+(2,2)*{+}@+, +(2,0)*+{C}="C" -,*\qspline{},"C",**\crvs{.} -,@i @)\endxy -\end{code} -$$\docode$$ -\displaycode - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -If the current stack is empty, simply pass everything to |\crvs@|, as if -the request originated from a |\crvs| or |\ar|. Otherwise we must build up -the segments of the spline. - -\DOCMODE( -\xydef@\qspline{\hbox\bgroup\crvresetbreaks@ \xy@spline@} - -\xydef@\xy@spline@#1#{\if\sempty@ \DN@{\crvs@{}\resetbreaks@}% - \else\DN@{\xy@spline@i{#1}}\fi \next@ }% -\DOCMODE) - -The |#1| parameter to |\xy@spline@i| is to allow -alternative implementations; currently it is ignored. -When |#1| is indeed empty, - -\DOCMODE( -\xydef@\xy@spline@i#1#2{\def\splineSTYLE@{#2}% - \DN@{\xy@spline@ii}\DNii@{#1}% - \ifx\nextii@\empty\DN@{\xy@spline@ii@@}\fi \next@ } - -\xydef@\xy@spline@ii{\save@ \cfromp@\idfromc@{@p}% - \enter@\cplusthec@ \count@@=\s@top\advance\count@@\m@ne - \cfroms@{\count@@}\leave@ - \halve@dimen\X@c % \divide\X@c\tw@ - \halve@dimen\Y@c % \divide\Y@c\tw@ - \czeroEdge@ \idfromc@{@c}% - \expandafter\doSplineStraight@\expandafter{\splineSTYLE@}% - \count@=\@ne \edef\next@{\the\count@}% - \ifx\next@\s@top\DN@{\xy@spline@iv}\else\DN@{\xy@spline@iii}\fi - \next@ } -\xylet@\xy@spline@ii@@=\xy@spline@ii - -\xydef@\xy@spline@iii{\crv@cnt@=\s@top - \loop \advance\crv@cnt@\m@ne \xy@spline@g \ifnum\crv@cnt@>\@ne\repeat - \xy@spline@iv} - -\xydef@\xy@spline@g{\cfromid@{@c}\idfromc@{@p}% - \count@@=\crv@cnt@\cfroms@{\count@@}\idfromc@{@m}% - \enter@\cplusthec@ \count@@=\crv@cnt@ \advance\count@@\m@ne - \cfroms@{\count@@}\leave@ - \halve@dimen\X@c % \divide\X@c\tw@ - \halve@dimen\Y@c % \divide\Y@c\tw@ - \czeroEdge@\idfromc@{@c}% - \expandafter\doSplineSegment@\expandafter{\splineSTYLE@}} - -\xydef@\xy@spline@iv{\cfromid@{@c}\idfromc@{@p}% - \cfroms@{\z@}\idfromc@{@m}\leave@ \save@ - \enter@\cplusthec@ \cfromid@{@m}\leave@ - \halve@dimen\X@c % \divide\X@c\tw@ - \halve@dimen\Y@c % \divide\Y@c\tw@ - \czeroEdge@\idfromc@{@c}% - \expandafter\doSplineSegment@\expandafter{\splineSTYLE@}% - \xy@spline@v } - -\xydef@\xy@spline@v{\cfromid@{@c}\idfromc@{@p}% - \leave@ \save@ \idfromc@{@c}% - \expandafter\doSplineStraight@\expandafter{\splineSTYLE@}% - \xy@spline@x } - -\xydef@\xy@spline@x{\leave@ - \def\Drop@@{\splineDrop@ \resetbreaks@}% - \def\Connect@@{\straight@\relax\splineConnect@ \resetbreaks@}% - \OBJECT@x} - -\xydef@\splineDrop@{\ifInvisible@\setboxz@h{}% - \else\setboxz@h{\kern-\the\X@c\raise-\the\Y@c\hbox{\styledboxz@}}\fi - \wdz@=\z@ \ht\z@=\z@ \dp\z@=\z@ \boxz@ } - -\xydef@\splineConnect@{% - \ifInvisible@\else\box\lastobjectbox@\fi }% -\DOCMODE) - -The initial and final points in a segment are stored as |@p| and |@c| -respectively. Where needed, the control is in |@m|. - -\DOCMODE( -\xydef@\doSplineStraight@#1{\begingroup \sinit@ - \cfromid@{@p}\pfromc@\cfromid@{@c}% - \connect@\crvs{#1}\relax\sleave@\endgroup } - -\xydef@\doSplineSegment@#1{\begingroup \sinit@ - \cfromid@{@p}\pfromc@\senter@\cfromid@{@m}\spushc@\cfromid@{@c}% - \connect@\crvs{#1}\relax\sinit@\sleave@\endgroup } -\DOCMODE) - -\DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\paragraph*{The end \& Log}\leavevmode - -\DOCMODE( -\xyendinput - -% $Log: xycurve.doc,v $ -% Revision 3.7 1999/02/16 15:12:50 krisrose -% Interim release (Y&Y fonts now free). -% -% Revision 3.6 1998/03/06 01:28:05 krisrose -% Releasing (with Y&Y fonts). -% -% Revision 3.4 1997/05/18 01:13:24 ross -% Essential bugfixes. -% -% Revision 3.3 1996/12/18 09:01:45 ross -% major revisions for the new BREAK methods -% spline edge-finding is more robust -% spline-breaks fully implemented -% intersections of curve with straight connections implemented -% improved tracings -% adjusted methods for styles -% -% Revision 3.2 1995/09/19 18:20:20 ross -% Bug fix release. -% -% Revision 3.1 1995/09/05 20:36:33 ross -% Release! -% -% Revision 3.0 1995/07/07 20:13:19 ross -% Major release w/new User's Guide! -% -% Revision 2.13 1995/07/05 07:58:43 ross -% Ready for v3 release? -% -% Revision 2.12 1994/10/25 03:01:14 ross -% Final 3beta release [bug fixes & AMS-LaTeX fitting]. -% -% Revision 2.12 1994/09/05 08:22:11 ross -% incorporates some speed-ups, extra documentation -% -% Revision 2.11 1994/07/05 09:27:52 ross -% Minor fixes; use 2.11 kernel stack code. -% -% Revision 2.9 1994/06/09 14:50:54 ross -% Release 3beta. -% -% Revision 2.8 1994/04/08 10:36:40 ross -% Second 3alpha release. -% -% Revision 2.7 1994/03/08 02:06:01 kris -% Release 3alpha. -% -% Revision 2.6.9.1 1994/03/07 04:22:46 ross -% Last internal 3alpha and pre-2.7 release. -% -% NEW for version 2.7 inspired by Knuth's picmac.tex. -\DOCMODE) - -\DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% Tell Emacs that this is a LaTeX document and how it is formatted: -% Local Variables: -% mode:latex -% fill-column:77 -% End: |