# Transform Plots Package Version 1.0
with(plots):

# This is the format of a function to be entered
# as an argument for ttransform_plot_fcn.
# g := (x,y) -> [exp(x)*cos(y),exp(x)*sin(y)];

# Transform a 2D plot structure P by a function f.
# P is expected to be created by a plot call 
# producing a PLOT(CURVES(...),...) structure
# The function f should be defined in the form
# (x,y) -> [exprn1_in_x_y,exprn2_in_x_y].
# The procedure works by applying f to each of the
# points in the CURVES part of the plot structure.
transform_plot_fcn := proc(P,f1)
	local pts,new_pts,u,v,w,new_color;
	u:= f1 @ op;
	pts := op(1,op(1,P));
	new_pts := map(u,pts);
	new_color := subsop(2=1,op(2,op(1,P)));
    subsop(1=subsop(1=new_pts,2=new_color, op(1,P)),
		   P);
	end:
	
# A simple example:
# 	P1 := plot(x^2,x=-1..1);
# Image of the parabola under the complex exponential map:
# 	P3 := transform_plot_fcn(P1,g):
# 	display(P3);

# Plot a rectangle with corners at [left,top] and [right,lower].
rect_plot0 := proc(left,top,right,lower)
	local rect1,rect2,rect3,rect4;

	rect1 := plot([t,top,t=left .. right]);
	rect2 := plot([t,lower,t=left .. right]);
	
	rect3 := plot([left,t,t=lower .. top]);
	rect4 := plot([right,t,t=lower .. top]);
	{rect1,rect2,rect3,rect4};
end:

# Plot a rectangle with corners at corner1 and corner2.
# Both corner1 and corner2 are assumed to be lists of
# two elements.
rect_plot := proc(corner1,corner2)
	local top,left,lower,right,rect1,rect2,rect3,rect4;
	
	left := corner1[1];
	top := corner1[2];
	right := corner2[1];
	lower := corner2[2];

	rect1 := plot([t,top,t=left .. right]);
	rect2 := plot([t,lower,t=left .. right]);
	
	rect3 := plot([left,t,t=lower .. top]);
	rect4 := plot([right,t,t=lower .. top]);
	{rect1,rect2,rect3,rect4};
end:

# orig_rect := rect_plot([2,4],[3,1]):
# display(orig_rect);

# Transform a 2D plot structure P by a function f, or
# by an expression in a list of variables. Thus acceptable
# calls are 
#	transform_plot(P,f)
# or
#	transform_plot(P,[exprn1_in_vars,exprn2_in_vars],
#			list_of_vars]).
transform_plot := proc(P)
	local fcn,expn,vars;
	if (nargs = 3) then
		expn := args[2];
		vars := args[3];
		fcn := unapply(expn,convert(vars[1],list),convert(vars[2],list));
		transform_plot_fcn(P,fcn);
	elif (nargs = 2) and (type(eval(args[2]),procedure))then
		transform_plot_fcn(P,args[2]);
	fi;
end:

#transform_plot(P1,g);

#transform_plot(P1,[exp(x)*cos(y),exp(x)*sin(y)],[x,y]);

# A way of combining an original rectangle together with the
# image of its boundary:
# image_rect := orig_rect union map(u->transform_plot(u,g),orig_rect):
# display(image_rect);

# Transform the boundary of a rectangle with corners corner1
# and corner2 by fcn. The original rectangle and its image are both
# displayed.
# The format for corner1 and corner2 is a list of two real numbers.
# The function f should be defined in the form
# (x,y) -> [exprn1_in_x_y,exprn2_in_x_y].
transform_rect_fcn := proc(corner1,corner2,fcn)
	local top,left,lower,right,rect1,rect2,rect3,rect4,w,
		orig_rect;
	
	left := corner1[1];
	top := corner1[2];
	right := corner2[1];
	lower := corner2[2];

	rect1 := plot([t,top,t=left .. right]);
	rect2 := plot([t,lower,t=left .. right]);
	
	rect3 := plot([left,t,t=lower .. top]);
	rect4 := plot([right,t,t=lower .. top]);		 	  display({rect1,rect2,rect3,rect4,transform_plot(rect1,fcn),transform_plot(rect2,fcn),transform_plot(rect3,fcn),transform_plot(rect4,fcn)});
	end:

# Transform the boundary of a rectangle with corners corner1
# and corner2 by either a function or by an expression
# in a list of variables. 
# The original rectangle and its image are both displayed.
# Transform a 2D plot structure P by a function f, or
# by an expression in a list of variables. Thus acceptable
# calls are 
#	transform_rect(corner1,corner2,f)
# or
#	transform_plot(corner1,corner2,
#			[exprn1_in_vars,exprn2_in_vars],
#			list_of_vars]).
transform_rect := proc(corner1,corner2)
	local fcn,expn,vars;
	if (nargs = 4) then
		expn := convert(args[3],list);
		vars := convert(args[4],list);
		fcn := unapply(expn,vars[1],vars[2]);
		transform_rect_fcn(corner1,corner2,fcn);
	elif (nargs = 3) and (type(eval(args[3]),procedure)) then
		transform_rect_fcn(corner1,corner2,args[3]);
	fi;
end:

# transform_rect([1.,.1],[.1,1.],(x,y) ->[x^2-y^2,2*x*y]);

# transform_rect([1.,.1],[.1,1.],[x^2-y^2,2*x*y],[x,y]);

 help_transform_plots := proc();
	printf(`\n\t\t\t\tPlot Transformation Package Version 1.0\n`);
	printf(`\nThis set of functions aids in transforming two dimensional\n`);
	printf(`plots by functions from R^2 to R^2.\n`);
	printf(`\n`);
	printf(`Basic examples include:\n`);
	printf(`\n`);
	printf(`\t\tP1 := plot(x^2,x=-1..1);\n`);
	printf(`\t\ttransform_plot(P1,[exp(x)*cos(y),exp(x)*sin(y)],[x,y]);\n`);
	printf(`\n`);
	printf(`to transform the graph of the parabola y = x^2 by the map\n`);
	printf(`(x,y) -> [exp(x)*cos(y),exp(x)*sin(y)].\n`);
	printf(`\n`);
	printf(`and\n`);
	printf(`\n`);
	printf(`\t\ttransform_rect([2.,2.],[1.,1.],[x^2-y^2,2*x*y],[x,y]);\n`);
	printf(`\n`);
	printf(`to display the rectangle with corners [1,1] and [2,2]\n`);
	printf(`together with the image of its boundary under the map\n`);
	printf(`(x,y) -> [x^2-y^2,2*x*y].\n`);
	printf(`\n`);
	printf(`Other routines are:\n`);
	printf(`\t\trect_plot([2,4],[3,1]);\n`);
	printf(`to display the rectangle with corners [2,4] and [3,1] and\n`);
	printf(`\t\thelp_transform_plots();\n`);
	printf(`to display this message.\n`);
	printf(`\n`);

	
end:

help_transform_plots();