# This file defines Maple functions to generate various plots and save # them as jpg files or in Maple's internal format. Some of the jpg # files are then included in the main LaTeX document for the project. # There are directories called plots and images, which are siblings # of the top maple directory. Plots in Maple's internal format are # stored in the plots directory, with names like foo.m. Images in # jpg format are stored in the images directory, with names like # foo.jpg. There is also a global variable called pics, and a Maple # representation of the plot may be stored as pics["foo"]. #@ pics pics := table(): # Files in .m format cannot contain bare, unnamed expressions. # Instead, they record values for certain named variables. To save # a plot P, we first assign P to the variable __pic__, then we # save that variable. When we read the file later, the required # plot will be assigned to __pic__ again, and we will immediately # copy it to somewhere more useful. The housekeeping is managed # by the functions save_plot and load_plot. __pic__ := NULL: make_plot := table(): ###################################################################### # This function returns true if P is a 2 or 3 dimensional plot object. # This fits into a general Maple framework, so if we define # a function like foo := proc(X::plot) ... end, then an error will # be generated if we call foo with an argument that is not a plot # object. #@ `type/plot` `type/plot` := (P) -> (type(P,function) and (op(0,P) = PLOT or op(0,P) = PLOT3D or op(0,P) = _PLOTARRAY)); ###################################################################### # The function list_plots() returns a list of names of plot files # in the plots directory. They are returned without the suffix .m. # One can also supply a regular expression to match agianst. For # example, list_plots("^E") will return a list of files that start # with E. #@ list_plots list_plots := proc(regex) local P,Q,f; Q := FileTools[ListDirectory](plots_dir); P := NULL; for f in Q do if length(f) > 2 and substring(f,-2..-1) = ".m" then P := P,substring(f,1..-3); fi; od; P := [P]; if nargs > 0 then P := select(f -> StringTools[RegMatch](regex,f),P); fi; return P; end: ###################################################################### # This function saves a plot. It can be called in two ways. # If we invoke save_plot("foo",P), then P will be saved in the file # foo.m in the plots directory, and pics["foo"] will also be set # equal to P. If we just invoke save_plot("foo"), then pics["foo"] # should already be set equal to a plot object, and that object # will be saved in foo.m. #@ save_plot save_plot := proc(s::string,P_::plot) global __pic__,pics; local P; if nargs > 1 then pics[s] := P_; P := P_; else P := pics[s]; if not type(P,plot) then error(sprintf("pics[%s] is not a plot",s)); fi; fi; __pic__ := pics[s]; if not(type(plots_dir,string)) then error("plots_dir is not set"); fi; if not(isdir(plots_dir)) then mkdir(plots_dir); fi; save(__pic__,cat(plots_dir,"/",s,".m")); __pic__ := NULL; end: # This accepts an arbitrary number of arguments, and applies the # single-argument form of save_plot() to each of them. #@ save_plots save_plots := proc() local s; for s in args do save_plot(s); od; end: ###################################################################### # Invoking load_plot("foo") will read a plot from the file foo.m, # save it as pics["foo"], and return the result. #@ load_plot load_plot := proc(s::string) global __pic__,pics; read(cat(genus2_dir,"/plots/",s,".m")); pics[s] := __pic__; __pic__ := NULL; pics[s]; end: # This accepts an arbitrary number of arguments, and applies # load_plot() to each of them. #@ load_plots load_plots := proc() local s; for s in args do load_plot(s); od; NULL; end: ###################################################################### # Invoking save_jpg("foo") will convert pics["foo"] to a jpg image # and save it in the images directory. Note that pics["foo"] should # have been set equal to a plot object before using this function. #@ save_jpg save_jpg := proc(s::string,w_,h_) local P,old_dir,w,h; P := pics[s]; if not type(P,plot) then error(sprintf("pics[%s] is not a plot",s)); fi; w := `if`(nargs>1,w_,1000); h := `if`(nargs>2,h_,1000); if not(type(images_dir,string)) then error("images_dir is not set"); fi; if not(isdir(images_dir)) then mkdir(images_dir); fi; old_dir := currentdir(images_dir); plotsetup(jpeg, plotoutput=cat(s,".jpg"), plotoptions=sprintf("height=%d,width=%d",h,w) ); print(P); plotsetup(default); currentdir(old_dir); end: save_jpgs := proc() local s; for s in args do save_jpg(s); od; end: #@ save_thumbnail save_thumbnail := proc(s::string) local P,old_dir,w,h; P := pics[s]; if not type(P,plot) then error(sprintf("pics[%s] is not a plot",s)); fi; if not(type(plots_dir,string)) then error("plots_dir is not set"); fi; if not(isdir(plots_dir)) then mkdir(plots_dir); fi; if not(isdir(thumbs_dir)) then mkdir(thumbs_dir); fi; old_dir := currentdir(thumbs_dir); plotsetup(jpeg, plotoutput=cat(s,".jpg"), plotoptions="height=100,width=100" ); print(P); plotsetup(default); currentdir(old_dir); end: #@ make_all_thumbnails make_all_thumbnails := proc() local old_pics,labels,label,P; global pics; # To avoid using an enormous amount of memory, we do not retain # all plot objects in the pics table. old_pics := eval(pics): labels := list_plots(): for label in labels do printf("%s\n",label); pics := table(): load_plot(label); P := pics[label]; if not(type(P,plot)) then P := display(P); pics[label] := P; fi; if type(P,plot) then save_thumbnail(label); fi; od: pics := eval(old_pics); NULL; end: ###################################################################### # This just makes the syntax for plotting plane curves more # compatible with the syntax for plotting space curves. #@ planecurve planecurve := (xy,R) -> plot([op(xy),R],args[3..-1]); #@ planetext planetext := (xy, t) -> textplot([op(xy),t],args[3..-1]); #@ spacetext spacetext := (xyz,t) -> textplot3d([op(xyz),t],args[3..-1]); ###################################################################### # Some convenience functions for plotting complex numbers as # points in R^2. Note that these functions will work with # expressions involving the symbolic constants a_H, a_P and a_E. # They will be replaced by the numerical values a_H0, a_P0 and a_E0. #@ cpolygon cpolygon := proc(points) polygon(map(z -> evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},[Re(z),Im(z)])),points),args[2..-1]); end: #@ ccurve ccurve := proc(points) curve(map(z -> evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},[Re(z),Im(z)])),points),args[2..-1]); end: #@ cpoint cpoint := proc(z) point(evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},[Re(z),Im(z)])),args[2..-1]); end: #@ cline cline := proc(z,w) line(evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},[Re(z),Im(z)])), evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},[Re(w),Im(w)])), args[3..-1]); end: #@ ctext ctext := proc(z,t) local x0,y0,z0; z0 := evalf(subs({a_H=a_H0,a_P=a_P0,a_E=a_E0},z)); x0 := Re(z0); y0 := Im(z0); textplot([x0,y0,t],args[3..-1]); end: #@ cplot cplot := proc(c,R) plot([Re(c),Im(c),R],args[3..-1]); end: ###################################################################### # sphere_arc(a,b,col) returns a plot element that can be used as an # argument to the display() function. It represents an arc of the # sphere joining a to b, in the colour specified by the argument col. # It is crude and only works well for short arcs. #@ sphere_arc sphere_arc := proc(a::RR0_3,b::RR0_3,col) local c,i,j,r; for i from 0 to 10 do c[i] := [seq(0.1* (i * a[j] + (10-i) * b[j]),j=1..3)]: r := sqrt(add(c[i][j]^2,j=1..3)); c[i] := [seq(c[i][j]/r,j=1..3)]; od: curve([seq(c[i],i=0..10)],colour=col); end: ###################################################################### # torus_box_plot(c) expects c to be a function R -> S^1 x S^1 which # is periodic of period 2 pi. It returns a plot of c with the torus # unwrapped to a flat square, and it deals with discontinuities in a # way that is adequate for the cases that we need. One can pass # additional arguments, such as torus_box_plot(c,colour = red). torus_box_plot_aux := proc(c,s) local a,eps; eps := 0.0001; a := map(argument,c)/~Pi +~ (2 *~ s); display( seq(planecurve(a,t=j*Pi/2+eps..(j+1)*Pi/2-eps,args[3..-1]),j=0..4), axes=none,scaling=constrained ): end: #@ torus_box_plot torus_box_plot := proc(c) if c[1] = -1 then display(torus_box_plot_aux(c,[ 0, 0],args[2..-1]), torus_box_plot_aux(c,[-1, 0],args[2..-1])); elif c[2] = -1 then display(torus_box_plot_aux(c,[ 0, 0],args[2..-1]), torus_box_plot_aux(c,[ 0,-1],args[2..-1])); else display(torus_box_plot_aux(c,[ 0, 0],args[2..-1])); fi: end: ###################################################################### triangle_axes := proc(z_range := -2..2) local tc,z_min,z_max; tc[1] := evalf([op(triangle_proj([1,0,0])),0]): tc[2] := evalf([op(triangle_proj([0,1,0])),0]): tc[3] := evalf([op(triangle_proj([0,0,1])),0]): z_min := op(1,z_range); z_max := op(2,z_range); display( line(tc[1],tc[2],colour=black), line(tc[2],tc[3],colour=black), line(tc[3],tc[1],colour=black), line(tc[1],[0,0,0],colour=black), line(tc[2],[0,0,0],colour=black), line(tc[3],[0,0,0],colour=black), line([0,0,z_min],[0,0,z_max],colour=black), scaling=constrained,axes=none ): end: ###################################################################### #@ make_wireframe_plots make_wireframe_plots := proc() global pics; pics["torus_wireframe"] := plot3d(TA_to_R3([t,u]),t=0..2*Pi,u=0..2*Pi, colour=gray,style=wireframe,scaling=constrained,axes=none); pics["sphere_wireframe"] := display(sphere([0,0,0],1,colour=grey,style=wireframe),axes=none): save_plot("torus_wireframe"); save_plot("sphere_wireframe"); save_jpg("torus_wireframe"); save_jpg("sphere_wireframe"); NULL; end: