%% rgbx0025.mp
%% Copyright 2006 Tommy Ekola <[email protected]>
%
% This work may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, either version 1.3 of this license
% or (at your option) any later version.  The latest version of this
% license is in http://www.latex-project.org/lppl.txt
%
% This work has the LPPL maintenance status `maintained'.  The Current
% Maintainer of this work is Tommy Ekola.  The Base Interpreter is
% MetaPost.

vardef setup_paralleloppositerightarrows (expr source_file, cmdname) =

 scantokens ("input tgbx0000");

 scantokens ("input " & source_file);

 expandafter def scantokens cmdname expr p =
   scantokens (cmdname & "__rgbxww")(p)
 enddef;

 expandafter vardef scantokens (cmdname & "__rgbxww " & "(expr apth) " &
   "text text_ = " &

   "save math_spread, x_height, u, rule_thickness, bar, math_axis," &
   "     asc_height, eps, fudge, crisp, hair;" &

   "math_spread     :=" & decimal math_spread & ";" &
   "x_height#       :=" & decimal x_height# & ";" &
   "u#              :=" & decimal u# & ";" &
   "rule_thickness# :=" & decimal rule_thickness# & ";" &
   "bar#            :=" & decimal bar# & ";" &
   "math_axis#      :=" & decimal math_axis# & ";" &
   "asc_height#     :=" & decimal asc_height# & ";" &
   "eps             :=" & decimal eps & ";" &
   "fudge           :=" & decimal fudge & ";" &
   "crisp#          :=" & decimal crisp# & ";" &
   "hair#           :=" & decimal hair# & ";")

   save prevpen;
   prevpen:=savepen;

   save x,y;
   numeric x[], x[]', x[]l, x[]'l, x[]r, x[]'r,
           y[], y[]', y[]l, y[]'l, y[]r, y[]'r;
   save spread, w;
   numeric spread, w;

   if crisp#>fudge*hair#:
     crisp#:=fudge*hair#;
   fi
   pickup if crisp#=0: nullpen else: pencircle scaled crisp# fi;

   spread = math_spread[.45x_height#, .55x_height#];
   w = 18u#;

   penpos1(rule_thickness#, 90); penpos2(rule_thickness#, 90);
   penpos3(bar#, 0);             penpos4(bar#, 0);
   y0=y1=y2=math_axis#; x1-.5rule_thickness#=u#; rt x0=w-u#;
   y3-y0=y0-y4=.24asc_height#+eps;
   x3=x4=x0-3u#-eps;
   penpos5(bar#, angle(z4-z0)); z5l=z0;
   penpos6(bar#, angle(z3-z0)); z6l=z0;
   z9=.381966[.5[z3,z4],z0];

   save pp; path pp;   pp = z4l{z9-z4}..z6r;
   save t; numeric t;  t = xpart(pp intersectiontimes ((0,y2l)--(w,y2l)));
   x2=xpart point t of pp;

   % Path macros

   save parallellineright;
   vardef parallellineright expr pppp =
     save s, stp;
     numeric s, stp; stp:=(arclength pppp) div 5pt;
                     if stp=0: stp:=1; fi
                     stp:=(arclength pppp)/stp;

     if stp>0:
     for s=0 step stp until arclength pppp - stp:
            point (arctime s of pppp) of pppp +
            (.24asc_height#+eps)*(unitvector direction (arctime s of pppp)
                                                       of pppp rotated 90)
            {direction (arctime s of pppp) of pppp}..
          endfor
          {direction (length pppp) of pppp}
          point (length pppp) of pppp +
          (.24asc_height#+eps)*(unitvector direction (length pppp)
             of pppp rotated 90)
     fi
   enddef;

   save parallellineleft;
   vardef parallellineleft expr pppp =
     save s, stp;
     numeric s, stp; stp:=(arclength pppp) div 5pt;
                     if stp=0: stp:=1; fi
                     stp:=(arclength pppp)/stp;

     if stp>0:
     for s=0 step stp until arclength pppp - stp:
            point (arctime s of pppp) of pppp -
            (.24asc_height#+eps)*(unitvector direction (arctime s of pppp)
                                                       of pppp rotated 90)
            {direction (arctime s of pppp) of pppp}..
          endfor
          {direction (length pppp) of pppp}
          point (length pppp) of pppp -
          (.24asc_height#+eps)*(unitvector direction (length pppp)
              of pppp rotated 90)
     fi
   enddef;

   save mapto, n;
   vardef mapto(text t) =
     hide(numeric n; n:=0;
          numeric x,x_[],y,y_[];
          for z=t: z_[incr n]:=z; endfor;
          transform T;
          z_2 = z_1 transformed T;
          z_4 = z_3 transformed T;
          z_6 = z_5 transformed T;)
     T
   enddef;

   % Macros for drawing the arrow head

   save pp; path pp; pp = z4l{z9-z4}..z6r;
   save pq; path pq; pq = z0..{z4-z9}z4r;
   save right_texarrowhead;
   vardef right_texarrowhead(expr T,s) =
     (subpath(0, xpart (pq intersectiontimes
           (point s of pp -- point s of pp + (2rule_thickness#,0))))
       of pq--subpath(s,t) of pp--z2l) transformed T
   enddef;

   save qq; path qq; qq = z3l{z9-z3}..z5r;
   save qp; path qp; qp = z3r{z9-z3}..z0;
   save left_texarrowhead;
   vardef left_texarrowhead(expr T, s) =
     (z2r--subpath(t,s) of qq
       --subpath(xpart ( qp intersectiontimes
           (point s of qq -- point s of qq + (2rule_thickness#,0)))
         ,length qp) of qp) transformed T
   enddef;

   % Draw the arrows. First the left arrow and then the right arrow

   save pa, pb, T, tt, ttt;
   save f,s;

   save p_left;  path p_left;  p_left  := parallellineleft apth;
   save p_right; path p_right; p_right := parallellineright apth;

   for ppp = p_left, reverse p_right:
     transform T;
     numeric tt;  tt  := arctime(arclength ppp - (x0-x9)) of ppp;
     numeric ttt; ttt := arctime(arclength ppp - (x0-x2)) of ppp;

     % Draw the right half of the arrow head

     if   arclength ppp = 0:
       T:=identity shifted (point (length ppp) of ppp - z0);
     elseif arclength ppp < x0-x3l:
       T:=identity rotatedaround(z0,angle (direction (length ppp) of ppp))
       shifted (point (length ppp) of ppp - z0);
     else:
       T:=mapto(z0,
                point (length ppp) of ppp,
                z2,
                point ttt of ppp,
                z9-(0,3rule_thickness#),
                point tt of ppp - 3rule_thickness#
                                    *(unitvector (direction tt of ppp)
                                    rotated 90));
     fi

     vardef f(expr s) =
       length(point s of (pp transformed T) - point tt of ppp)
       < length(point 0 of pp - z9)
     enddef;

     if f(0) or (arclength ppp < x0-x3l): s := 0;
     else:    s := solve f(length pp, 0);
     fi

     path pa;
     pa := right_texarrowhead(T,s);

     % Draw the left part of the arrow head

     if   arclength ppp = 0:
       T:=identity shifted (point (length ppp) of ppp - z0);
     elseif arclength ppp < x0-x3l:
       T:=identity rotatedaround(z0,angle (direction (length ppp) of ppp))
       shifted (point (length ppp) of ppp - z0);
     else:
       T:=mapto(z0,
                point (length ppp) of ppp,
                z2,
                point ttt of ppp,
                z9+(0,3rule_thickness#),
                point tt of ppp + 3rule_thickness#
                                    *(unitvector (direction tt of ppp)
                                    rotated 90));
     fi

     vardef f(expr s) =
       length(point s of (qq transformed T) - point tt of ppp)
       < length(point 0 of qq - z9)
     enddef;

     if f(0) or (arclength ppp < x0-x3l): s := 0;
     else:    s := solve f(length qq, 0);
     fi

     path pb;
     pb := left_texarrowhead(T,s);

     filldraw pa--pb--cycle text_;

     % Draw the path

     if arclength ppp > x0-x2:
       draw subpath(0,ttt) of ppp withpen pencircle scaled rule_thickness#
       text_;
     fi

   endfor

   pickup prevpen;

 enddef;

enddef;