`surfarro/evl` := t -> convert(evalm(t), list); `surfarro/enull`:= proc(s) if type(s,string) then NULL else s fi end; savelib('`surfarro/evl`', '`surfarro/enull`',`surfarro/init.m`); `surfarro/arrow3d` := proc(base::{list,vector},vect::{list,vector,`+`}) ## Plots an arrow as a line with a pyramidal head. ## usage: arrow3d(base, vect, options) ## "base" is point for base of arrow, "vect" is tip - base ## These can be lists or vectors. ## "options" are the usual plot3d options, plus ## scalefactor=s to scale length by real constant s. ## Colour is red, and stem thickness 3, by default. options `Maple Advisor Database 1.00 for Maple V Release 4 and 5`, `Copyright (c) 1998 by Robert B. Israel. All rights reserved`; local b1,v1,stem,r,hbase,hpoint,v2,v3,head,opts, scopts; b1 := evalf(`surfarro/evl`(base)); v1 := evalf(`surfarro/evl`(vect)); if not type(v1,list) or nops(b1) <> 3 or nops(v1) <> 3 then ERROR(`points need three dimensions`) fi; if not (type(b1,[realcons,realcons,realcons]) and type(v1,[realcons,realcons,realcons])) then ERROR(`coordinates must evaluate to real constants`) fi; opts := args[3 .. nargs]; scopts := indets({opts}, identical('scalefactor')=realcons); if scopts <> {} then v1:= evalf(op(2,scopts[1])) * v1; opts:= op({opts} minus scopts); fi; hbase := `surfarro/evl`(b1+.8*v1); hpoint := `surfarro/evl`(b1+v1); if not has({opts},{color,colour}) then opts := opts,colour = red fi; if not has({opts},thickness) then opts:= opts, thickness=3 fi; stem := plots[spacecurve]([b1,hbase],opts); if v1 = [0,0,0] then RETURN(stem) fi; r := sqrt(linalg[norm](v1,2)); v2 := `surfarro/evl`(linalg[crossprod]([1,0,0],v1)); if linalg[dotprod](v2,v2) < .01*linalg[dotprod](v1,v1) then v2 := `surfarro/evl`(linalg[crossprod]([0,1,0],v1)) fi; v2 := `surfarro/evl`(.05*r*v2/linalg[norm](v2,2)); v3 := linalg[crossprod](v1,v2); v3 := `surfarro/evl`(.05*r*v3/linalg[norm](v3,2)); head := plots[polygonplot3d]([hpoint,`surfarro/evl`(hbase+v2), `surfarro/evl`(hbase+v3), `surfarro/evl`(hbase-v2), `surfarro/evl`(hbase-v3), `surfarro/evl`(hbase+v2)] ,style = patchnogrid,opts); plots[display]({stem,head}) end; `surfarro/arrow2d` := proc(base::{list,vector}, vect::{list,vector,`+`}) ## Plots an arrow as a line with a triangular head. ## usage: arrow2d(base, vect, options) ## "base" is point for base of arrow, "vect" is tip - base ## These can be lists or vectors. ## "options" are the usual plot options, plus ## scalefactor=s to scale length by real constant s. ## Colour is red by default. options `Maple Advisor Database 1.00 for Maple V Release 4 and 5`, `Copyright (c) 1998 by Robert B. Israel. All rights reserved`; local b1,v1,stem,hbase,hpoint,v2,head,opts, scopts; b1 := evalf(`surfarro/evl`(base)); v1 := evalf(`surfarro/evl`(vect)); if not type(v1,list) or nops(b1) <> 2 or nops(v1) <> 2 then ERROR(`points need two dimensions`) fi; if not (type(b1,[realcons,realcons]) and type(v1,[realcons,realcons])) then ERROR(`coordinates must evaluate to real constants`) fi; opts := args[3 .. nargs]; scopts := indets({opts}, identical('scalefactor')=realcons); if scopts <> {} then v1:= evalf(op(2,scopts[1])) * v1; opts:= op({opts} minus scopts); fi; if not has({opts},{color,colour}) then opts := opts,colour = red fi; if not has({opts},thickness) then opts:= opts, thickness=3 fi; hbase := `surfarro/evl`(b1+.8*v1); hpoint := `surfarro/evl`(b1+v1); stem := plot([b1,hbase],opts); if v1 = [0,0] then RETURN(stem) fi; v2:= [.1*v1[2],-.1*v1[1]]; head := plots[polygonplot]([hpoint,`surfarro/evl`(hbase+v2),`surfarro/evl`(hbase-v2)], style = patchnogrid,opts); plots[display]({stem,head}) end; savelib('`surfarro/arrow2d`',`surfarro/arrow2d.m`); savelib('`surfarro/arrow3d`',`surfarro/arrow3d.m`); `surfarro/surfarrows` := proc(fld,surf,r1::name=range,r2::name=range) ## Plots a 3d surface (parametric or cartesian) with arrows from ## a vector field at points on the surface ## Usage: ## surfarrows(F(s,t), [x(s,t),y(s,t),z(s,t)], s=a1 .. b1, t=a2 .. b2, options) ## for vectors F(s,t) at points [x(s,t), y(s,t), z(s,t)] ## where F(s,t) is a list or vector expression ## surfarrows(F(x,y), z(x,y), x=a1 .. b1, y=a2 .. b2, options) ## for vectors F(x,y) at points [x, y, z(x,y)] ## where F(x,y) is a list or vector expression ## surfarrows(F, [x(s,t),y(s,t),z(s,t)], s=a1 .. b1, t=a2 .. b2, options) ## for vectors F(x(s,t),y(s,t),z(s,t)) at [x(s,t),y(s,t),z(s,t)] ## where F is a list-valued or vector-valued function of three variables ## surfarrows(F, z(x,y), x=a1 .. b1, y=a2 .. b2, options) ## for vectors F(x,y,z(x,y)] at [x,y,z(x,y)] ## where F is a list-valued or vector-valued function of three variables ## "options" are the usual 3d plot options, plus ## arrowgrid= [n1, n2] ## for arrows in an n1 by n2 grid, equally spaced in terms of the parameters ## of the surface (default is arrowgrid=[8,8]) ## arrowcolour= c (or arrowcolor=c) for arrows of colour c. The default ## is the same as the "colour" option, if that is specified, or red if it is not. ## arrowthickness= n for arrows of thickness n. The default is the ## same as "thickness" if that is specified, otherwise 3. ## scalefactor= s to multiply arrow lengths by real constant s. options `Maple Advisor Database 1.00 for Maple V Release 4 and 5`, `Copyright (c) 1998 by Robert B. Israel. All rights reserved`; local opts,aopts,gspec,acspec,p1,p2,s2,f2,v1,v2,a1,a2,b1,b2,n1,n2,h1,h2,i,j,remproc; opts := args[5 .. nargs]; v1 := op(1,r1); v2 := op(1,r2); a1 := op(1,op(2,r1)); b1 := op(2,op(2,r1)); a2 := op(1,op(2,r2)); b2 := op(2,op(2,r2)); gspec := indets({opts},identical('arrowgrid') = list); if gspec = {} then gspec := arrowgrid = [8,8] else opts := op({opts} minus gspec); gspec := gspec[1] fi; acspec:= indets({opts}, {identical('arrowcolour'),identical('arrowcolor'), identical('arrowthickness'), identical('scalefactor')} = anything); if acspec <> {} then opts:= op({opts} minus acspec); fi; p1 := plot3d(surf,r1,r2,opts); opts := {opts} minus indets({opts}, {identical('grid'),identical('style')} = anything); if acspec <> {} then acspec:=subs('arrowcolour'='colour','arrowcolor'='colour', 'arrowthickness'='thickness',acspec); aopts:= subs('color'='colour',opts); remproc:= (opt,spec) -> has(spec, op(1,opt)); aopts:= op(remove(remproc, aopts, acspec)), op(acspec); else aopts:= op(opts) fi; n1 := op(2,gspec)[1]-1; n2 := op(2,gspec)[2]-1; h1 := (b1-a1)/n1; h2 := (b2-a2)/n2; if type(surf,list) and nops(surf)=3 then s2 := surf elif type(surf,vector) and linalg[vectdim](surf)=3 then s2 := `surfarro/evl`(surf) elif type(surf,algebraic) then s2 := [v1,v2,surf] else ERROR(surf, `is not an expression for a surface`) fi; if type(fld,procedure) then f2:= `surfarro/evl`(fld(op(s2))) elif type(fld, vector) then f2:= `surfarro/evl`(fld) elif type(fld, list) then f2:= fld else ERROR(fld,`is not a vector field`) fi; if nops(f2) <> 3 then ERROR(fld,`is not a 3-dimensional field`) fi; p2 := seq(seq(`surfarro/enull`(traperror( surfarro[arrow3d](op(subs(v2 = a2+j*h2,v1 = a1+h1*i,[s2,f2])),aopts))), i = 0 .. n1),j = 0 .. n2); plots[display]({p2,p1},op(opts)) end; `surfarro/curvarrows` := proc(fld,curv,t::name=range) ## Plots a 2d or 3d curve (parametric or cartesian) with arrows from ## a vector field at points on the curve ## Usage: ## curvarrows(F(t), [x(t),y(t) {,z(t)}], t=a .. b, options) ## for vectors F(t) at points [x(t), y(t) {, z(t)}] ## where F(t) is a list expression ## curvarrows(F(x), y(x), x=a .. b, options) ## for vectors F(x) at points [x, y(x)] ## where F(x) is a list expression ## curvarrows(F, [x(t),y(t) {, z(t)}], t=a .. b, options) ## for vectors F(x(t),y(t) {, z(t)}) at [x(t),y(t) {,z(t)} ] ## where F is a list-valued function of two {or three} variables ## curvarrows(F, y(x), x=a .. b, options) ## for vectors F(x,y(x)) at [x,y(x)] ## where F is a list-valued function of two variables ## "options" are the usual plot or plot3d options, plus ## arrownum= n ## for n arrows along the curve, equally spaced in terms of the ## parameter defining the curve (default is 10) ## arrowcolour= c (or arrowcolor=c) for arrows of colour c. The default ## is the same as the "colour" option, if that is specified, or red if it is not. ## arrowthickness= n for arrows of thickness n. The default is the ## same as the "thickness" option, if that is specified, or 3 otherwise. ## scalefactor= s to multiply arrow lengths by real constant s options `Maple Advisor Database 1.00 for Maple V Release 4 and 5`, `Copyright (c) 1998 by Robert B. Israel. All rights reserved`; local opts,aopts,gspec,acspec,p1,p2,s2,f2,v1,a1,b1,n1,h1,i,dim,aproc,remproc,vw; opts := args[4 .. nargs]; v1 := op(1,t); a1 := op(1,op(2,t)); b1 := op(2,op(2,t)); gspec := indets({opts},identical('arrownum') = posint); if gspec = {} then gspec := arrownum = 10 else opts := op({opts} minus gspec); gspec := gspec[1] fi; acspec:= indets({opts}, {identical('arrowcolour'),identical('arrowcolor'), identical('arrowthickness'), identical('scalefactor')} = anything); if acspec <> {} then opts:= op({opts} minus acspec); fi; if type(curv, algebraic) then dim:= 2 elif type(curv,list) then if nops(curv)=3 then dim:= 3 elif nops(curv)=2 then dim:= 2 else ERROR(`The curve`, curv,`does not have two or three components`) fi else ERROR(curv, `is not an expression for a curve`) fi; if dim=2 then aproc:= eval(surfarro[arrow2d]); if type(curv, list) then p1:= plot([op(curv), t], opts) # parametric 2d else p1 := plot(curv,t,opts) # cartesian 2d fi else aproc:= eval(surfarro[arrow3d]); p1:= plots[spacecurve](curv,t,opts) # parametric 3d fi; vw:= indets(p1,specfunc(anything,VIEW)); # remove VIEW option if nops(vw) > 0 then p1:= subs(map(t -> (t=NULL),vw),p1) fi; opts := {opts} minus indets({opts}, {identical('numpoints'),identical('style')} = anything); if acspec <> {} then acspec:=subs('arrowcolour'='colour','arrowcolor'='colour', 'arrowthickness'='thickness',acspec); aopts:= subs('color'='colour',opts); remproc:= (opt,spec) -> has(spec, op(1,opt)); aopts:= op(remove(remproc, aopts, acspec)), op(acspec); else aopts:= op(opts) fi; n1 := op(2,gspec)-1; h1 := (b1-a1)/n1; if type(curv,list) then s2 := curv else s2 := [v1,curv] fi; if type(fld,procedure) then f2:= `surfarro/evl`(fld(op(s2))) else f2:= `surfarro/evl`(fld) fi; if not type(f2,list) or nops(f2) <> dim then ERROR(fld,`is not a vector of dimension`,dim) fi; p2 := seq(`surfarro/enull`(traperror( aproc(op(subs(v1 = a1+h1*i,[s2,f2])),aopts))), i = 0 .. n1); plots[display]({p2,p1},op(opts)) end; savelib('`surfarro/surfarrows`',`surfarro/surfarrows.m`); savelib('`surfarro/curvarrows`',`surfarro/curvarrows.m`); surfarro:= table(package,'surfarro',[ arrow2d = 'readlib('`surfarro/arrow2d`')', arrow3d = 'readlib('`surfarro/arrow3d`')', curvarrows = 'readlib('`surfarro/curvarrows`')', surfarrows = 'readlib('`surfarro/surfarrows`')']): savelib('surfarro', `surfarro.m`); savelib();