# 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: