# $Source: /u/maple/research/lib
#/DEtools/src/RCS/DEplot,v $
#
# DEplot (DE,vars,trange,<options>)
# DEplot (DE,vars,trange,xrange,yrange,<options>)
#
#  Author: 					Katy Simonsen, June 1991
#  Modified by: 				Adam Judson, May 1992
#  Modified by: 				George Labahn, July 1992
#  Modified and overhauled:			Blaine Campbell, July 1994
#  Undocumented backwards compatability fixes: 	B. Campbell, August 1995
#  Fix due to nullificatoin of revision 53.15 by 53.17, 
#  	and added error message for dfield plots with an
#	indep var in the scene:			B. Campbell, June 1996
# Modified by:                                                                    M. Ebrahimi, M. Monagan, May 2004
#                added numsteps and velocity options, 
#                improved arrow shapes and help page examples
#
#  Given a system of first order differential equations of the form 
#  x' = f1(t,x,y,...), y' = f2(t,x,y,...), ..., and a list of initial 
#  conditions, DEplot produces a plot of the solution curves for the 
#  differential equation system under those initial conditions.
#  If the system is determined to be autonomous, DEplot will also produce
#  a direction field, by default. 
#
#  When no initial conditions are given, only arrows (direction field) will
#  be plotted, if possible.  If solution curves alone are desired (no arrows),
#  the option arrows='NONE' should be used.
#
#  Added velocity option to capture the velocity of the direction field by
#  either using color (velocity=color) or changing the size of the arrows (velocity=length).
#
#*** SUGGESTIONS FOR FUTURE IMPROVEMENTS
#  1) Allow the user to specify D's in the scene for higher order systems,
#     to allow views of the regular variables, versus derivative values
#     (this information is already available upon return from dsolve[numeric]).
#     Will require redesign of the w structure to indicate plot variables,
#     along with change to vars & dvar to hold diff forms for subs into
#     dsolve[numeric] returns.  Design issue of how the user is to specify 
#     'scene' when specifying a derivative.
#  2) Internal rk4 (or other) fixed step integrator to give greater speed
#     when generating lines.
#  3) Option to force DEplot to assume a system is autonomous and use what
#     it can when generating direction fields.
#  4) See "NOTE"'s in the code.
#***
#
# ARGUMENTS
# ---------
#
# DE
#  DE should indicate a system of differential equations in one 
#  of the following equivalent forms:
#      
#     [diff(x(t),t)=f1(t,x,y,z),diff(y(t),t)= f2(t,x,y,z),...]
#     [diff(x(t),t)-f1(t,x,y,z)=0,diff(y(t),t)-f2(t,x,y,z)=0,...]
#     [diff(x(t),t)-f1(t,x,y,z),diff(y(t),t)-f2(t,x,y,z),...]
#     [D(x)(t)=f1(t,x,y,z),D(y)(t)=f2(t,x,y,z),...]
#
#  There may be ONLY one independent variable.
#
# vars 
#  For all systems, vars should be of the form [x(t),y(t),...].
#  In the all cases, the default view will be to plot the first two
#  independent variables, though this may be changed with the "scene" option.  
#
# trange 
#  trange may be of the form a..b or t=a..b, where a and b are real
#  constants, and t is the independent variable.
#
   macro( `DEtools/makefunc`   = `plot3d/makefunc`,
          `DEtools/DEplot/HighCheck`  = `DEtools/highorder`,
          `DEtools/DEplot/Autonomous` = `DEtools/autonomous`,
          `t`  = `DEtools/DEplot_t`,    `N` = `DEtools/DEplot_N`,
          `Y`  = `DEtools/DEplot_Y`,   `YP` = `DEtools/DEplot_YP`,
          `a1` = `DEtools/DEplot_a1`,  `a2` = `DEtools/DEplot_a2`,
          `_x` = `DEtools/DEplot_x`,   `_y` = `DEtools/DEplot_y`,
          `_v` = `DEtools/DEplot_v`,   `_body1` = `DEtools/DEplot_body1`,
          `_body2` = `DEtools/DEplot_body2`,  `_ivar` = `DEtools/DEplot_ivar`,
          `_func` = `DEtools/DEplot_fund`
        ):


`DEtools/DEplot`  := proc(inDES, invars, trange)

   local dvrange,linepts,initial,features_p,ni,iter,ivar,dvar,\
       lims,rang,toplot,f,IC,w,h,i,j,m,n,eivar,nDES,DES,vars,\
       highorder,colorinfo,arrowpts,arrw,test1,test2,features_n,\
       stopp,result1,plot_3,left,right,label_ftr,arguments,features,\
       line_color,totalorder,velocitycol,velocitylen,randomarrow;

   global _plotDigits,data1,data2;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   _plotDigits := Digits;

   # Check if we are to produce a 3D plot.
   if args[nargs] = 'call_from_DEplot3d' then
      plot_3 := true; 
   else 
      plot_3 := false;
   fi;

   # Check inputs and set the variable specifications.
   `DEtools/DEplot/InputCheck`(inDES,invars,trange,'DES','vars','nDES',\
       'ndvar','ivar','dvar','rang');
   # Check for a higher order equation.
   highorder := `DEtools/DEplot/HighCheck`(DES);
   totalorder := `DEtools/DEplot/TOrder`(DES,nDES);

   # Set range limits for independent variable.
   left := evalf(op(1,rang),_plotDigits); 
   right := evalf(op(2,rang),_plotDigits);
   lims[1,1] := min(left,right);
   lims[1,2] := max(left,right);
   if lims[1,2] = lims[1,1] then
      error "Invalid range for independent variable";
   fi;
   if not(type(lims[1,1],realcons) and type(lims[1,2],realcons)) then
      error "Limits on trange must be evaluate to numerical values.";
   fi;
   # Analyse optional arguments
   arguments := [seq(args[i],i=4..nargs)];
   `DEtools/DEplot/AnalyseOptions`(arguments,'features_p',\
        'features_n','h','iter','arrw','m','n','colorinfo','toplot',\
        'stopp','ni','initial','label_ftr','dvrange','lims','IC',ndvar,\
        plot_3,dvar,vars,ivar,highorder,'totalorder','line_color','velocitycol','velocitylen','randomarrow');
   features_n := [features_n];

   if ni = 0 and member(false,convert(dvrange,set)) and not(highorder) then
      error "All dependent variable ranges must be specified.";
   fi;
   if not(plot_3) and ni = 0 and nDES > 2 then
      error "Direction fields may only be produced for systems with two"
          " or less, dependent variables.";
   fi;

   # Determine if the system of DE's is in fact autonomous.
   if not(plot_3) then                         # only check 2-D 
      eivar := false;
      if not(type(DES,list(procedure))) and ndvar <> 1 and not(highorder) then
         eivar := `DEtools/DEplot/Autonomous`(DES,dvar,ivar);
      fi;
      if type(DES,list(procedure)) then eivar := true fi;
      userinfo(10,'`DEtools/DEplot`',`System of DE's is assumed autonomous: `, \
                   eivar);
      if ni = 0 and not(eivar) and (nDES <> 1 or highorder) then
         error "Cannot produce plot non-autonomous DE(s) require initial conditions.";
      fi;
   fi;

   # Decide on which variables are to be plotted on which axes.
   toplot := `DEtools/DEplot/WhichPlot`(toplot,plot_3,highorder,ivar,dvar);
   # Set w array to indicate variables graphed by number labels
   for i from 1 to nops(toplot) do
      if toplot[i] = ivar then
         if not(plot_3) and ni = 0 and nDES > 1 then
     error "Direction fields are not available for systems with multiple"
       " dependent variables and a scene containing the independent variable."
         else
            w[i] := 1
         fi
      else
         for j from 1 to ndvar do
            if toplot[i] = vars[j] or toplot[i] = dvar[j] then
               w[i] := j+1;
            fi;
         od;
      fi;
   od;
   i := 'i'; w := [seq(w[i],i=1..nops(toplot))];

   # Ensure proper labelling if the user has not specified it.
   if label_ftr = NULL then
      label_ftr := 'labels'=[seq(convert(op(i,toplot),string),\
          i=1..nops(toplot))];
   fi;

	# Check for co-ords
	i := select(type,{features_p},identical('coords')='anything');
	i := remove(type,i,identical('coords'='cartesian'));
	if i<>{} then
	  error "can only plot in cartesian co-ordinates, got invalid option %1",i[1];
	fi;
	features_p := remove(type,[features_p],identical('coords')='anything');

   # Set plot features.
   if plot_3 then
      features := [`plots/getoptions3d`(`plot3d/options3d`(op(features_p),label_ftr))];
   else
      features := [`plots/getoptions`([`plot/options2d`(op(features_p),label_ftr)])];
   fi;

   # Check the DE's; isolate for the slope functions if needed for dir field.
   # This code has been placed this far along in the proceedings as eivar
   # must be determined beforehand (in case the slope funcs are not needed).
   test1 := false;   test2 := false;  result1 := false;
   if not(plot_3) then
      test1 := ndvar = 2 and eivar and not(arrw='NONE'); 
      test2 := ndvar = 1 and not(highorder) and not(arrw='NONE');
   fi;
   if not(plot_3) and (test1 or test2) then result1 := true; fi;
   `DEtools/DEplot/CheckDE`('DES',nDES,ivar,ndvar,vars,dvar,'f',w,plot_3,\
       result1);

   # If there are initial conditions -> lines to draw.
   linepts := []; 
ni;
   if ni > 0 then 
      linepts := `DEtools/DEplot/CreateLines`(ni,IC,'lims',h,iter,dvrange,\
          DES,initial,vars,ivar,stopp,w,plot_3,features_n,line_color,
          op(select(type,features,specfunc(anything,'THICKNESS'))));
   fi;

	# Now if limits are empty, we want to extend them by a small amout
	if lims[1,1]=lims[1,2] then
		i := 0.00005*max(1e-15,abs(lims[1,1]));
		lims[1,1] := lims[1,1]-i; lims[1,2] := lims[1,2]+i;
	fi;
	if lims[2,1]=lims[2,2] then
		i := 0.00005*max(1e-15,abs(lims[2,1]));
		lims[2,1] := lims[2,1]-i; lims[2,2] := lims[2,2]+i;
	fi;
	if plot_3 and lims[3,1]=lims[3,2] then
		i := 0.00005*max(1e-15,abs(lims[3,1]));
		lims[3,1] := lims[3,1]-i; lims[3,2] := lims[3,2]+i;
	fi;
 
   #creating data for random plot
   if randomarrow>0 then
       data1:=rtable(0..randomarrow,frandom(lims[w[1],1]..lims[w[1],2]),datatype=float[8]);
       data2:=rtable(0..randomarrow,frandom(lims[w[2],1]..lims[w[2],2]),datatype=float[8]);
   else
       data1:=rtable(0..randomarrow,datatype=float[8]);
       data2:=rtable(0..randomarrow,datatype=float[8]);
   fi;
   # Process color information (if it exists).
   if test1 or test2 then
      if colorinfo <> NULL then
         if randomarrow=0 then
         colorinfo := `DEtools/DEplot/CreateColour`(colorinfo,lims,m-1,n-1,ivar,dvar,vars,w,randomarrow);
         else
          colorinfo := `DEtools/DEplot/CreateColour`(colorinfo,lims,randomarrow-1,randomarrow-1,ivar,dvar,vars,w,randomarrow);
         fi;
      elif velocitycol='true' then
         colorinfo :=`DEtools/DEplot/Colorfun`(f,lims,m,n,arrw,ndvar,w,test1,test2,randomarrow);
      else
         if randomarrow=0 then
             colorinfo:=COLOR('HUE',seq(seq(0,i=1..m),j=1..n));
         else
             colorinfo:=COLOR('HUE',seq(0,i=1..randomarrow));
         fi;
      fi;
   else
      colorinfo := false;
   fi;

   # Plot direction fields if possible.
   if not(plot_3) and (test1 or test2) then
      arrowpts := `DEtools/DEplot/CreateArrows`(f,lims,m,n,arrw,ndvar,w,test1,test2,velocitylen,randomarrow,colorinfo);
   else
      arrowpts := [];
   fi;

   # Produce the actual plots.
   `DEtools/DEplot/CreatePlots`(plot_3,lims,linepts,m,n,arrowpts,w,features);
end:  # `DEtools/DEplot`
#-------------------------------------------------------------------------
# Check the input variables.  Set needed variables for later.

`DEtools/DEplot/InputCheck`:=proc(indes,invars,trange,des,vars,ndes,nvars,\
    ivar,dvar,rang)

   local indep,i,deS,varS,ndeS,nvarS,ivaR,dvaR,ranG;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   # Check that DE's are algebraic equations - make into lists.
   if type(indes,{algebraic,equation}) or type(indes,procedure) then
      deS := [indes];
   elif type(indes,set({algebraic,equation})) and not \
       type(indes,set(procedure)) then 
      deS := convert(eval(indes),list);
   elif type(indes,list({algebraic,equation})) and not \
       type(indes,list(procedure)) then
      deS := eval(indes);
   else
      error "DEs must be a list of algebraic equations, or a procedure.";
   fi;

   # Get input variables into the proper internal form.
   indep := true;                        # independent variable is present
   if type(invars,set(function(name))) then
      varS := convert(invars,list);
   elif type(invars,set(name)) then
      varS := convert(invars,list);
      indep := false;
   elif type(invars,function(name)) then
      varS := [invars];
   elif type(invars,name) then
      varS := [invars];
      indep := false;
   elif type(invars,list(function(name))) then
      varS := invars;
   elif type(invars,list(name)) then
      varS := invars;
      indep := false;
   else
      error "vars must be declared as a list, e.g. [x(t),y(t),...]";
   fi;

   nvarS := nops(varS);                  # number of variables (dependent)
   ndeS := nops(deS);                    # number of DE's in the system
   if nvarS <> ndeS and not type(deS,list(procedure)) then         
      error "System must have same number of dependent variables as DE's.";
   fi;

   # Ensure the input variable set is valid.
   if nops({op(varS)}) <> nops(invars) then
      error "Variables repeated in vars: %1", invars;
   fi;
   if indep then
      ivaR := op(1,varS[1]);             # independent variable
   fi;
   for i from 1 to nvarS do              # set dvaR form & check 
      if indep then
         if nops(op(1,varS[i])) <> 1 then
            error "Only one independent variable allowed in: %1", varS[i];
         fi;
         if op(1,varS[i]) <> ivaR then
            error "Must be a function of independent variable: %1", varS[i];
         fi;
         dvaR[i] := op(0,varS[i]);
      elif type(varS[i],name) then
         dvaR[i] := varS[i];
      else
         error "Illegal variable %1", varS[i];
      fi;
   od;
   dvaR := [seq(dvaR[i],i=1..nvarS)];
   # Check range of independent variable.
   if type(trange, name=realcons..realcons) then
      ranG := op(2, trange);
      if indep then                      # make sure proper range
         if not(op(1, trange) = ivaR) then
            error "Incorrect variable in specification of independent"
                " variable range.";
         fi;
      else
         ivaR := op(1,trange);
      fi;
   elif type (trange,realcons..realcons) then

      ranG := trange;
      if not(indep) then                 # no indep var given in varS
         error "Must indicate the independent variable.";
      fi;
   else
      error "Invalid range for independent variable.";
   fi;
# NOTE:  Allowing the following construction of varS is kept only to allow
#        for backward compatability.  It should be removed for versions
#        after bobcat (V.4).
   if not indep then
      for i from 1 to nvarS do
         varS[i] := subs(_y=varS[i],_x=ivaR,_y(_x))
      od
   fi;

   des := deS; vars := varS; ndes := ndeS; nvars := nvarS; ivar := ivaR;
   dvar := dvaR; rang := ranG;
end:  # `DEtools/DEplot/InputCheck`

#-------------------------------------------------------------------------
# Determine the total order of a system (i.e. sum of orders of DEs).

`DEtools/DEplot/TOrder` := proc( des,ndes )
   
   option `Copyright (c) 1995 by Waterloo Maple Inc. All rights reserved.`;
   local tord, i, desi, mx, de, d, dx;
   tord := 0;
   if not type(des,procedure) then
      for i from 1 to ndes do
         if has(op(i,des),'D') then 
            desi := indets(collect(convert(op(i,des),'diff'),'diff'),function)
         else 
            desi := indets(collect(op(i,des),'diff'))
         fi;
         desi := map(proc(x) if has(x,'diff') then x fi end, desi);
         mx := 0;
         for de in desi do
            d := de;  dx := 0;
            while has(d,'diff') do d := op(1,d);  dx := dx + 1 od;
            if dx > mx then mx := dx fi
         od;
         tord := tord+mx
      od;
   fi;
   return tord
end:

#-------------------------------------------------------------------------
# Analyse the optional input equations for validity; set variables.

`DEtools/DEplot/AnalyseOptions`:=proc(arguments,features_p,\
    features_n,h,iter,arrw,m,n,colorinfo,toplot,stopp,ni,initial,label_ftr,\
    dvrange,lims,IC,ndvar,plot_3,dvar,vars,ivar,highorder,totalorder,\
    line_color,velocitycol,velocitylen,randomarrow)

   local i,j,opt,l,r,ri,narg,ftr_p,ftr_n,method_ftr,hl,arrowsize,\
       ml,nl,plotview,deprange,cinfo,labels,stopb,nlines,iters,plot3dftr,\
       plot2dftr,numfeatures,l_color,hval,t_ord,velocitycolor,velocitylenght,random;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   userinfo(6,'`DEtools/DEplot`',`analysing arguments.`);

   # currently allowed options for plot3d, plot, and dsolve/numeric
   plot3dftr := {'ambientlight','axes','axesfont','color','colour','contours',\
       'coords','font','labelfont',':-labels','light','linestyle','orientation',\
       'projection','scaling','shading','style','symbol','thickness',\
       'tickmarks','title','titlefont','view'};
   plot2dftr := {'axes','axesfont','color','colour','coords','font',\
       'labelfont','linestyle','resolution','scaling','style','symbol',\
       'thickness','title','titlefont','view','xtickmarks','velocity'};
   numfeatures := {'abserr','control','corrections','ctrl','errorper', \
       'initial','itask','maxder','maxfun','maxkop','maxord','maxpts', \
       'maxstep','method','minrel','minstep','relerr', \
       'start','startinit','stepsize','tolerance','value',\
       'stiff','maxfevals'};
   # Added above two 'stiff','maxfevals' for SC code

   hl := evalf((lims[1,2]-lims[1,1])/50,_plotDigits);  # stepsize
     # increased default #points from 20 to 50 by MBM and Moe Ebrahimi May/04
   iters := 1;                          # steps to make between plotted points
   velocitycolor:=false:         #velocity option
   velocitylenght:=false;        #velocity option
   arrowsize := 'SMALL';                # arrows to use
   ml := 20; nl := 20;                  # grid points for arrows
   random:=0;	            #number of random arrows if dirgrid=posint
   plotview := [];                      # variables to be plotted
   stopb := true;                       # stop at integration limits
   nlines := 0;                         # number of lines to plot
   method_ftr := 'method=classical[rk4]'; # numerical method used
   deprange := array(1..ndvar);         # boundary setting
   for i from 1 to ndvar do deprange[i] := false; od;
   ftr_p := NULL; ftr_n := NULL;        # user input features
   cinfo := NULL;                       # colouring information
   l_color := NULL;                     # line colouring information
   labels := NULL;                      # axes labels
   t_ord := eval(totalorder);
   if plot_3 then narg := nops(arguments)-1; else narg := nops(arguments); fi;

   for j from 1 to narg do
      opt := arguments[j];              # option being considered
      type(opt,{list,set}) ;
      if type(opt,{list,set}) then      # initial conditions
         `DEtools/DEplot/CheckInitial`(opt,'nlines','IC','initial',ndvar,dvar,highorder,t_ord);
      elif not(type(opt,equation)) then
         error "Option %1 must be specified as an equation.", opt;
      else
         l := op(1,opt); 
         r := op(2,opt);
         if member(l,{op(dvar),op(vars)}) and type(r,realcons..realcons) then
                                        # check for specific ranges on dep vars
            for i from 1 to ndvar do
               if (l = dvar[i] or l = vars[i]) then
                  lims[i+1,1] := evalf(op(1,r),_plotDigits);
                  lims[i+1,2] := evalf(op(2,r),_plotDigits);
                  if lims[i+1,1] >= lims[i+1,2] then 
                     error "Invalid range for  %1", l;
                  fi;
                  deprange[i] := true;
               fi;
            od;
         elif l = 'number' then            # number of first order eqns
            t_ord := r 
         elif l = 'method' then            # numerical method
            method_ftr := opt;
         elif l = ':-labels' then             # axes labels
            labels := opt;
         elif l = 'iterations' then        # iterations between steps
            if type (r,posint) then
               iters := r;
            else
               error "Invalid number of iterations, must be a positive integer: %1", opt;
            fi;

         elif l = 'velocity' then
               if r='color' then velocitycolor :=true; cinfo:=NULL;
               elif r='length' then velocitylenght:=true;
               elif r='none' then velocitycolor:=false; velocitylenght:=false;
               else  error "invalid option, options for velocity are color and lenght:%1,opt;"
               fi;
       
         elif l = 'arrows' then            # arrow sizes
            if not(plot_3) then
               if member(r,{'SMALL','MEDIUM','LARGE','NONE','FISH','CURVE'}) then
                  arrowsize:= r;
               elif (r = 'fish' or r = 'Fish' ) then 
                  arrowsize := 'FISH';
               elif (r = 'curve' or r = 'Curve') then 
                  arrowsize := 'CURVE';
               elif (r = 'small' or r = 'thin' or r = 'THIN') then 
                  arrowsize := 'SMALL';
               elif (r = 'medium' or r = 'slim' or r = 'SLIM') then
                  arrowsize := 'MEDIUM';
               elif (r = 'large' or r = 'thick' or r = 'THICK') then
                  arrowsize := 'LARGE';
               elif r = 'none'  then arrowsize := 'NONE';
               else error "Invalid arrow specification, must be one of "
                   "SMALL, MEDIUM, LARGE, NONE,FISH,CURVE: %1", opt;
               fi;
            else
               userinfo(1,'`DEtools/DEplot3d`',`arrows ignored.`);
            fi;
         elif l = 'dirgrid' then           # dim of grid for direction field
            if not(plot_3) then
               if type (r,[posint,posint]) and r[1] > 1 and r[2] > 1 then
                  ml := r[1]; nl := r[2];
               elif type (r,posint) and r>1 then 
                   random:=r;

               else error "Invalid grid specification, must be list of "
                   " positive integers or a positive integer number: %1", opt;
               fi;
            else
               userinfo(1,'`DEtools/DEplot3d`',`dirgrid ignored.`);
            fi;
         elif l = 'colour' or l = 'color' then  # colourinfo spec.
            if not(plot_3)   then
               cinfo := r; velocitycolor=false;
            else
               userinfo(1,'`DEtools/DEplot3d`',`colour ignored.`);
            fi;
         elif l = 'linecolor' or l = 'linecolour' then  # line colouring spec.
            l_color := r;
         elif l = 'scene' then             # specify scene to be displayed 
            for ri in r do
               if not(member(ri,{ivar,op(vars),op(dvar)})) then
                  error "Invalid scene; must be list of vars: %1", opt;
               fi;
            od;
            if not(plot_3) then
               if nops(r) = 2 then
                  plotview := r;
               else
                  error "'scene' must specify two variables in DEplot: %1", opt
               fi;
            else
               if nops(r) = 3 then
                  plotview := r;
               else
                  error "'scene' must specify three variables in DEplot3d: %1",
                                 opt;
               fi;
            fi;
         elif l = 'numsteps' then
            if type(r,posint) then
               hl := evalf((lims[1,2]-lims[1,1])/r,_plotDigits);  # stepsize
            else 
               error "numsteps must be a positive integer: %1", opt;
            fi;
         elif l = 'stepsize' then           # distance between mesh values
            if type(r,realcons) and r > 0 then
               hl := r;
            else
               error "stepsize must be a nonzero real constant: %1", opt;
            fi;
         elif l = 'obsrange' then           # boundaries strictly observed
            if r = 'FALSE' or r = 'false' then stopb := false;
            elif not(r = 'TRUE' or r = 'true') then
               error "obsrange must be one of 'TRUE' or 'FALSE': %1", opt;
            fi;
         elif member(l,numfeatures) then    # remaining features (numeric)
            ftr_n := ftr_n,opt;
         elif member(l,plot2dftr) and not(plot_3) then # remaining ftrs (plot)
            ftr_p := ftr_p,opt;
         elif member(l,plot3dftr) and plot_3 then  # remaining ftrs (plot3d)
            ftr_p := ftr_p,opt;
         else
            if plot_3 then
               error "Option keyword (%1) "
                   "was not in the allowed set of options, consisting of:  "
                   "iterations, obsrange, scene, linecolour, stepsize, "
                   "a dependent variable range, a list of initial conditions "
                   "one of the allowed plot3d options: %2, "
                   "or one of the allowed dsolve/numeric options: %3",
                   l, plot3dftr, numfeatures;
            else
               error "Option keyword (%1) "
                   "was not in the allowed set of options, consisting of:  "
                   "iterations, arrows, dirgrid, obsrange, scene, "
                   "colour, linecolour, stepsize, "
                   "a dependent variable range, a list of initial conditions "
                   "or one of the allowed plot options: %2, "
                   "or one of the allowed dsolve/numeric options: %3",
                   l, plot2dftr, numfeatures;
            fi;
         fi;
      fi;
   od;
   if plot_3 and nlines = 0 then
      error "DEplot3d - inits required to produce a plot.";
   fi;
   if has(method_ftr,{'classical','gear','mgear'}) then
      ftr_n := ftr_n,subs(hval=hl,'stepsize=hval');
   fi;
   ftr_n := ftr_n,method_ftr;

   iter := iters;  arrw := arrowsize;  h := hl;  m := ml;  n := nl; randomarrow:=random;
   velocitycol:=velocitycolor;  velocitylen:=velocitylenght;  
   dvrange := deprange;  colorinfo := cinfo;  label_ftr := labels;
   toplot := plotview;  stopp := stopb;  ni := nlines; 
   line_color := l_color; features_p := ftr_p;  features_n := ftr_n;
   totalorder := t_ord
end:  # `DEtools/DEplot/AnalyseOptions`

#--------------------------------------------------------------------------
# Check the initial conditions specified for solution curves.
# NOTE:  Allowing lists of values for first order systems is only present
#        in bobcat (V.4) for backwards compatability.  It should be removed
#        for future versions.  (Allowing such lists can result in ambiguity
#        in plots if the user specifies the dependent variables as a set.)

`DEtools/DEplot/CheckInitial`:=proc(r,ni,IC,initial,ndvar,dvar,hord,tord)

   local k,init,i,nlines,ICl,initl,tinit;
 
   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   userinfo(6,'`DEtools/DEplot`',`checking initial conditions`);
   if tord = 0 then
      error "The 'number' option must be specified before initial conditions."
   fi;
   initl  := [];                      # the initial condition list
      
   if type(r,{'set','list'}) then
      initl := r;
      if type(initl,'set') then
         initl := [op(initl)];
      elif type(initl,'list') then
         for i from nops(initl)-1 by -1 to 1 do
            if member(initl[i],initl[i+1..-1],'k') then
	initl := subsop(k=NULL,initl);
            fi;
         od;
      fi;
      nlines := nops(initl);          # number of solution curves
      if nlines > 0 then
         ICl := array(1..nlines);     # initial t values for each line
         k := 1;
         for init in initl do         # condition on each var for each line
            if type(init,'list(equation)') then
               if nops(init) > tord then
                  error "Too many initial conditions: %1", init
               elif nops(init) < tord then
                  error "Too few initial conditions: %1", init
               fi;
            elif type(init,'list(realcons)') then
               if hord then
                  error "inits cannot be specified as lists of values for higher order DEs.";
               elif nops(init) <> tord+1 then
                  error "Incorrect number of initial conditions: %1", init
               fi
            fi;
            if type(init,'list(equation)') then
               if has(init,'diff') then
                  error "'diff' cannot appear in inits.";
               fi;
               ICl[k] := evalf(op([1,1,1],init),_plotDigits); 
               if nops({seq(op([i,1,1],init),i=1..ndvar)}) <> 1 then
                  error "Invalid initial conditions.";
               elif not type(evalf[_plotDigits](ICl[k]),'numeric') then
                  error "initial point in initial conditions must be numeric, got %1",ICl[k];
               fi;
            elif not type(init,'list(realcons)') then
               error "Invalid initial conditions - must be list of lists of conditions.";
            else  # build init conds for dsolve/numeric
               ICl[k] := evalf(op(1,init),_plotDigits);
               tinit := NULL;
               for i from 1 to ndvar do
                  tinit := tinit, subs(_y=dvar[i],_x=ICl[k],_v=op(i+1,init),
                                         _y(_x)=_v)
               od;
               initl := subs(init=[tinit],initl)
            fi;
            k := k+1;
         od;
      else
         error "Missing initial conditions in inits.";
      fi;
   else
      error "inits must be specified as a list of lists.";
   fi;
   ni := nlines; IC := ICl; initial := initl;
end:  # `DEtools/DEplot/CheckInitial`

#--------------------------------------------------------------------------
# If scene has not been specified by the user, decide which variables can
# be plotted.

`DEtools/DEplot/WhichPlot`:=proc(scene,p_3,high,ivar,imvar)

   local ndv,view;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   ndv := nops(imvar);
   if nops(scene) = 0 then                 # no user-specified scene
      if not(p_3) then                     # 2-D plot  
         if not(high) then
            if ndv = 1 then                # 1-system of 1st order
               view := [ivar,imvar[1](ivar)];
               userinfo(1,'`DEtools/DEplot`',`scene =`,view);
            else                           # two+ -system of 1st order
               if ndv > 2 then
                  error "More than two dependent variables - "
                      "please indicate the desired scene.";
               else
                  view := [imvar[1],imvar[2]];
                  userinfo(1,'`DEtools/DEplot`',`scene =`,view);
               fi;
            fi;
         else                              # only 2-D for high order plots
            view := [ivar,imvar[1](ivar)];
            userinfo(1,'`DEtools/DEplot`',`scene =`,view);
         fi;
      else                                 # 3-D plot
         if ndv = 3 then                   # three dependent variables
            view := [imvar[1],imvar[2],imvar[3]];
            userinfo(1,'`DEtools/DEplot3d`',`scene =`,view);
         elif ndv = 2 then                 # two dependent varaibles
            view := traperror([ivar,imvar[1](ivar),imvar[2](ivar)]);
            userinfo(1,'`DEtools/DEplot3d`',`scene =`,view);
         elif ndv > 3 then                 # too many dep variables to decide
            error "More than three dependent variables in DEplot3d - "
                "please indicate the desired scene.";
         else
            error "Only one depedent variable specified in DEplot3d - "
                "ensure vars has been specified properly.";
         fi;
      fi;
   else
      view := scene;
   fi;
   return view;
end:  # `DEtools/DEplot/WhichPlot`

#---------------------------------------------------------------------------
# This function maps ocurrences of dependent variable names to dependent
# variables.
# This is temporary, as the capability of allowing D(y)(x)=y/x as an
# input equation is deprecated.

`DEtools/DEplot/NameToDepvar`:=proc(DES,y,x)
local fake,inds,des,i;

	# Ok, first we need to map out any 'functions' that will be destroyed
	# by substitution of y=y(x)
	inds := select(has,indets(DES,'function'),y);
	inds := [seq(inds[i]=fake[i](x),i=1..nops(inds))];
	des := eval(DES,inds);
	# Now fix the system
	des := eval(des,y=y(x));
	# Now reverse the substitutions
	inds := map(proc(a) rhs(a)=lhs(a); end,inds);
	eval(des,inds);
end:  # `DEtools/DEplot/NameToDepvar`

#---------------------------------------------------------------------------
# Does a basic check on the DE's.  Most importantly, sets up the slope
# evaluation procedures for direction curves, provided test is true.

`DEtools/DEplot/CheckDE`:=proc(DES,nDES,ivar,ndvar,vars,dvar,f,w,plot_3,test)

   local i,j,call,calls,iden,fn,deriv,k,sym,tcall,tvar,v,des;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   userinfo(6,'`DEtools/DEplot`',`checking DES`);
   f := array(1..nDES);
   des := eval(DES);
   if not type(des,list(procedure)) and 
                 type(des,list({algebraic,equation})) then
      for i from 1 to nDES do            # Check each DE separately 
         if has(des[i], {'diff','D'}) then
            calls := indets(des[i], 'function');
            for j in dvar do
               if member(j,indets(des[i], 'name')) then
	       des := `DEtools/DEplot/NameToDepvar`(des,j,ivar);
 	       WARNING(StringTools:-FormatMessage("%1 is present as both a \
	       dependent variable and a name. Inconsistent specification of the dependent \
	       variable is deprecated, and it is assumed that the name is being used in place \
	       of the dependent variable.",j));
               fi;
            od;
            for call in calls do 
               if has(call,'D') then     # handle D by converting to diff
                  tcall := copy(call);
                  call := convert(tcall,'diff');
                  tcall := subs(tcall=call,des[i]);
                  des := subsop(i=tcall,des);
               fi;
               if op(0, call) = 'diff' then
                  if ivar <> op(2, call) then
                     error "Derivative must be wrt indept variable.";
                  fi;
                  iden := 0;             # number identifier for the dep var 
                  if not has(op(1,call),{op(vars)}) then
                     error "Must take derivative of dependent variable."
                  fi;
                  if test then
                     for k from 1 to 2 do
                        if w[k] = 1 then
                           if has(op(1,call),vars[w[2]-1]) then 
                              iden := 1;  break
                           fi
                        elif has(op(1,call),vars[w[k]-1]) then
                           iden := k;  break
                        fi
                     od;
                     if iden <> 0 then deriv := call fi
                  fi
               fi
            od;
            if test and iden <> 0 then
               fn[iden] := traperror(op(2, isolate(des[i], deriv)));
               fn[iden] := subs(seq(vars[j]=dvar[j],j=1..ndvar),fn[iden]);
               if fn[iden] = lasterror then
                  error "Unable to isolate the derivative for  %1", vars[iden]
               fi;
            fi;
         else
            error "Derivatives must be given explicitly."
         fi;
         if test and iden <> 0 then
            sym := indets(fn[iden],'name');       # sybolic parts of the DE
            for v in sym do 
               if not member (v,{ivar,op(dvar)}) then
                  if v <> evalf(v) then      # not a symbol known to Maple
                     fn[iden] := subs(v=evalf(v),fn[iden])
                  else
                     error "Symbolic name %1 could not evaluate to float.", v
                  fi
               fi
            od
         fi
      od;
      if not(plot_3) and test then        # set the variables used as args
         if w[1] = 1 then
            tvar := dvar[w[2]-1]
         elif w[2] = 1 then
            tvar := dvar[w[1]-1]
         else
            tvar := dvar[w[1]-1],dvar[w[2]-1]
         fi
      fi;
      f := `DEtools/DEplot/makefunc`(fn,ivar,[tvar]); 
   elif not(plot_3) and type(des,list(procedure)) and test then
      # No real way to check procedures, just hope for the best.
      f := des[1];
   elif not type(des,list(procedure)) then
      error "Invalid differential equation given.";
   fi;
	DES:=des;
end:  # `DEtools/DEplot/CheckDE`

#--------------------------------------------------------------------------
# Front end for creating integral curves.

`DEtools/DEplot/CreateLines`:=proc(ni,IC,lims,h,iter,dvrange,\
     DES,initial,vars,ivar,stopp,w,plot_3,ftrs_n)

   local DEset,lines,i,j,k,points,l_color,color_l,multi,t_s,thk;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   if nargs > 14 then
      if nargs = 15 then
         if type(args[15],specfunc(anything,'THICKNESS')) then
            thk := op(args[15]); l_color := NULL;
         else l_color := args[15]; thk := 3;
         fi;
      elif nargs = 16 then
         if type(args[15],specfunc(anything,'THICKNESS')) then
            thk := op(args[15]); l_color := args[16]
         else thk := op(args[16]); l_color := args[15]
         fi;
      else l_color := NULL; thk := 3;
      fi;
   else l_color := NULL; thk := 3;
   fi;

   DEset := convert(DES,set);              # dsolve/numeric will need set 
   lines := array (1..ni);
   `DEtools/DEplot/drawlines`(lines,ni,IC,lims,h,iter,dvrange,DEset,initial,\
       ftrs_n,vars,stopp,w,'t_s',ivar);
   if l_color = NULL then
# Modified the default color to blue by MBM and Moe Ebrahimi May/04
      color_l[1] := COLOR('RGB',0,0,0.9);  multi := false;
   else
      if has(l_color,{op(vars)}) then
         error "linecolour cannot be an expression in %1 or %2", op(1,vars), op(2,vars);
      fi;
      color_l := `DEtools/linecolour`(l_color,t_s,ni,ivar,'multi');
   fi;
   if not(plot_3) then
      if not(multi) then
         points := CURVES(seq([seq([seq(lines[j][k][i],i=1..2)],\
             k=1..nops(lines[j]))],j=1..ni),STYLE(LINE),THICKNESS(thk)),\
             color_l[1];
      else
         points := seq(CURVES(seq(
               [[seq(lines[j][k][i],i=1..2)],[seq(lines[j][k+1][i],i=1..2)]],\
             k=1..nops(lines[j])-1),color_l[j],STYLE(LINE),THICKNESS(thk)),\
             j=1..ni);
      fi;
   else
      if not(multi) then
         points:=seq(CURVES([seq([seq(lines[j][k][i],i=1..3)],\
             k=1..nops(lines[j]))],THICKNESS(thk)),j=1..ni),color_l[1];
      else
         points := seq(CURVES(seq(
               [[seq(lines[j][k][i],i=1..3)],[seq(lines[j][k+1][i],i=1..3)]],\
             k=1..nops(lines[j])-1),color_l[j],STYLE(LINE),THICKNESS(thk)),\
             j=1..ni);
      fi;
   fi;
   return [points];
end:  # `DEtools/DEplot/CreateLines`

#--------------------------------------------------------------------------
# drawlines generates the set of point for each of the lines specified by
# the set of initial conditions.

`DEtools/DEplot/drawlines`:=proc(lines,ni,IC,lims,h,iter,dvrange,
    DEset,intl,ftrs_n,vars,stopp,w,t_list,ivar)

   local dvmin,dvmax,pt,j,dv0,i,er,dvlist,pts,k,a,b,nsteps,t,features_n,
       srt_i,finish_i,srt,dir,ndir,f,F_val,F,initset,out,ndplot,initialset,
       errs;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   features_n := op(ftrs_n);
   a := lims[1,1]; b := lims[1,2];         # domain of integration
   ndplot := nops(w);
   dvmin := [seq(array(1..ni),i=1..ndplot)];
   dvmax :=  [seq(array(1..ni),i=1..ndplot)];
   pt := array (1..ndplot);                # point generated in integration
   nsteps := ceil((b-a)/(iter*h))+1;       # number of points to store
 
   for j from 1 to ni do                   # perform integration for each line
      dv0 := IC[j];                        # dv0 is the initial t value
      pts := 'pts';
      pts := array(1..nsteps,1..ndplot);   # set of output points
      if dv0 <= a then                     # interval to the right
         srt[1] := a;                      # integration starting point
         srt_i[1] := 1;                    # starting array index
         finish_i[1] := nsteps;            # finishing array index
         dir[1] := +1;                     # direction increment
         ndir := 1;                        # number of directions involved
      elif dv0 >= b then                   # interval to the left
         srt[1] := b;
         srt_i[1] := nsteps;
         finish_i[1] := 1;
         dir[1] := -1;
         ndir := 1;
      else                                 # t0 inside the interval
         srt[1] := a+h*round((dv0-a)/h);   # positive integration settings
         srt_i[1] := trunc((srt[1]-a)/(h*iter) + 1);
         finish_i[1] := nsteps;
         dir[1] := +1;
         srt[2] := srt[1]-h*iter;          # negative integration settings
         srt_i[2] := srt_i[1] - 1;
         finish_i[2] := 1;
         dir[2] := -1;
         ndir := 2; 
      fi;
      if type(DEset,set(procedure)) then
         initset:=convert(op(j,intl),set);
         initialset := array(1..nops(initset),
                             map(proc(x) op(2,x) end,op(j,intl)));
         F := dsolve(vars,'output'='listprocedure','type'='numeric',\
             'number'=nops(initset),'procedure'=op(DEset),'start'=dv0,\
             'initial'=initialset,features_n);
         for k from 1 to ndplot do
            if w[k] <> 1 then 
               F_val[w[k]-1] := subs(F,`dsolve/numeric_F`[w[k]-1](ivar))
            fi
         od;   
      else
         initset := convert(op(j,intl),set);
         # Add range argument for SC methods: rkf45,rosenbrock
         if has([features_n],{'method'='rkf45','method'='rosenbrock'}) then
            features_n := features_n,'range'=a..b;
         fi;
			_Env_dsolve_nowarn := true;
         F := dsolve(DEset union initset, convert(vars,set), \
             'output'='listprocedure', 'type'='numeric', features_n);
			_Env_dsolve_nowarn := false;
         for k from 1 to ndplot do
            if w[k] <> 1 then F_val[w[k]-1] := subs(F,op(w[k]-1,vars)); fi;
         od;   
      fi;

      errs := {};
      for f from 1 to ndir do                 # do pos then neg integration
         out := false;
         t := srt[f];
         for i from srt_i[f] by dir[f] to finish_i[f] do 
            if not(out and stopp) then
               for k from 1 to ndplot do      # integrate on each variable
                  if w[k] = 1 then            # no integrating to do
                     pts[i,k] := t;
                  else
                     try
                        pt[k] := F_val[w[k]-1](t); 
                                              # decide when to store results
                        if w[k] = 1 or not(dvrange[w[k]-1]) then 
                           pts[i,k] := pt[k];
                        else
                           if (pt[k]>lims[w[k],2]) or (pt[k]<lims[w[k],1]) then
                              pts[i,k] := pt[k];
                              out := true;
                           else
                              pts[i,k] := pt[k];
                              if out then out := false; fi;
                           fi;
                        fi; 
                     catch:
                        errs := errs union {StringTools:-FormatMessage(
                                 lastexception[2..-1])};
                        pts[i,k] := undefined;
                     end try;
                  fi;
               od;
            else
               for k from 1 to ndplot do      # went out of bounds
                  pts[i,k] := undefined;
               od;
            fi;
            t := t + dir[f]*(iter*h);         # new output point
         od;
      od;
      if errs<>{} then
         printf("Warning, plot may be incomplete, the following errors(s) were issued:\n");
         for i in errs do
            printf("   %s\n",i);
         od;
      fi;
      userinfo(10,'`DEtools/DEplot`',`Calculating graph boundaries`);
      for k from 1 to ndplot do
         if not w[k] = 1 and not dvrange[w[k]-1] then 
            dvlist[k] := op(subs(undefined=NULL,[seq(pts[i,k],i=1..nsteps)]));
            dvmin[k][j] := min(dvlist[k]);
            dvmax[k][j] := max(dvlist[k]);
            lims[w[k],1] := min(seq(dvmin[k][i],i=1..j));
            lims[w[k],2] := max(seq(dvmax[k][i],i=1..j));
         fi;
      od;

      userinfo(10,'`DEtools/DEplot`',`Creating line`,j);
      lines[j] := [seq([seq(pts[i,k],k=1..ndplot)],i=1..nsteps)];
   od;
   t_list := [seq(a+j*iter*h,j=0..nsteps-2)];
end:  # `DEtools/DEplot/drawlines`

#----------------------------------------------------------------------------
# Front end for creating direction fields.

`DEtools/DEplot/CreateArrows`:=proc(f,lims,m,n,arrw,ndvar,w,\
    test1,test2,velocitylen,randomarrow)

   local colorinfo,points;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   colorinfo := NULL;
   if nargs = 12then
      colorinfo := args[12];
   fi;
   if test1 or test2 then
      points := `DEtools/DEplot/direction`(eval(f),lims[w[1],1],\
          lims[w[1],2],lims[w[2],1],lims[w[2],2],m,n,arrw,ndvar,\
          w,velocitylen,randomarrow,colorinfo);
   else
      points := NULL;
   fi;
   return [points]:
end:  # `DEtools/DEplot/CreateArrows`

#-----------------------------------------------------------------------------
# This function draws arrows for a direction field plot.

`DEtools/DEplot/direction` := proc(f,a,b,c,d,m,n,arrow,ndvar,w,velocitylen,randomarrow)

   local xa,ya,i,j,lm,ln,curves,Coords,colorinfo,size;
   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;   
   colorinfo := NULL;
   if nargs = 13 then   colorinfo := args[13];   fi;
   if randomarrow=0 then  lm := m - 1;  ln := n - 1; else lm:=randomarrow-1; ln:=randomarrow-1; fi;
   if arrow = 'LARGE' then            # thick arrows - need 7 vertices
      size:=3;
   if randomarrow=0 then   xa := array(0..lm,0..7*ln+6);   ya := array(0..lm,0..7*ln+6);
                    else   xa := array(0..lm,0..6);        ya := array(0..lm,0..6);   fi;
   `DEtools/DEplot/arrows`(f,xa,ya,a,b,c,d,lm,ln,7,ndvar,velocitylen,size,randomarrow);
   if randomarrow=0 then
      if xa[1,1] = 'xa[1,1]' then
         curves := NULL;
      else
         curves:= POLYGONS(seq(seq([[xa[i,7*j],ya[i,7*j]],[xa[i,7*j+1],\
             ya[i,7*j+1]],[xa[i,7*j+2],ya[i,7*j+2]],[xa[i,7*j+3],\
             ya[i,7*j+3]],[xa[i,7*j+4],ya[i,7*j+4]],[xa[i,7*j+5],\
             ya[i,7*j+5]],[xa[i,7*j+6],ya[i,7*j+6]],[xa[i,7*j],\
             ya[i,7*j]]],i=0..lm),j=0..ln),colorinfo,STYLE('PATCHNOGRID'));
      fi;
   else
         curves:= POLYGONS(seq([[xa[i,0],ya[i,0]],[xa[i,1],
             ya[i,1]],[xa[i,2],ya[i,2]],[xa[i,3],
             ya[i,3]],[xa[i,4],ya[i,4]],[xa[i,5],
             ya[i,5]],[xa[i,6],ya[i,6]],[xa[i,0],
             ya[i,0]]],i=0..lm),colorinfo,STYLE('PATCHNOGRID'));
   fi;
   elif arrow = 'MEDIUM' then           # medium arrows - need 7 vertices
     size:=2;
     if randomarrow=0 then   xa := array(0..lm,0..7*ln+6);   ya := array(0..lm,0..7*ln+6);
                      else   xa := array(0..lm,0..6);        ya := array(0..lm,0..6);   fi;
    `DEtools/DEplot/arrows`(f,xa,ya,a,b,c,d,lm,ln,7,ndvar,velocitylen,size,randomarrow);
     if randomarrow=0 then
        if xa[1,1] = 'xa[1,1]' then
           curves := NULL;
        else
           curves:= POLYGONS(seq(seq([[xa[i,7*j],ya[i,7*j]],[xa[i,7*j+1],\
               ya[i,7*j+1]],[xa[i,7*j+2],ya[i,7*j+2]],[xa[i,7*j+3],\
               ya[i,7*j+3]],[xa[i,7*j+4],ya[i,7*j+4]],[xa[i,7*j+5],\
               ya[i,7*j+5]],[xa[i,7*j+6],ya[i,7*j+6]],[xa[i,7*j],\
               ya[i,7*j]]],i=0..lm),j=0..ln),colorinfo,STYLE('PATCHNOGRID'));
        fi;
     else
           curves:= POLYGONS(seq([[xa[i,0],ya[i,0]],[xa[i,1],
               ya[i,1]],[xa[i,2],ya[i,2]],[xa[i,3],
               ya[i,3]],[xa[i,4],ya[i,4]],[xa[i,5],
               ya[i,5]],[xa[i,6],ya[i,6]],[xa[i,0],
               ya[i,0]]],i=0..lm),colorinfo,STYLE('PATCHNOGRID'));
     fi;
   elif arrow = 'FISH' then           #  need 19 vertices           
     size:=4;
     if randomarrow=0 then   xa := hfarray(0..lm,0..19*ln+18);   ya := hfarray(0..lm,0..19*ln+18);
                      else   xa := hfarray(0..lm,0..18);         ya := hfarray(0..lm,0..18);   fi;
     `DEtools/DEplot/arrows`(f,xa,ya,a,b,c,d,lm,ln,19,ndvar,velocitylen,size,randomarrow);
     if randomarrow=0 then
        if xa[1,1] = 'xa[1,1]' then
           curves := NULL;
        else
	    curves:=CURVES(seq(seq([
	        [xa[i,19*j],ya[i,19*j]], [xa[i,19*j+1],ya[i,19*j+1]],[xa[i,19*j+2],ya[i,19*j+2]],[xa[i,19*j+3],ya[i,19*j+3]],
	        [xa[i,19*j+4],ya[i,19*j+4]],[xa[i,19*j+5], ya[i,19*j+5]],[xa[i,19*j+6],ya[i,19*j+6]],[xa[i,19*j+7],ya[i,19*j+7]],
	        [xa[i,19*j+8],ya[i,19*j+8]],[xa[i,19*j+9],ya[i,19*j+9]],[xa[i,19*j+18],ya[i,19*j+18]],[xa[i,19*j+17],ya[i,19*j+17]],[xa[i,19*j+16],ya[i,19*j+16]],
	        [xa[i,19*j+15],ya[i,19*j+15]],[xa[i,19*j+14],ya[i,19*j+14]],[xa[i,19*j+13],ya[i,19*j+13]],[xa[i,19*j+12],ya[i,19*j+12]],
	        [xa[i,19*j+11],ya[i,19*j+11]],[xa[i,19*j+10],ya[i,19*j+10]],[xa[i,19*j],ya[i,19*j]]],i=0..lm),j=0..ln),colorinfo,'THICKNESS'(1));
        fi;
      else
            curves:=CURVES(seq([
	        [xa[i,0],ya[i,0]],[xa[i,1],ya[i,1]],[xa[i,2],ya[i,2]],[xa[i,3],ya[i,3]],[xa[i,4],ya[i,4]],[xa[i,5],ya[i,5]],
	        [xa[i,6],ya[i,6]],[xa[i,7],ya[i,7]],[xa[i,8],ya[i,8]],[xa[i,9],ya[i,9]],[xa[i,18],ya[i,18]],[xa[i,17],ya[i,17]],
	        [xa[i,16],ya[i,16]],[xa[i,15],ya[i,15]],[xa[i,14],ya[i,14]],[xa[i,13],ya[i,13]],[xa[i,12],ya[i,12]],[xa[i,11],ya[i,11]],
	        [xa[i,10],ya[i,10]],[xa[i,0],ya[i,0]]],i=0..randomarrow-1),colorinfo,'THICKNESS'(1));
      fi;
          
   elif arrow = 'CURVE' then           #  need 10 vertices           
      size:=5;
      if randomarrow=0 then   xa := hfarray(0..lm,0..10*ln+9);   ya := hfarray(0..lm,0..10*ln+9);
                       else   xa := hfarray(0..lm,0..9);         ya := hfarray(0..lm,0..9);   fi;
      `DEtools/DEplot/arrows`(f,xa,ya,a,b,c,d,lm,ln,10,ndvar,velocitylen,size,randomarrow);
      if randomarrow=0 then
        if xa[1,1] = 'xa[1,1]' then
           curves := NULL;
        else
	    curves:=CURVES(seq(seq([
	   [xa[i,10*j],ya[i,10*j]],[xa[i,10*j+1],ya[i,10*j+1]],
	   [xa[i,10*j+2],ya[i,10*j+2]],[xa[i,10*j+3],ya[i,10*j+3]],
           [xa[i,10*j+4],ya[i,10*j+4]],[xa[i,10*j+5], ya[i,10*j+5]],
	   [xa[i,10*j+6],ya[i,10*j+6]],[xa[i,10*j+7],ya[i,10*j+7]]
	   ],i=0..lm),j=0..ln),colorinfo,'THICKNESS'(1)),
                   CURVES(seq(seq([
	   [xa[i,10*j+7],ya[i,10*j+7]],[xa[i,10*j+8],ya[i,10*j+8]],
	   [xa[i,10*j+9],ya[i,10*j+9]]],i=0..lm),j=0..ln),colorinfo,'THICKNESS'(2));
         fi;
      else
	    curves:=CURVES(seq([
	   [xa[i,0],ya[i,0]],[xa[i,1],ya[i,1]],
	   [xa[i,2],ya[i,2]],[xa[i,3],ya[i,3]],
	   [xa[i,4],ya[i,4]],[xa[i,5],ya[i,5]],
	   [xa[i,6],ya[i,6]],[xa[i,7],ya[i,7]]
	    ],i=0..lm),colorinfo,'THICKNESS'(1)),
                    CURVES(seq([
	   [xa[i,7],ya[i,7]],[xa[i,8],ya[i,8]],
	   [xa[i,9],ya[i,9]]],i=0..lm),colorinfo,'THICKNESS'(2));
      fi;         
      else                                # thin arrows - four vertices 
        size:=1;
        if randomarrow=0 then   xa := hfarray(0..lm,0..4*ln+3);  ya := hfarray(0..lm,0..4*ln+3);
                         else   xa := hfarray(0..lm,0..3);       ya := hfarray(0..lm,0..3);   fi;
        `DEtools/DEplot/arrows`(f,xa,ya,a,b,c,d,lm,ln,4,ndvar,velocitylen,size,randomarrow);
         if randomarrow=0 then
             if xa[1,1] = 'xa[1,1]' then
                 curves := NULL;
             else
               curves:= CURVES(seq(seq([[xa[i,4*j],ya[i,4*j]],[xa[i,4*j+1],ya[i,4*j+1]],[xa[i,4*j+2],ya[i,4*j+2]], 
                        [xa[i,4*j+1],ya[i,4*j+1]],[xa[i,4*j+3],ya[i,4*j+3]]],i=0..lm),j=0..ln),colorinfo,'THICKNESS'(2));
             fi;
         else
               curves:= CURVES(seq([[xa[i,0],ya[i,0]],[xa[i,1],ya[i,1]], [xa[i,2],ya[i,2]],
                        [xa[i,1],ya[i,1]], [xa[i,3],ya[i,3]]],i=0..lm), colorinfo,'THICKNESS'(2));
         fi;
    fi;
    return curves;
end:  # `DEtools/DEplot/direction`

#---------------------------------------------------------------------------
# arrows generates the set of arrow point for direction.

`DEtools/DEplot/arrows`:=proc(f,xa,ya,xmin,xmax,ymin,ymax,m,n,vertices,ndvar,velocitylen,size,randomarrow)

   local hfs,er,Xmin,Xmax,Ymin,Ymax,ran1,ran2,i;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;
   er:=NULL;  
   hfs := array([xmin,xmax,ymin,ymax,randomarrow,size,vertices]); 
   if _plotDigits <= evalhf(Digits) then
         try
            er:=evalhf(`DEtools/DEplot/arrowshf`(f,var(xa),var(ya),var(hfs),m,n,ndvar,velocitylen,data1,data2));
	    return;
            catch: 
         end try;
   fi;  
   if er=NULL then
     print("hf computation failed");
     userinfo(15,'`DEtools/DEplot`',`in arrows had to do sfp because of`,er); 
     try
       er := `DEtools/DEplot/arrowsf`(f,xa,ya,hfs,m,n,ndvar,velocitylen,data1,data2);
       return;
       catch: userinfo(15,'`DEtools/DEplot`',`in arrows had to stop because of`,er);
     end try;  
     fi;
end:  # `DEtools/DEplot/arrows`

#---------------------------------------------------------------------------
# arrowsf computes the locations of the vertices of each arrow through DrawIt.
#
`DEtools/DEplot/arrowsf` := proc(f,xa,ya,hfs,m,n,ndvar,velocitylen,data1,data2)
   local i,j,k,xinc,yinc,l,scale,xlen,ylen,xs,ys,hfk,xmin,xmax,ymin,ymax,MAX,
         pt, rs,maxim,info,tempt,fisht,Xmin,Ymin,Xmax,Ymax,ran1,ran2,randomarrow,size,vertices;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;
   xmin := hfs[1]; xmax := hfs[2]; ymin := hfs[3]; ymax := hfs[4]; randomarrow:=hfs[5]; size:=hfs[6]; vertices:=hfs[7];
   MAX:=0;
   pt := array(1..3);  rs := array(1..3); 
   info:=array(1..6);  tempt:=array(1..2);
   hfk := array(1..9);  fisht:=array(1..3,1..11);
   l := 1/max(m,n); 
   xs := xmax-xmin; ys := ymax-ymin;
   MAX:=0;
  if randomarrow=0 then scale := .5*l*xs*ys; elif (randomarrow>0 and (size=4 or size=5)) then scale:=(randomarrow/20)*l*xs*ys;  else scale:=(randomarrow/35)*l*xs*ys;fi;
   xlen := xs^2; ylen := ys^2;
   if randomarrow=0 then maxim:=min(xinc,yinc); else maxim:=min((xmax-xmin)/10,(ymax-ymin)/10); fi;
   xinc := xs/m; yinc := ys/n;
   hfk[1] := scale; hfk[2] := xs; hfk[3] := ys; hfk[4] := xlen;
   hfk[5] := ylen; hfk[6] := vertices;  hfk[9]:=randomarrow;
   info[1]:=ndvar;   info[2]:=velocitylen;   info[3]:=maxim;   info[5]:=xinc;   info[6]:=yinc; 
   #data for creating the Fish
   fisht[1,1]:=0.0; fisht[1,2]:=0.1; fisht[1,3]:=0.2;fisht[1,4]:=0.3; fisht[1,5]:=0.4; fisht[1,6]:=0.6; fisht[1,7]:=0.8; fisht[1,8]:=0.9; fisht[1,9]:=0.95;  fisht[1,10]:=0.99;         fisht[1,11]:=1;
   fisht[2,1]:=0.0; fisht[2,2]:=0.2; fisht[2,3]:=0.4; fisht[2,4]:=0.6; fisht[2,5]:=0.8; fisht[2,6]:=1.2; fisht[2,7]:=1.6; fisht[2,8]:=1.8; fisht[2,9]:=1.9;  fisht[2,10]:=1.98;          fisht[2,11]:=2;
   fisht[3,1]:=0.0; fisht[3,2]:=0.4; fisht[3,3]:=0.6; fisht[3,4]:=0.8; fisht[3,5]:=1.0; fisht[3,6]:=1.2; fisht[3,7]:=1.4; fisht[3,8]:=1.6; fisht[3,9]:=1.8;  fisht[3,10]:=2.0;            fisht[3,11]:=0; 

#Find the MAX length of all the vectors added for the velocity option
  if ndvar <> 1 then      
    if randomarrow=0 then             
         pt[1] := xmin;                      
         for i from 0 to m do
            pt[2] := ymin;
            for j from 0 to n do
              f(2,pt[1],pt,rs);
               hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]); 
               if Im(hfk[7]) <> 0 or Im(hfk[8]) <> 0 then
                 MAX:=max(MAX,0);
               else                        
                  MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));
               fi;
               pt[2] := pt[2]+yinc;
            od;
            pt[1] := pt[1]+xinc;
         od;
    else
         pt[1] := data1[0];       
         pt[2] := data2[0];               
         for i from 0 to randomarrow do
               f(2,pt[1],pt,rs);
               hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
               if Im(hfk[7]) <> 0 or Im(hfk[8]) <> 0   then
                  MAX:=max(MAX,0);
               else                         
                 MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));
               fi;
               pt[2] := data2[i];
               pt[1] := data1[i];
        od;    
     fi;    
  else   
    if randomarrow=0 then             
       pt[2] := xmin;                      
       hfk[7] := 1;  
       for i from 0 to m do
          pt[1] := ymin;
          for j from 0 to n do
            f(2  ,pt[2],pt,rs);
             hfk[8] := rs[1];             
             if Im(hfk[8]) <> 0 then
                MAX:=max(MAX,1);
             else
                MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));
             fi;
             pt[1] := pt[1]+yinc;
          od;
          pt[2] := pt[2]+xinc;
       od;
    else
         pt[1] := data1[0];       
         pt[2] := data2[0]; 
         hfk[7] := 1;              
         for i from 0 to randomarrow do
               f(2,pt[1],pt,rs);
               hfk[8] := evalf(rs[1]);  
               if Im(hfk[8]) <> 0   then
                  MAX:=max(MAX,1);
               else                         
                 MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));
               fi;
               pt[2] := data2[i];
               pt[1] := data1[i];
        od;    
     fi;                                

   fi;   
   info[4]:=MAX;         
 #computes the locations of the vertices
 if ndvar <> 1 then   
      if randomarrow=0 then        
         pt[1] := xmin;                      
         for i from 0 to m do
            pt[2] := ymin;
            for j from 0 to n do
               f(2,pt[1],pt,rs);
               hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
               if hfk[7]=0 and hfk[8]=0 then
                  for k from 0 to (vertices-1) do
                     xa[i,vertices*j+k]:= 0;
                     ya[i,vertices*j+k]:= 0;
                  od;
               elif Im(hfk[7]) <> 0 or Im(hfk[8]) <> 0 #or not(type(rs[3],indexed)) 
               then
                  for k from 0 to (vertices-1) do
                     xa[i,vertices*j+k] := undefined;
                     ya[i,vertices*j+k] := undefined;
                  od;
               else                          # got a R non-zero slope - make arrow
                  `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,pt,i,j,info,size,fisht);
               fi;
               pt[2] := pt[2]+yinc;
            od;
            pt[1] := pt[1]+xinc;
         od;
      else
          pt[1] := data1[0];       
          pt[2] := data2[0];               
          for i from 0 to randomarrow-1 do
                f(2,pt[1],pt,rs);
                hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
                if hfk[7]=0 and hfk[8]=0 then
                   for k from 0 to (vertices-1) do
                      xa[i,k]:= 0;
                      ya[i,k]:= 0;
                   od;
                elif Im(hfk[7]) <> 0 or Im(hfk[8]) <> 0  
                then
                   for k from 0 to (vertices-1) do
                      xa[i,k] := undefined;
                      ya[i,k] := undefined;
                   od;
                else                          # got a R non-zero slope - make arrow
                   `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,pt,i,i,info,size,fisht);
                fi;
                pt[2] := data2[i+1];
                pt[1] := data1[i+1];
          od;
     fi;
   else                                         # ndvar = 1
      if randomarrow=0 then        
      pt[2] := xmin;                        # pt[1] is y, pt[2] is ivar
      hfk[7] := 1;  
      for i from 0 to m do
         pt[1] := ymin;
         for j from 0 to n do
            f(2,pt[2],pt,rs);
            hfk[8] := rs[1];              # slope of function
            if (Im(hfk[8]) <> 0)  or not(type(rs[3],indexed)) 
            then
               for k from 0 to (vertices-1) do
                  xa[i,vertices*j+k] := undefined;
                  ya[i,vertices*j+k] := undefined;
               od;
            else
           tempt[2]:=pt[1];
           tempt[1]:=pt[2];
               `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,tempt,i,j,info,size,fisht);
            fi;
            pt[1] := pt[1]+yinc;
         od;
         pt[2] := pt[2]+xinc;
      od;
      else  
          pt[2] := data2[0];        
          pt[1] := data1[0];     
          hfk[7] := 1;               
          for i from 0 to randomarrow-1 do
                hfk[8] := f(2,pt[2],pt,rs);  # slopes
                if (Im(hfk[8]) <> 0)  or not(type(rs[3],indexed)) 
                then
                   for k from 0 to (vertices-1) do
                      xa[i,k] := undefined;
                      ya[i,k] := undefined;
                   od;
                else
                   tempt[2]:=pt[1];
                   tempt[1]:=pt[2];
                   `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,tempt,i,j,info,size,fisht)
                fi;
                pt[1] := data2[i+1];
                pt[2] := data1[i+1];
          od;
     fi;

   fi;  
end:  # `DEtools/DEplot/arrowsf`
#---------------------------------------------------------------------------
# arrowshf computes the locations of the vertices of each arrow through DrawIt
# using evalhf.
# Note that this had to be broken off from arrowsf because of the presence
# of an Imaginary value test - this does not work under evalhf
#
`DEtools/DEplot/arrowshf` := proc(f,xa,ya,hfs,m,n,ndvar,velocitylen,data1,data2)

   local i,j,k,xinc,yinc,l,scale,xlen,ylen,xs,ys,hfk,xmin,xmax,ymin,ymax,MAX,
         pt,rs,maxim,info,tempt,fisht,randomarrow,size,vertices;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;
   xmin := hfs[1]; xmax := hfs[2]; ymin := hfs[3]; ymax := hfs[4]; randomarrow:=hfs[5]; size:=hfs[6]; vertices:=hfs[7];
   MAX:=0;
   pt := array(1..2);  rs := array(1..2);
   info:=array(1..6);  tempt:=array(1..2);
   hfk := array(1..9);  fisht:=array(1..3,1..11);
   l := 1/max(m,n); 
   xs := xmax-xmin; ys := ymax-ymin;
   if randomarrow=0 then scale := .5*l*xs*ys; elif (randomarrow>0 and (size=4 or size=5)) then scale:=(randomarrow/20)*l*xs*ys;  else scale:=(randomarrow/35)*l*xs*ys;fi;
   xlen := xs^2; ylen := ys^2;
   xinc := xs/m; yinc := ys/n;
   if randomarrow=0 then maxim:=min(xinc,yinc); else maxim:=min(xmax-xmin,ymax-ymin)/10; fi;
   hfk[1] := scale; hfk[2] := xs; hfk[3] := ys; hfk[4] := xlen;
   hfk[5] := ylen; hfk[6] := vertices; hfk[9]:=randomarrow;
   info[1]:=ndvar;   info[2]:=velocitylen;   info[3]:=maxim;   info[5]:=xinc;   info[6]:=yinc; 
   #data for creating the Fish
   fisht[1,1]:=0.0; fisht[1,2]:=0.1; fisht[1,3]:=0.2; fisht[1,4]:=0.3; fisht[1,5]:=0.4; fisht[1,6]:=0.6; fisht[1,7]:=0.8; fisht[1,8]:=0.9;  fisht[1,9]:=0.95; fisht[1,10]:=0.99; fisht[1,11]:=1;
   fisht[2,1]:=0.0; fisht[2,2]:=0.2; fisht[2,3]:=0.4; fisht[2,4]:=0.6; fisht[2,5]:=0.8; fisht[2,6]:=1.2; fisht[2,7]:=1.6; fisht[2,8]:=1.8;  fisht[2,9]:=1.9;  fisht[2,10]:=1.98; fisht[2,11]:=2;
   fisht[3,1]:=0.0; fisht[3,2]:=0.4; fisht[3,3]:=0.6; fisht[3,4]:=0.8; fisht[3,5]:=1.0; fisht[3,6]:=1.2; fisht[3,7]:=1.4; fisht[3,8]:=1.6;  fisht[3,9]:=1.8;  fisht[3,10]:=2.0;  fisht[3,11]:=0; 

#find MAX
    if ndvar <> 1 then 
          if randomarrow=0 then              
            pt[1] := xmin;                      
            for i from 0 to m do
               pt[2] := ymin;
               for j from 0 to n do
                  f(2,pt[1],pt,rs);
                  hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);             
                  MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));         
                  pt[2] := pt[2]+yinc;
               od;
               pt[1] := pt[1]+xinc;
            od;
           else
               pt[1] := data1[0];       
               pt[2] := data2[0];               
               for i from 0 to randomarrow do
                  f(2,pt[1],pt,rs);
                  hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
                  MAX:=max(MAX,(((hfk[7])^2+(hfk[8])^2)^(1/2)));
                  pt[2] := data2[i];
                  pt[1] := data1[i];
               od;    
     fi;    
             
    else                               
            pt[2] := xmin;                      
            hfk[7] := 1;  
      for i from 0 to m do
         pt[1] := ymin;
         for j from 0 to n do
            f(2,pt[2],pt,rs);
            hfk[8] := rs[1];                         
               MAX:=max(MAX,hfk[8]);        
            pt[1] := pt[1]+yinc;
         od;
         pt[2] := pt[2]+xinc;
      od;
   fi;   
info[4]:=MAX;
#computes the locations of the vertices.
 if ndvar <> 1 then   
      if randomarrow=0 then        
         pt[1] := xmin;                      
         for i from 0 to m do
            pt[2] := ymin;
            for j from 0 to n do
               f(2,pt[1],pt,rs);
               hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
               if hfk[7]=0 and hfk[8]=0 then
                  for k from 0 to (vertices-1) do
                     xa[i,vertices*j+k]:= 0;
                     ya[i,vertices*j+k]:= 0;
                  od;
               elif Im(hfk[7]) <> 0 or Im(hfk[8]) <> 0 #or not(type(rs[3],indexed)) 
               then
                  for k from 0 to (vertices-1) do
                     xa[i,vertices*j+k] := undefined;
                     ya[i,vertices*j+k] := undefined;
                  od;
               else                          # got a R non-zero slope - make arrow
                  `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,pt,i,j,info,size,fisht);
               fi;
               pt[2] := pt[2]+yinc;
            od;
            pt[1] := pt[1]+xinc;
         od;
      else
          pt[1] := data1[0];       
          pt[2] := data2[0];               
          for i from 0 to randomarrow-1 do
                f(2,pt[1],pt,rs);
                hfk[7] := evalf(rs[1]);  hfk[8] := evalf(rs[2]);  # slopes
                if hfk[7]=0 and hfk[8]=0 then
                   for k from 0 to (vertices-1) do
                      xa[i,vertices*i+k]:= 0;
                      ya[i,vertices*i+k]:= 0;
                   od;
                else                          # got a R non-zero slope - make arrow
                   `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,pt,i,i,info,size,fisht);
                fi;
                pt[2] := data2[i+1];
                pt[1] := data1[i+1];
          od;
     fi;
   else                                         # ndvar = 1
     pt[2] := xmin;                        # pt[1] is y, pt[2] is ivar
      hfk[7] := 1;  
      for i from 0 to m do
         pt[1] := ymin;
         for j from 0 to n do
            f(2,pt[2],pt,rs);
            hfk[8] := rs[1];              # slope of function
            if (Im(hfk[8]) <> 0)  or not(type(rs[3],indexed)) 
            then
               for k from 0 to (vertices-1) do
                  xa[i,vertices*j+k] := undefined;
                  ya[i,vertices*j+k] := undefined;
               od;
            else
           tempt[1]:=pt[2];
           tempt[2]:=pt[1];
               `DEtools/DEplot/DrawIt`(f,xa,ya,hfk,tempt,i,j,info,size,fisht);
            fi;
            pt[1] := pt[1]+yinc;
         od;
         pt[2] := pt[2]+xinc;
      od;
   fi;   
end:  # `DEtools/DEplot/arrowshf`

#----------------------------------------------------------------------------

# DrawIt generates the set of vertices for each arrow.
#
`DEtools/DEplot/DrawIt` := proc(f,xa,ya,hfk,pt,i,j,info,size,fisht)

   local x,y,x1,x2,x3,Dx,scale,xs,ys,xlen,ylen,vertices,velocitylen,maxim,dx,dy,dx2,dx3,dy2,dy3,SCALE,
         vx,vy,k,t2,t3,t4,t5,t6,plt,m,MAX,randomarrow;
   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;
   x:=pt[1];   y:=pt[2];
   x1 := array(1..2);  x2 := array(1..2); 
   x3 := array(1..2);  Dx:=array(1..6);
   scale := hfk[1]; xs := hfk[2]; ys := hfk[3]; xlen := hfk[4]; 
   ylen := hfk[5]; vertices := hfk[6]; randomarrow:=hfk[9];
   velocitylen:=info[2]; maxim:=info[3];  MAX:=info[4];
   if  velocitylen=false then 
       SCALE:=0.9;
   else
       SCALE:=((((hfk[7])^2+(hfk[8])^2)^(1/2))/((1.05)*MAX))^(1/3); #using cube root scaling  
   fi;
   dx := scale*SCALE*hfk[7]*(ylen*hfk[7]^2+xlen*hfk[8]^2)^(-1/2);
   dy := scale*SCALE*hfk[8]*(ylen*hfk[7]^2+xlen*hfk[8]^2)^(-1/2);
   vx := dx/xs; vy := dy/ys; k:= vertices*j;
   t2 := 0.70710678118654752440; t3 := 0.23570226039551584147;
   t4 := 0.63301270189221932338; t5 := t2*0.7; t6 := t3*0.7;
   if size=1 then           # arrow_style is LINE , SMALL  
      if randomarrow=0 then
         xa[i,k] := (x-dx);                         ya[i,k] :=( y-dy);
         xa[i,k+1] := (x+dx);                       ya[i,k+1] := (y+dy);
         xa[i,k+2]:= x+dx + (-t4*vx+.25*vy)*xs;     ya[i,k+2]:= y+dy - (t4*vy+.25*vx)*ys;
         xa[i,k+3]:= x+dx - (t4*vx+.25*vy)*xs;      ya[i,k+3]:= y+dy + (-t4*vy+.25*vx)*ys;
      else
         xa[i,0] := (x-dx);                         ya[i,0] :=( y-dy);
         xa[i,1] := (x+dx);                         ya[i,1] := (y+dy);
         xa[i,2]:= x+dx + (-t4*vx+.25*vy)*xs;       ya[i,2]:= y+dy - (t4*vy+.25*vx)*ys;
         xa[i,3]:= x+dx - (t4*vx+.25*vy)*xs;        ya[i,3]:= y+dy + (-t4*vy+.25*vx)*ys;
      fi;
   elif size=2 then          # arrow_style is MEDIUM 
      if randomarrow=0 then
         xa[i,k] := x+dx;                           ya[i,k] := y+dy;
         xa[i,k+1] := x+dx - t5*(vx+vy)*xs;         ya[i,k+1] := y+dy + t5*(vx-vy)*ys;
         xa[i,k+2] := x+dx - (t5*vx+t6*vy)*xs;      ya[i,k+2] := y+dy + (t6*vx-t5*vy)*ys;
         xa[i,k+3] := x-dx - t6*vy*xs;              ya[i,k+3] := y-dy + t6*vx*ys;
         xa[i,k+4] := x-dx + t6*vy*xs;              ya[i,k+4] := y-dy - t6*vx*ys;
         xa[i,k+5] := x+dx + (-t5*vx+t6*vy)*xs;     ya[i,k+5] := y+dy - (t5*vy+t6*vx)*ys;
         xa[i,k+6] := x+dx + t5*(vy-vx)*xs;         ya[i,k+6] := y+dy - t5*(vx+vy)*ys;
      else
         xa[i,0] := x+dx;                           ya[i,0] := y+dy;
         xa[i,1] := x+dx - t5*(vx+vy)*xs;           ya[i,1] := y+dy + t5*(vx-vy)*ys;
         xa[i,2] := x+dx - (t5*vx+t6*vy)*xs;        ya[i,2] := y+dy + (t6*vx-t5*vy)*ys;
         xa[i,3] := x-dx - t6*vy*xs;                ya[i,3] := y-dy + t6*vx*ys;
         xa[i,4] := x-dx + t6*vy*xs;                ya[i,4] := y-dy - t6*vx*ys;
         xa[i,5] := x+dx + (-t5*vx+t6*vy)*xs;       ya[i,5] := y+dy - (t5*vy+t6*vx)*ys;
         xa[i,6] := x+dx + t5*(vy-vx)*xs;           ya[i,6] := y+dy - t5*(vx+vy)*ys;
      fi;
   elif size=3 then            # arrow_style is LARGE 
      if randomarrow=0 then
         xa[i,k] :=( x+dx);                         ya[i,k] := (y+dy);
         xa[i,k+1] := (x+dx - t2*(vx+vy)*xs);       ya[i,k+1] := (y+dy + t2*(vx-vy)*ys);
         xa[i,k+2] := (x+dx - (t2*vx+t3*vy)*xs);    ya[i,k+2] := (y+dy + (t3*vx-t2*vy)*ys);
         xa[i,k+3] := (x-dx - t3*vy*xs);            ya[i,k+3] := (y-dy + t3*vx*ys);
         xa[i,k+4] := (x-dx + t3*vy*xs);            ya[i,k+4] := (y-dy - t3*vx*ys);
         xa[i,k+5] := (x+dx + (-t2*vx+t3*vy)*xs);   ya[i,k+5] := (y+dy - (t2*vy+t3*vx)*ys);
         xa[i,k+6] := (x+dx + t2*(vy-vx)*xs);       ya[i,k+6] := (y+dy - t2*(vx+vy)*ys);
      else
         xa[i,0] :=( x+dx);                         ya[i,0] := (y+dy);
         xa[i,1] := (x+dx - t2*(vx+vy)*xs);         ya[i,1] := (y+dy + t2*(vx-vy)*ys);
         xa[i,2] := (x+dx - (t2*vx+t3*vy)*xs);      ya[i,2] := (y+dy + (t3*vx-t2*vy)*ys);
         xa[i,3] := (x-dx - t3*vy*xs);              ya[i,3] := (y-dy + t3*vx*ys);
         xa[i,4] := (x-dx + t3*vy*xs);              ya[i,4] := (y-dy - t3*vx*ys);
         xa[i,5] := (x+dx + (-t2*vx+t3*vy)*xs);     ya[i,5] := (y+dy - (t2*vy+t3*vx)*ys);
         xa[i,6] := (x+dx + t2*(vy-vx)*xs);         ya[i,6] := (y+dy - t2*(vx+vy)*ys);
      fi;
  elif size=4 then           # arrow_style is FISH
      Dx:=`DEtools/DEplot/CreatFish`(f,xa,ya,hfk,pt,i,j,info,size);
      dx:=Dx[1];   dy:=Dx[2];   dx2:=Dx[3];   dy2:=Dx[4];   dx3:=Dx[5];   dy3:=Dx[6];
      x1[1]:=x-(0.8*dx+1.2*dx3)/2;                  x1[2]:=y-(0.8*dy+1.2*dy3)/2;
      x2[1]:=x;                                     x2[2]:=y;
      x3[1]:=x+(0.8*dx+1.2*dx2)/2;                  x3[2]:=y+(0.8*dy+1.2*dy2)/2;
      plt:=`DEtools/DEplot/fish`(x1,x2,x3,size,maxim,fisht);
      if randomarrow=0 then
         for m from 0 to 9 do     xa[i,k+m] := plt[m,1];     ya[i,k+m] :=plt[m,2];     od;
         for m from 10to 18 do    xa[i,k+m] := plt[m-9,3];   ya[i,k+m] :=plt[m-9,4];   od; 
      else
         for m from 0 to 9 do     xa[i,m] := plt[m,1];       ya[i,m] :=plt[m,2];       od;
         for m from 10 to 18 do   xa[i,m] := plt[m-9,3];     ya[i,m] :=plt[m-9,4];     od;  fi;     
  elif size=5 then           # arrow_style is CURVE
      Dx:=`DEtools/DEplot/CreatFish`(f,xa,ya,hfk,pt,i,j,info,size);
      dx:=Dx[1];   dy:=Dx[2];   dx2:=Dx[3]; dy2:=Dx[4];   dx3:=Dx[5];   dy3:=Dx[6];
      x1[1]:=x-(0.8*dx+1.2*dx3)/2;                  x1[2]:=y-(0.8*dy+1.2*dy3)/2;
      x2[1]:=x;                                     x2[2]:=y;
      x3[1]:=x+(0.8*dx+1.2*dx2)/2;                  x3[2]:=y+(0.8*dy+1.2*dy2)/2;
      plt:=`DEtools/DEplot/fish`(x1,x2,x3,size,maxim,fisht);
      if randomarrow=0 then
         for m from 0 to 9 do     xa[i,k+m] := plt[m,1];       ya[i,k+m] :=plt[m,2];   od;
      else
         for m from 0 to 9 do     xa[i,m] := plt[m,1];         ya[i,m] :=plt[m,2];     od; fi; 
   fi;

end:  # `DEtools/DEplot/DrawIt`
#-------------------------------------------------------------------
`DEtools/DEplot/CreatFish`:=proc(f,xa,ya,hfk,pt,i,j,info,size)
local x,y,rt,rs,lt,ls,Dx,scale,xs,ys,xlen,ylen,vertices,ndvar,velocitylen,maxim,SCALE,SCALE2,SCALE3,dx,dy,vx,vy,k,xinc,yinc, dx2,dx3,dy2,dy3,MAX,rightx,righty,leftx,lefty;
   x:=pt[1];   y:=pt[2];
   rt:=array(1..2);   rs:=array(1..2);   lt:=array(1..2):   ls:=array(1..2);   Dx:=array(1..6);
   scale:= hfk[1];   xs := hfk[2];   ys := hfk[3];   xlen := hfk[4];   ylen := hfk[5];   vertices := hfk[6];
   ndvar:=info[1];   velocitylen:=info[2];   maxim:=info[3];   MAX:=info[4];
   xinc:=info[5];    yinc:=info[6];
   if  velocitylen=false then 
       SCALE:=0.9;
  else
       SCALE:=((((hfk[7])^2+(hfk[8])^2)^(1/2))/((1.05)*MAX))^(1/3); #using cube root scaling  
   fi;
   dx := scale*SCALE*hfk[7]*(ylen*hfk[7]^2+xlen*hfk[8]^2)^(-1/2);
   dy := scale*SCALE*hfk[8]*(ylen*hfk[7]^2+xlen*hfk[8]^2)^(-1/2);
   vx := dx/xs;   vy := dy/ys;   k:= vertices*j;
     if ndvar <> 1 then   
	rt[1]:=x+dx;  rt[2]:=y+dy;   
 	 f(2,rt[1],rt,rs);
	rightx:=evalf(rs[1]); righty:=evalf(rs[2]);
 	if   velocitylen=false then SCALE2:=1.0;
 	else
                           SCALE2:=1.21*((((rightx)^2+(righty)^2)^(1/2))/(MAX))^(1/5)
 	fi;
	if rightx=0 and righty=0 then 
	    dx2:=0; dy2:=0; 
	else
	       dx2:=scale*SCALE2*rightx*(ylen*rightx^2+xlen*righty^2)^(-1/2);
	       dy2:=scale*SCALE2*righty*(ylen*rightx^2+xlen*righty^2)^(-1/2);
	fi;
	lt[1]:=x-dx;  lt[2]:=y-dy;
 	f(2,lt[1],lt,ls);
                   leftx:=evalf(ls[1]); lefty:=evalf(ls[2]);
 	if  velocitylen=false then SCALE3:=1.0;
 	else
	          SCALE3:=1.21*((((leftx)^2+(lefty)^2)^(1/2))/(MAX))^(1/5)
 	fi;
	if leftx=0 and lefty=0 then 
	       dx3:=0; dy3:=0; 
	else
	       dx3:=scale*SCALE3*leftx*(ylen*leftx^2+xlen*lefty^2)^(-1/2);
	       dy3:=scale*SCALE3*lefty*(ylen*leftx^2+xlen*lefty^2)^(-1/2);
	fi;	
      else     
            dx:=0.8*dx;  dy:=0.8*dy;    
            rt[1]:=x+dx;  rt[2]:=y+dy;        
            f(2,rt[1],rt,rs);
            rightx:=(rs[1]); righty:=(rs[2]);
                  if   velocitylen=false then SCALE2:=1.4;
         	else
       	      SCALE2:=1.4*(rightx^2)^(0.5)/(MAX);
 	fi;
	if rightx=0 and righty=0 then 
	    dy2:=0; dx2:=0;
 	else
                      if (Im(rightx) <> 0) then
                           dx2:=0;    dy2:=0;
                     else   
                         dx2:=scale*SCALE2*(xlen*rightx^2)^(-1/2);
                          if dx2>0.2*maxim then  dx2:=0.2*maxim;  fi;  
	       dy2:=0;
                      fi;
	fi;                 
	lt[2]:=x-dx;  lt[1]:=y-dy;
 	f(2,lt[1],lt,ls);
                  leftx:=(ls[1]); lefty:=(ls[2]);
 	if velocitylen=false then SCALE3:=1.4;
 	else
       	       SCALE3:=1.4*(leftx^2)^(0.5)/(MAX);
 	fi;
	if leftx=0 and lefty=0 then 
	      dx3:=0; dy3:=0; 
	else
                      if (Im(leftx) <> 0) then
                          dx3:=0; dy3:=0;
                     else   
	        dx3:=scale*SCALE3*(xlen*leftx^2)^(-1/2);
 	         if dx3>0.2*maxim then  dx3:=0.2*maxim;
                        fi;  
	      dy3:=0;
                     fi;
	fi;           
      dx:=2.1*dx;   dy:=2.1*dy;     
      fi;   
      Dx[1]:=dx;   Dx[2]:=dy;   Dx[3]:=dx2; Dx[4]:=dy2;   Dx[5]:=dx3;   Dx[6]:=dy3;
     return Dx;
end; #`DEtools/DEplot/CreatFish`

#------------------------------------------------------------------------
`DEtools/DEplot/fish`:=proc(x1,x2,x3,size,maxim,fisht)
 local plt,a,b,c,d,e,f,g,i,s1,t1,h,t2,r11,r21,r12,r22,s,t;

 plt:=hfarray(0..9,1..4);
 # fits a paraboler (parametrically with t=0,1,2) to the three points (vectors) x1,x2,x3 in R^2
 a:=x1[1]/2-x2[1]+x3[1]/2; b:=(4*x2[1]-3*x1[1]-x3[1])/2; c:=x1[1];
 e:=x1[2]/2-x2[2]+x3[2]/2; f:=(4*x2[2]-3*x1[2]-x3[2])/2; g:=x1[2];
 if size=4 then # arrows=fish
   for i  from 1 to 10 do     
        # h[i]:=function of s, based on 0..1 looks like the top of a fish with head at s=1, tail at s=0   
        s1:=fisht[1,i];  h := maxim*0.2838854382*sqrt(1-s1)*exp(-5.0*(1-s1)); 
        t1 := fisht[2,i];  t2 := fisht[2,i+1]; r11 := c+t1*(b+a*t1);  r21 := g+t1*(f+e*t1);r12 := c+t2*(b+a*t2);  r22 := g+t2*(f+e*t2);
        s:=sqrt((r22-r21)^2+(r12-r11)^2);
        plt[i-1,1]:=r12+(h/s)*(r22-r21);     plt[i-1,2]:=r22+(h/s)*(r11-r12);
        plt[i-1,3]:=r12+(h/s)*(-r22+r21);   plt[i-1,4]:=r22+(h/s)*(-r11+r12);   
   od; 
   return plt;
   else # arrows=curve
        plt:=hfarray(0..9,1..2);
        for i  from 1 to 10 do  t:=fisht[3,i]; plt[i-1,1]:=c+t*(b+a*t); plt[i-1,2]:=g+t*(f+e*t); od; 
        return plt;
   fi;
end: #`DEtools/DEplot/fish`

#-----------------------------------------------------------------------------
#create a color function when using the velocity option.

`DEtools/DEplot/Colorfun`:= proc(f,lims,m,n,arrw,ndvar,w,test1,test2,randomarrow)
 local col,lm,ln;

   if test1 or test2 then
      if randomarrow=0 then   lm := m-1 ;  ln := n-1 ;   else   lm :=randomarrow-1; ln:=randomarrow-1; fi;
      `DEtools/DEplot/Arrows`(f,lims[w[1],1], lims[w[1],2],lims[w[2],1],lims[w[2],2],lm,ln,ndvar,randomarrow);
   else
      if randomarrow=0 then
         col := COLOR('HUE',seq(seq(0,i=1..m),j=1..n));
      else
         col := COLOR('HUE',seq(0,i=1..randomarrow));
      fi;
   fi;
end:  # `DEtools/DEplot/colorfun`


#------------------------------------------------------------------------------
#modified version of DEplot/arrows for computing colorinfo
`DEtools/DEplot/Arrows`:=proc(f,xmin,xmax,ymin,ymax,m,n,ndvar,randomarrow)

   local hfs,er;
       er:=NULL;
       hfs := array([xmin,xmax,ymin,ymax]);  
       er :=`DEtools/DEplot/Colorsf`(f,hfs,m,n,ndvar,randomarrow);
 
end:  # `DEtools/DEplot/Arrows`
#------------------------------------------------------------------------------
#Calculates the RGB color values.
`DEtools/DEplot/Colorsf` := proc(f,hfs,m,n,ndvar,randomarrow)

   local lcolour,colorG,colorB,colorR,j,i,x,y,yinc,xinc,ylen,xlen,ys,xs,l,rs,
           ymax,ymin,xmax,xmin,pt,MAX;

   xmin := hfs[1]; xmax := hfs[2]; ymin := hfs[3]; ymax := hfs[4];
   pt := array(1..3);  rs := array(1..3);
   l := 1/max(m,n);
   xs := xmax-xmin; ys := ymax-ymin;
   MAX:=0;
   xlen := xs^2;   ylen := ys^2;   xinc := xs/m;   yinc := ys/n; 
if ndvar <> 1 then      
    if randomarrow=0 then             
         pt[1] := xmin;                      
         for i from 0 to m do
            pt[2] := ymin;
            for j from 0 to n do
              f(2,pt[1],pt,rs);
               x := evalf(rs[1]);  y := evalf(rs[2]); 
               if Im(x) <> 0 or Im(y) <> 0 then
                 MAX:=max(MAX,0);
               else                        
                  MAX:=max(MAX,(((x)^2+(y)^2)^(1/2)));
               fi;
               pt[2] := pt[2]+yinc;
            od;
            pt[1] := pt[1]+xinc;
         od;
    else
         pt[1] := data1[0];       
         pt[2] := data2[0];               
         for i from 0 to randomarrow do
               f(2,pt[1],pt,rs);
               x:= evalf(rs[1]);  y := evalf(rs[2]);  # slopes
               if Im(x) <> 0 or Im(y) <> 0   then
                  MAX:=max(MAX,0);
               else                         
                 MAX:=max(MAX,(((x)^2+(y)^2)^(1/2)));
               fi;
               pt[2] := data2[i];
               pt[1] := data1[i];
        od;    
     fi;    
  else                                 
      pt[2] := xmin;                      
      x := 1;  
      for i from 0 to m do
         pt[1] := ymin;
         for j from 0 to n do
           f(2  ,pt[2],pt,rs);
            y:= rs[1];             
            if Im(y) <> 0 then
               MAX:=max(MAX,1);
            else
               MAX:=max(MAX,(((x)^2+(y)^2)^(1/2)));
            fi;
            pt[1] := pt[1]+yinc;
         od;
         pt[2] := pt[2]+xinc;
      od;
   fi;  
  #find RGB
  if ndvar <> 1 then                   
    if randomarrow=0 then        
         pt[1] := xmin;                      
         for i from 0 to m do
            pt[2] := ymin;
            for j from 0 to n do
               f(2,pt[1],pt,rs);
               x := evalf(rs[1]);  y := evalf(rs[2]);  # slopes
               if Im(x) <> 0 or Im(y) <> 0 #or not(type(rs[3],indexed))
               then
               colorR[i,j]:=0;   colorB[i,j]:=0;   colorG[i,j]:=0;
               else                         
               colorR[i,j]:=(((x^2+y^2)^(1/2))/MAX)^(1/2);   colorB[i,j]:=0;   colorG[i,j]:=1-(((x^2+y^2)^(1/2))/MAX)^(1/2);
               fi;
               pt[2] := pt[2]+yinc;
            od;
            pt[1] := pt[1]+xinc;
         od;
      else
          pt[1] := data1[0];       
          pt[2] := data2[0];               
          for i from 0 to randomarrow-1 do
                f(2,pt[1],pt,rs);
                x := evalf(rs[1]);  y := evalf(rs[2]);  # slopes
                colorR[i,i]:=(((x^2+y^2)^(1/2))/MAX)^(1/2);   colorB[i,i]:=0;   colorG[i,i]:=1-(((x^2+y^2)^(1/2))/MAX)^(1/2);
                pt[2] := data2[i+1];
                pt[1] := data1[i+1];
          od;
     fi;
   else                            
      pt[2] := xmin;                      
      x:= 1;  
      for i from 0 to m do
         pt[1] := ymin;
         for j from 0 to n do
            f(2,pt[2],pt,rs);
            y:= rs[1];             
            if Im(y) <> 0 or not(type(rs[3],indexed)) then  
            colorR[i,j]:=0;   colorB[i,j]:=0;   colorG[i,j]:=0;               
            else
            colorR[i,j]:=(((x^2+y^2)^(1/2))/MAX)^(1/2);   colorB[i,j]:=0;   colorG[i,j]:=1-(((x^2+y^2)^(1/2))/MAX)^(1/2);
            fi;
            pt[1] := pt[1]+yinc;
         od;
         pt[2] := pt[2]+xinc;
      od;
   fi;   
   if randomarrow=0 then
      lcolour := COLOR('RGB', op( map(op,[seq(map(op,[seq([colorR[i,j], colorG[i,j],colorB[i,j]],i=0..m)]),j=0..n)])));
   else
      lcolour := COLOR('RGB', op( map(op,[seq([colorR[i,i], colorG[i,i],colorB[i,i]],i=0..m)])));
   fi;
 return lcolour;
end:  # `DEtools/DEplot/Colorsf`
#------------------------------------------------------------------------------
# Handle the colour option by setting colorinfo appropriately.

`DEtools/DEplot/CreateColour`:=proc(colorinfo,lims,m,n,ivar,dvar,vars,w,randomarrow)

   local a,b,c,d,xa,ya,za,F,i,j,lcolour,arg1,arg2,c_info;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   a := lims[w[1],1]; b := lims[w[1],2]; c:=lims[w[2],1]; d := lims[w[2],2];
   c_info := colorinfo;
   for i from 1 to nops(dvar) do
      c_info := subs(vars[i]=dvar[i],c_info);
   od;
   if type(colorinfo,name) and not(type(colorinfo,procedure)) and \
       not(has(colorinfo,{op(dvar)})) then
      lcolour := `plot/color`(colorinfo);
   elif op(0,colorinfo) = 'COLOR' or op(0,colorinfo) = 'COLOUR' then
      lcolour := colorinfo;
   elif type(colorinfo,list) and nops(colorinfo) = 3  then
      if w[1] = 1 then arg1 := ivar else arg1 := dvar[w[1]-1] fi;
      if w[2] = 1 then arg2 := ivar else arg2 := dvar[w[2]-1] fi;
      F[1] := op(1,c_info); F[2] := op(2,c_info); F[3] := op(3,c_info);
      for i from 1 to 3 do
         if not(type(F[i],procedure)) then
            if not(type(F[i],realcons)) and not(has(F[i],{arg1,arg2})) then
               error "Colour list elements must be expressions in %1, %2", arg1,arg2;
            fi;
            F[i] := `DEtools/makefunc`(F[i],[arg1,arg2]);
         elif nops([op(1,op(F[i]))]) <> 2 then
            error "Colour procedure lists must take two arguments.";
         fi;
      od;
      #The function colorsur needs to be fixed. for now this function works when randomarrow>0 but it is very slow.
      #for ref. look at the function arrowshf. Moe ebrahimi
      xa := `plot3d/colorsur`(F[1],a,b,c,d,m,n);
      ya := `plot3d/colorsur`(F[2],a,b,c,d,m,n);
      za := `plot3d/colorsur`(F[3],a,b,c,d,m,n);
      if randomarrow=0 then
      lcolour := COLOR('RGB', op( map(op,[seq(map(op,[seq([xa[i,j],ya[i,j],za[i,j]],i=1..m+1)]),j=1..n+1)])));
      else
      lcolour := COLOR('RGB', op( map(op,[seq([xa[i,m],ya[i,m],za[i,m]],i=1..m+1)])));
      fi;
   elif type(colorinfo,list) then
      error "Colour lists must have three elements.";
   else
      if not(type(colorinfo,procedure)) then
         if w[1] = 1 then arg1 := ivar else arg1 := dvar[w[1]-1] fi;
         if w[2] = 1 then arg2 := ivar else arg2 := dvar[w[2]-1] fi;
         if not(has(c_info,{arg1,arg2})) then
            error "Arrow colour expressions must take either %1 or %2", arg1,arg2;
         fi;
         F := `DEtools/makefunc`(c_info,[arg1,arg2]);
      else
         if nops([op(1,op(colorinfo))]) <> 2 then
            error "Arrow colour procedures must take two arguments.";
         fi;
         F := c_info;
      fi;
      za :=traperror(`plot3d/colorsur`(F,a,b,c,d,m,n));
      if za = lasterror then
         error "check color function, getting error- %1", za;
      fi;
      if randomarrow=0 then
            lcolour := COLOR('HUE',op(map(op,[seq([seq(za[i,j],i=1..m+1)],j=1..n+1)])));
      else
            lcolour := COLOR('HUE',op(map(op,[seq(za[i,1],i=1..m+1)])));
      fi;
   fi;
   return lcolour;
end:  # `DEtools/DEplot/CreateColour`

#-----------------------------------------------------------------------------
# Generate the resulting plots.

`DEtools/DEplot/CreatePlots`:=proc(plot_3,lims,linepts,m,n,arrowpts,w,ftrs)

   local ap,bp,cp,dp,region,arrowpoints,linepoints,features;

   option 
       `Copyright (c) 1994 by the University of Waterloo. All rights reserved.`;

   linepoints:= op(linepts); arrowpoints:= op(arrowpts); features:= op(ftrs);
   if plot_3 then
      region:= VIEW(lims[w[1],1]..lims[w[1],2],lims[w[2],1]..lims[w[2],2],\
          lims[w[3],1]..lims[w[3],2]);
      PLOT3D(linepoints,STYLE('WIREFRAME'),AXES('BOXED'),region,features);
   else 
      ap := lims[w[1],1]; bp := lims[w[1],2];
      cp := lims[w[2],1]; dp := lims[w[2],2];
      region := VIEW(ap-(bp-ap)/m..bp+(bp-ap)/m, cp-(dp-cp)/n..dp+(dp-cp)/n);
      PLOT(arrowpoints,linepoints,region,features);
   fi;
end:  # `DEtools/DEplot/CreatePlots`
#-----------------------------------------------------------------------------

`DEtools/DEplot/makefunc` := proc(f,ivar,x)

   local lf;

   option `Copyright (c) 1995 by Waterloo Maple Inc. All rights reserved.`;

   if nops(x) = 1 then
      if type(f,list(numeric)) then
         subs( {_func=f,_ivar=ivar},
            proc(N,_ivar,Y,YP)
               YP[1] := _ivar;  YP[2] := _func[1];
            end )
      elif _plotDigits <= evalhf(Digits) then
         lf := subs( _body1=subs(x[1]=Y[1],ivar=`&args`[2],f[1]),
             `&statseq`(
                 `&:=`(`&args`[4][1],_body1)
                       ));
         lf := `&proc`([N,ivar,Y,YP],[],[],lf);
         lf := procmake(lf);
      else
         lf := subs( _body1=subs(x[1]=Y[1],ivar=`&args`[2],f[1]),
             `&statseq`(
                 `&:=`(`&local`[1],traperror(evalf(_body1,_plotDigits))),
                 `&if`('type'(`&local`[1],numeric),
                       `&:=`(`&args`[4][1],`&local`[1]),
                       true,`&:=`(`&args`[4][1],undefined))
                        ));
         lf := `&proc`([N,ivar,Y,YP],[a1],[],lf);
         lf := procmake(lf);
      fi
   else
      if type(f,list(numeric)) then
         subs( _func=f,
            proc(N,ivar,Y,YP)
               YP[1] := _func[1];  YP[2] := _func[2];
            end )#-------------------------------------------------------------------------------------------------------------------
      elif _plotDigits <= evalhf(Digits) then
         lf := subs( _body1=subs(x[1]=Y[1],x[2]=Y[2],ivar=`&args`[2],f[1]),
                     _body2=subs(x[1]=Y[1],x[2]=Y[2],ivar=`&args`[2],f[2]),
             `&statseq`(
                 `&:=`(`&args`[4][1],_body1),
                 `&:=`(`&args`[4][2],_body2)
                       ));
         lf := `&proc`([N,ivar,Y,YP],[],[],lf);
         lf := procmake(lf);
      else
         lf := subs( _body1=subs(x[1]=Y[1],x[2]=Y[2],ivar=`&args`[2],f[1]),
                     _body2=subs(x[1]=Y[1],x[2]=Y[2],ivar=`&args`[2],f[2]),
             `&statseq`(
                 `&:=`(`&local`[1],traperror(evalf(_body1,_plotDigits))),
                 `&if`('type'(`&local`[1],numeric),
                       `&:=`(`&args`[4][1],`&local`[1]),
                       true,`&:=`(`&args`[4][1],undefined)),
                 `&:=`(`&local`[2],traperror(evalf(_body2,_plotDigits))),
                 `&if`('type'(`&local`[2],numeric),
                       `&:=`(`&args`[4][2],`&local`[2]),
                       true,`&:=`(`&args`[4][2],undefined))
                        ));
         lf := `&proc`([N,ivar,Y,YP],[a1,a2],[],lf);
         lf := procmake(lf);
      fi
   fi;
   return lf
end;

macro( `DEtools/makefunc`   = `DEtools/makefunc`,
           H=H,
          `DEtools/DEplot/HighCheck`  = `DEtools/DEplot/HighCheck`,
          `DEtools/DEplot/Autonomous` = `DEtools/DEplot/Autonomous`,
          `t`  = `t`,    `N` = `_N`,
          `Y`  = `Y`,   `YP` = `YP`,
          `a1` = `a1`,  `a2` = `a2`,
          `_x` = `_x`,   `_y` = `_y`,
          `_v` = `_v`,   `_body1` = `_body1`,
          `_body2` = `_body2`,  `_ivar` = `_ivar`,
          `_func` = `_func`
        ):
#-----------------------------------------------------------------------------

#savelib(\
'`DEtools/DEplot`',\
'`DEtools/DEplot/InputCheck`',\
'`DEtools/DEplot/TOrder`',\
'`DEtools/DEplot/AnalyseOptions`',\
'`DEtools/DEplot/CheckInitial`',\
'`DEtools/DEplot/WhichPlot`',\
'`DEtools/DEplot/NameToDepvar`',\
'`DEtools/DEplot/CheckDE`',\
'`DEtools/DEplot/CreateLines`',\
'`DEtools/DEplot/drawlines`',\
'`DEtools/DEplot/CreateArrows`',\
'`DEtools/DEplot/direction`',\
'`DEtools/DEplot/arrows`',\
'`DEtools/DEplot/arrowsf`',\
'`DEtools/DEplot/arrowshf`',\
'`DEtools/DEplot/fish`',\
'`DEtools/DEplot/h1`',\
'`DEtools/DEplot/h2`',\
'`DEtools/DEplot/DrawIt`',\
'`DEtools/DEplot/CreatFish`',\
'`DEtools/DEplot/fish`',\
'`DEtools/DEplot/CreateColour`',\
'`DEtools/DEplot/maxarrow`',\
'`DEtools/DEplot/CreatePlots`',\
'`DEtools/DEplot/Colorfun`',\
'`DEtools/DEplot/makefunc`'):
