%% $Id: pst-bezier.tex 87 2009-01-29 10:37:06Z herbert $
%%
%% This is file `pst-bezier.tex',
%%
%% IMPORTANT NOTICE:
%%
%% Package `pst-bezier.tex'
%%
%% Tobias Nähring (www.tn-home.de) (inactive)
%% Herbert Voss <hvoss@tug.org>
%%
%% This program can be redistributed and/or modified under the terms
%% of the LaTeX Project Public License Distributed from CTAN archives
%% in directory CTAN:/macros/latex/base/lppl.txt.
%%
%% DESCRIPTION:
%%   `pst-bezier' is a PSTricks package to draw spline curves
%%
%%
\csname PSTbezierLoaded\endcsname
\let\PSTbezierLoaded\endinput

\ifx\PSTricksLoaded\endinput\else\input pstricks.tex\fi
\ifx\PSTXKeyLoaded\endinput\else \input pst-xkey    \fi
\ifx\PSTplotLoaded\endinput\else \input pst-plot    \fi
\ifx\PSTnodesLoaded\endinput\else\input pst-node    \fi

\def\fileversion{0.03}
\def\filedate{2016/09/03}
\message{ v\fileversion, \filedate}

\edef\TheAtCode{\the\catcode`\@}\catcode`\@=11

\pst@addfams{pst-bezier}

%% We need this if we do not have LaTeX:
\expandafter\if\csname gobble\endcsname\relax\def\gobble#1{}\fi
%%
%% \newcommand is not native TeX. Therefore the following definition.
%%%%%%%%%%%%
%% \defopt defines a macro with one optional argument.
%% Syntax:
%%   \defopt\MyNewMacro{DefaultValue}[#1]#2{StuffToBeAssignedToMyNewMacro}
%% where \myNewMacro, DefaultValue, and StuffToBeAssignedToMyNewMacro
%% have the obvious meaning. Instead of #2 up to #9 arguments can be
%% specified.
\def\defopt#1#2{%
  \def\defopt@tmp##1{%
    \expandafter\def\csname##1\endcsname{%
      \def\defopt@tmp{\futurelet\defopt@arg}%
      \expandafter\defopt@tmp\csname##1@opt\endcsname%
    }%
    \expandafter\def\csname##1@opt\endcsname{%
      \if\defopt@arg[%]
        \def\next{\csname##1@@opt\endcsname}%
      \else%
        \def\next{\csname##1@@opt\endcsname[#2]}%
      \fi\next}%
    }%
  \edef\defopt@arg{\expandafter\gobble\string#1}
  \expandafter\defopt@tmp\expandafter{\defopt@arg}%
  \expandafter\def\csname\expandafter\gobble\string#1@@opt\endcsname%
}
%% The postscript part of pst-bezier:
\pstheader{pst-bezier.pro}

%% A list of TeX-code fragments is generated when parsing \psbcurve.
%% The list is managed with the help of these two counters:
\newcount\psbcurve@codeCntrEnd
\newcount\psbcurve@codeCntr
%% These counters should never be set globally.
%% Also the code fragments should never be set globally.
%% The list entries are numberated (therefore the entries can be
%% accessed via \csname only).
%% E. g. for the third entry you have the following items:
%% \csname psbcurve@code3l\endcsname (the left control point)
%% \csname psbcurve@code3r\endcsname (the right control point)
%% \csname psbcurve@code3\endcsname (the interpolated point)
%% \csname psbcurve@code3sl\endcsname (the left scaling factor)
%% \csname psbcurve@code3sr\endcsname (the right scaling factor)
%% \csname psbcurve@code3addon\endcsname (additional code that is run at
%% first)
%% 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Auxiliary macros for dealing
%% with the list TeX-code fragments
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Syntax:
%%  \psbcurve@def[offset]{item}{TeXcode}
%% Where offset is some number (default:0),
%% and item is one of {l,r,sl,sr,addon}.
%% TeXcode will be assigned to the item of the list entry at
%% \psbcurve@codeCntrEnd + offset.
\defopt\psbcurve@def{0}[#1]#2{
  \psbcurve@codeCntr\psbcurve@codeCntrEnd
  \advance\psbcurve@codeCntr by #1
  \expandafter\def\csname psbcurve@code\the\psbcurve@codeCntr#2\endcsname}

%% Essentially the same as \psbcurve@def, but
%% the list item will only be set if it is undefined.
\defopt\psbcurve@defIfVoid{0}[#1]#2{
  \psbcurve@codeCntr\psbcurve@codeCntrEnd
  \let\next\relax
  \advance\psbcurve@codeCntr by #1
  \expandafter\ifx\csname %
        psbcurve@code\the\psbcurve@codeCntr#2\endcsname\relax%
  \def\next{\expandafter\def\csname %
        psbcurve@code\the\psbcurve@codeCntr#2\endcsname}%
  \fi\next}

%% Essentially the same as \psbcurve@def (just \def replaced by \let):
\defopt\psbcurve@let{0}[#1]#2{
  \psbcurve@codeCntr\psbcurve@codeCntrEnd
  \advance\psbcurve@codeCntr by #1
  \expandafter\let\csname psbcurve@code\the\psbcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \psbcurve@letvar[offset]{item}\MyVarToBeSet
%% sets \MyVarToBeSet to the value of the list entry.
%% See the definition of \psbcurve@def for a description
%% of the list entry.
\defopt\psbcurve@letvar{0}[#1]#2#3{
  \psbcurve@codeCntr\psbcurve@codeCntrEnd
  \advance\psbcurve@codeCntr by #1
  \def#3{\noexpand#3}%
  \expandafter\let\expandafter#3\csname psbcurve@code\the\psbcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \psbcurve@ifx[offset]{item}\MyVarToBeCompared
%% That is essentially an \ifx with the list item compared to
%% \MyVarToBeCompared.
\defopt\psbcurve@ifx{0}[#1]#2{
  \psbcurve@codeCntr\psbcurve@codeCntrEnd
  \advance\psbcurve@codeCntr by #1
  \expandafter\ifx\csname psbcurve@code\the\psbcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \psbcurve@get{item}
%% This expands to the macro corresponding to `item' from the
%% list entry at \psbcurve@codeCntr.
\def\psbcurve@get#1{\csname psbcurve@code\the\psbcurve@codeCntr#1\endcsname}


%% Auxiliary macros:
%%%%%%%%%%%%%%%%%%%%%
%% Multiple branching
%% Syntax:
%%   \psbcurve@switch\ExpandingToKey{KeyI,\MacroI,KeyII,\MacroII,...and so on...}
%% If \ExpandingToKey expands to one of the keys KeyI, \KeyII, ...
%% the corresponding \MacroI, \MacroII, ..., resp. is called.
%% The key value \relax is special. Its corresponding \Macro is the
%% default action which is taken if none of the Keys matches.
\def\psbcurve@switch#1#2{%
\def\next##1,##2,##3|{%
\ifx#1##1\relax\def\next####1|{\let\next##2}\fi%
\ifx##1\relax\def\next####1|{\let\next##2}\fi%
\next##3|%
}%
\next#2,\relax,\relax,|\next}

%% The user interface to psbcurve:
%% Usage: See description in pst-bezier-doc.tex.
%% The default value \relax for the optional argument indicates that
%% there are no optional arguments.
\defopt\psbcurve\relax[#1](#2){%
  \bgroup% Makes optional pstricks-settings local to this \psbcurve call.
  \ifx#1\relax\else%
    \psset{#1}%
  \fi%
  \def\psbcurve@code{%
  \moveto(#2)%
    \code{
      <<
      /Splines [%] begin of the array of splines
      [%] begin of the first dummy spline (just the start point)
      /n /n /n /n } \coor(#2) \code{%
      /n /n %[
      ] % end of the first dummy spline
    }% end of \code
  }%
  %% Initialise the list of postscript code fragments:
  \psbcurve@codeCntrEnd0%
  \psbcurve@pointSetDefaults%% Init first spline.
  \psbcurve@def{l}{\coor(#2)}%% Default left control point of the first spline.
  \psbcurve@next%% Now, get the next arguments...
}

%% The following macro declare the pstricks option psbcurveTension
%% and set it to its default value.
\define@key[psset]{pst-bezier}{bcurveTension}[0.25]{\def\psk@bcurveTension{#1}}
\psset[pst-bezier]{bcurveTension=0.25}

%% Points of a spline that are not set yet
%% to a certain value or action
%% get the following value:
\def\psbcurve@ptNotDef{\code{ /n /n }}

%% A newly allocated spline gets the following defaults:
\def\psbcurve@pointSetDefaults{%
  \psbcurve@defIfVoid{l}{\psbcurve@ptNotDef}%
  \psbcurve@defIfVoid{r}{\psbcurve@ptNotDef}%
  \psbcurve@defIfVoid{sl}{\code{ \psk@bcurveTension\space }}%
  \psbcurve@defIfVoid{sr}{\code{ \psk@bcurveTension\space }}%
  \psbcurve@defIfVoid{addon}{}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Now, there comes a series of commands. Depending on the next optional modifier
%% in the argument list of \psbcurve one of these is called. If there follows a
%% point (x,y) without modifier \psbcurve@nextPoint is called. If there follows a token that
%% does not make sense to \psbcurve \psbcurve@end is called.

%% the modifier l
\def\psbcurve@lPoint#1(#2){%
  \psbcurve@def{l}{\coor(#2)}%
  \psbcurve@next}

%% the modifier r
\def\psbcurve@rPoint#1(#2){%
  \psbcurve@def{r}{\coor(#2)}%
  \psbcurve@next}

%% the modifier L
\def\psbcurve@LPoint#1(#2){%
  \psbcurve@def{l}{\coor(#2)}%
  \psbcurve@def[-1]{r}{\code{ /s /s }}%
  \psbcurve@next}

%% the modifier T
\def\psbcurve@Tension#1#2{%
  \psbcurve@def{addon}{\psset{bcurveTension=#2}}%
  \psbcurve@next}

%% The t modifier has some sub-modifiers
%% These are recognised by this macro and the
%% corresponding action is taken.
\def\psbcurve@tension#1{\futurelet\psbcurve@tmp\psbcurve@@tension}
%%
\def\psbcurve@@tension{%
  \psbcurve@switch\psbcurve@tmp{%
    l,\psbcurve@ltension,%
    r,\psbcurve@rtension,%
    s,\psbcurve@stension,%
    \relax,\psbcurve@@@tension
}}

%% the modifier t without further sub-modifiers
\def\psbcurve@@@tension#1{%
  \psbcurve@def{sr}{\code{ #1 }}%
  \psbcurve@def{sl}{\code{ #1 }}%
  \psbcurve@next}

%% the modifier ts
\def\psbcurve@stension#1#2{% symmetric
  \psbcurve@def[-1]{sr}{\code{ #2 }}%
  \psbcurve@def{sl}{\code{ #2 }}%
  \psbcurve@next}

%% the modifier tl
\def\psbcurve@ltension#1#2{% left control point
  \psbcurve@def{sl}{\code{ #2 }}%
  \psbcurve@next}

%% the modifier tr
\def\psbcurve@rtension#1#2{% right control point
  \psbcurve@def{sr}{\code{ #2 }}%
  \psbcurve@next}

%% This macro is called if the next token is
%% no modifier but a point (x,y)
\def\psbcurve@nextPoint(#1){%
  \psbcurve@def{}{\coor(#1)}%
  \advance\psbcurve@codeCntrEnd by 1
  \psbcurve@pointSetDefaults%
  \psbcurve@next}

%% If the next token does not make sense to \psbcurve
%% the curve is finished.
\def\psbcurve@end{
  %% Do we need to set the last control point to its default?
  \def\tmp{\psbcurve@ptNotDef}%
  \psbcurve@ifx[-1]{r}\tmp%
    \psbcurve@letvar[-1]{}\tmp% \tmp is set to the end point
    \psbcurve@let[-1]{r}\tmp% last control point is set to \tmp
  \fi%
  %% pscustom deactivates showpoints: reverse this:
  \let\if@psbcurve@showpoints\ifshowpoints%
  \pscustom{%
    %% Following, the TeX-code fragments in \psbcurve@code...
    %% are executed. These compose the postscript spline array.
    \psbcurve@code%
    \psbcurve@codeCntr0
    \loop%
    \code{[ %]
    }%
    \psbcurve@get{addon}% additional code
    \psbcurve@get{l}% left control point
    \psbcurve@get{r}% right control point
    \psbcurve@get{}% interpolation point
    \psbcurve@get{sl}% left scaling factor
    \psbcurve@get{sr}% right scaling factor
    \code{ %[
      ] }% end of the spline.
    \advance\psbcurve@codeCntr by 1
    \ifnum\psbcurve@codeCntr<\psbcurve@codeCntrEnd%
    \repeat%
    \code{%[
      ] % end of the spline array
      /K 1
      >> pstBCurve
          }%
    \if@psbcurve@showpoints%
      \pst@OpenShowPoints %% works fine, only the dashed lines are missing:
      \code{ \tx@BezierShowPoints }%
    \fi%
  }%
  \egroup%
}

%% The following macro reads the next argument from the \psbcurve argument list
%% recognises optional modifiers and branches to the corresponding macro.
\def\psbcurve@next{\futurelet\psbcurve@tmp\psbcurve@@next}
\def\psbcurve@@next{%
  \psbcurve@switch\psbcurve@tmp{%
  (,\psbcurve@nextPoint,%)
  l,\psbcurve@lPoint,%
  r,\psbcurve@rPoint,%
  L,\psbcurve@LPoint,%
  t,\psbcurve@tension,%
  T,\psbcurve@Tension,%
  \relax,\psbcurve@end}%
}
%
\define@key[psset]{pst-bezier}{nPoints}{\def\psk@nPoints{#1 }}
\define@boolkey[psset]{pst-bezier}[Pst@]{showPolygon}[true]{}
\define@boolkey[psset]{pst-bezier}[Pst@]{autoTrace}[true]{}
% valeurs par défaut
% les coordonnées des points de contrôle P0= x0 y0, etc.
%\psset[pst-RQBC]{P0=2 0,P1=2 2,P2=0 2,w=1 0.707 1,n=400,showPoints=true,showPolygon=false}
\psset[pst-bezier]{nPoints=400,showPolygon=false,autoTrace=false}
%
\def\pst@get@w#1,#2,#3\@nil{%
  \def\pst@@w{#1 #2 #3 }%
  \def\psk@wZero{#1 }%
  \def\psk@wUn{#2 }%
  \def\psk@wDeux{#3 }}
%
\def\psRQBCmasse{\def\pst@par{}\pst@object{psRQBCmasse}}
\def\psRQBCmasse@i(#1)(#2)(#3)#4{{%
%  \addbefore@par{showpoints=false}%
  \begin@SpecialObj
  \pst@get@w#4\@nil
  \pst@getcoor{#1}\pst@tempA
  \pst@getcoor{#2}\pst@tempB
  \pst@getcoor{#3}\pst@tempC
  \pst@cntm=\pscalculate{abs(\psk@wZero)<1e-6 ? 0 : 1}%
  \pst@cntn=\pscalculate{abs(\psk@wUn)<1e-6 ? 0 : 2}%
  \pst@cnto=\pscalculate{abs(\psk@wDeux)<1e-6 ? 0 : 4}%
  \edef\ps@choix{\the\numexpr\pst@cntm+\pst@cntn+\pst@cnto}%
%  \typeout{>>pst-bezier: ps@choix=\ps@choix}%
  \pstVerb{
%  \addto@pscode{
    tx@Dict begin 
    /nB \psk@nPoints def
    \pst@tempA \tx@UserCoor /yP0 exch def /xP0 exch def
    \pst@tempB \tx@UserCoor /yP1 exch def /xP1 exch def
    \pst@tempC \tx@UserCoor /yP2 exch def /xP2 exch def
    \pst@@w /w2 exch def /w1 exch def /w0 exch def
    /choix \ps@choix\space def
    tx@RQBCmasse 
    end 
  } % fin pstVerb
  \pnodes(#1){P0}(#2){P1}(#3){P2}
  \pnode(!P0P1){P0P1}
  %\pnode(!P1P0){P1P0}
  \pnode(!P1P2){P1P2}
  \pnode(!P0P2){P0P2}
  \pslistplot{RQBCmasse1}\pslistplot[showpoints=false]{RQBCmasse2}%
  \ifPst@autoTrace
    \ifcase\ps@choix
    \or %1
      \psline[linestyle=dashed,linecolor=black,arrowinset=0.1,arrowsize=0.2]{->}(#1)(P0P1)
      \psline[linestyle=dashed,linecolor=green,arrowinset=0.1,arrowsize=0.2]{->}(#1)(P0P2)
      %\psline[linestyle=dashed,linecolor=magenta,arrowinset=0.1,arrowsize=0.2]{->}(P1)
      \psdots(#1)%(P1)(P2)
    \or %2
      \psline[linestyle=dashed,linecolor=black,arrowinset=0.1,arrowsize=0.2]{->}(#2)(P0P1)
      \psline[linestyle=dashed,linecolor=green,arrowinset=0.1,arrowsize=0.2]{->}(#2)(P1P2)
      %\psline[linestyle=dashed,linecolor=magenta,arrowinset=0.1,arrowsize=0.2]{->}(P1)
      \psdots(#2)%(P1)(P2)
    \or %3
    \or %4
      \psline[linestyle=dashed,linecolor=black,arrowinset=0.1,arrowsize=0.2]{->}(#3)(P1P2)
      \psline[linestyle=dashed,linecolor=green,arrowinset=0.1,arrowsize=0.2]{->}(#3)(P0P2)
      %\psline[linestyle=dashed,linecolor=magenta,arrowinset=0.1,arrowsize=0.2]{->}(P1)
      \psdots(#3)%(P1)(P2)
    \or % 5
      \psline[linestyle=dashed,linecolor=black,arrowinset=0.1,arrowsize=0.2]{->}(#1)(P0P1)
      \psline[linestyle=dashed,linecolor=green,arrowinset=0.1,arrowsize=0.2]{->}(#3)(P1P2)
      \psline[linestyle=dashed,linecolor=magenta,arrowinset=0.1,arrowsize=0.2]{->}(#2)
      \psdots(#1)(#2)(#3)
    \or %6
    \or %7
      \psline(#1)(#2)(#3)\psdots(#1)(#2)(#3)
    \fi
  \fi
 \end@SpecialObj}\ignorespaces}
%
\catcode`\@=\TheAtCode\relax
\endinput

