MathGroup Archive 1990

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Plotting two surfaces

  • Subject: Re: Plotting two surfaces
  • From: uunet!garnet.berkeley.edu!campbell (Robert I. Campbell)
  • Date: Mon, 12 Mar 90 16:16:34 PST
  • Apparently-to: mathgroup-send at yoda.ncsa.uiuc.edu

>I wonder if it is possible to overlap two surfaces in Mathematica
>(on one plot).
>
>Peter
>flatau at handel.cs.colostate.edu

Basically, the way to do this is to convert both surfaces (SurfaceGraphics
objects) to Graphics3D objects, then Show the resulting Graphics3D objects.
It would be nice to be able to directly combine SurfaceGraphics objects,
but the whole idea of such an object is that if it can be assumed to be a
graph of a SINGLE function of two variables, then the hidden line
algorithms sued in displaying it are much simplified. Try the following:
plot1=Plot3D[Sin[x y],{x,-Pi,Pi},{y,-Pi,Pi}]
plot2=Plot3D[(x^2-y^2)/9,{x,-Pi,Pi},{y,-Pi,Pi}]
plot1=Graphics3D[plot1]  (* Converts to Graphics3D object *)
plot2=Graphics3D[plot2]
Show[{plot1,plot2}]
	Alternatively, I wrote a widget to do this called MultiPlot3D. It
is in a package called "Student.m", which I will append to this letter.
It is also available for anonymous ftp from otter.stanford.edu in the
/ftp/mma directory.

					- Robert Campbell -
					Math Dept, UC Berkeley

BeginPackage["Student`"]

(* Copyright 1990 Robert Campbell *)

Bezier::usage = "Bezier[{{x0,y0},...,{x3,y3}}]
computes the cubic bezier curve with control points
{xi,yi}, prints out its parametric description, and
then draws the curve and its control polygon, and
returns the parametric description.
Bezier[{{x0,y0},...},nodraw] returns a list of the two
components of the parametric description."

Midpoint::usage = "Midpoint[f,{x,xmin,xmax},n] will compute the numeric
integral of the function f(x) on the interval [xmin,xmax],
using the midpoint method with n divisions. The numeric
result and the error, or difference from the system command
NIntegrate, will be printed and the result returned will
be a graph of the	process. Midpoint[f,{x,xmin,xmax},n,nodraw]
prints the error and returns the numeric result without graphing it."
	
MultiPlot3D::usage = "MultiPlot3D[{f1,...},{x_,x0_,x1_},{y_,y0_,y1_}]
extends the function Plot3D by allowing the user to plot 
several functions of two variables on the same set of axes. 
The result is a Graphics3D object, not a SurfaceGraphics object.
The function can use the same options as Plot3D (Not entirely true at
present 14 Feb, 1990). THIS IS A VERY SLOW AND EXPENSIVE PROGRAM."

	
Newton::usage = "Newton[f,{x,xstart},n] will use n steps
of Newton's method to try to compute a root of f(x),
starting at the point x=xstart and will return a graph of
the process. Newton[f,{x,xstart},n,nodraw] will print the
result at each step of the process, and will return a list
of the values."

Polyapprox::usage = "Polyapprox[f,x,{x0,...,xn}]
will compute the polynomial of degree (n-1) which interpolates
f(x) at the points {x0,...}. It will print this polynomial
and then graph it on the same plot with f along with f."

Trapezoid::usage = "Trapezoid[f,{x,xmin,xmax},n] will
compute the numeric integral of f(x) on the interval
[xmin,xmax], using the trapezoid method with n divisions.
The numeric result and the error, or difference from the
system command NIntegrate, will be printed and a
graph will be returned. Trapezoid[f,{x,xmin,xmax},n,nodraw]
prints the error and returns the numeric result without graphing it."

nodraw;

Begin["`Private`"]

Bezier[{{x0_,y0_},{x1_,y1_},{x2_,y2_},{x3_,y3_}}]:=
(* Compute and display the cubic Bzier curve with the specified control pts.*)
Block[{xcoord,ycoord,plot,points,poly,paramname,t},
	(* Define the x and y coordinates of the point on the curve 
	with parameter un. Generate a new name, of the form un, for the 
	parametric variable used in Bezier. *)
	paramname = Unique["u"];
	xcoord=x0*(1-paramname)^3 + 3*x1*paramname*(1-paramname)^2 \
		+ 3*x2*paramname^2*(1-paramname) + x3*paramname^3;
	ycoord=y0*(1-paramname)^3 + 3*y1*paramname*(1-paramname)^2 \
		+ 3*y2*paramname^2*(1-paramname) + y3*paramname^3;
	Print["The Bzier curve is:"];
	Print["x(",paramname,") = ",xcoord];
	Print["y(",paramname,") = ",ycoord];
	(* recompute the curve using an internal variable parameter *)
	xcoord=x0*(1-t)^3 + 3*x1*t*(1-t)^2 + 3*x2*t^2*(1-t) + x3*t^3;
	ycoord=y0*(1-t)^3 + 3*y1*t*(1-t)^2 + 3*y2*t^2*(1-t) + y3*t^3;
	(* Now draw the curve invisibly *)
	plot=ParametricPlot[{xcoord,ycoord},{t,0,1},DisplayFunction->Identity];
	(* Prepare to draw the control points *)
	points={Point[{x0,y0}],Point[{x1,y1}],Point[{x2,y2}],Point[{x3,y3}]};
	(* Connect the control points to get the control polygon. *)
	poly=Line[{{x0,y0},{x1,y1},{x2,y2},{x3,y3}}];
	(* combine the graph with the control points, and display them. *)
	Show[Graphics[{PointSize[0.02],points,poly}],plot,\
		DisplayFunction->$DisplayFunction]
]

Bezier[{{x0_,y0_},{x1_,y1_},{x2_,y2_},{x3_,y3_}},nodraw]:=
(* Compute the cubic Bzier curve with the specified 
control pts and return it as a parametric curve in "un".*)
Block[{xcoord,ycoord,paramname},
	(* Generate a new name, of the form un, for the parametric 
	variable used in Bezier. *)
	paramname = Unique["u"];
	xcoord=x0*(1-paramname)^3 + 3*x1*paramname*(1-paramname)^2 \
		+ 3*x2*paramname^2*(1-paramname) + x3*paramname^3;
	ycoord=y0*(1-paramname)^3 + 3*y1*paramname*(1-paramname)^2 \
		+ 3*y2*paramname^2*(1-paramname) + y3*paramname^3;
	{xcoord,ycoord}
]	

Midpoint[f_,{x_,xmin_,xmax_},n_]:=
(* This routine will compute the numeric integral of the
function f(x) on the interval [xmin,xmax], using the 
midpoint method with n divisions. The numeric result and
the error, or difference from the system NIntegrate, will
be printed and the result returned will be a graph of the
process.*)
Block[{mp,error,i,j,rectlist,linelist,val,step,plot}, 
	mp=0;
	step=(xmax-xmin)/n;
	For[i=0,i<n,i++,
		val[i]=f/. x-> xmin+(i+0.5) step;
		mp=mp+val[i] step;
	];
	rectlist=Table[Rectangle[{xmin+j*step,0},{xmin+(j+1) step,val[j]}]\
		,{j,0,n-1}];
	linelist=Table[Line[{{xmin+j*step,0},{xmin+j*step,val[j]},\
		{xmin+(j+1) step,val[j]},{xmin+(j+1) step,0}}],{j,0,n-1}];
	rectlist=Prepend[rectlist,GrayLevel[0.6]];
	linelist=Prepend[linelist,GrayLevel[0]];
	plot=Plot[f,{x,xmin,xmax},DisplayFunction->Identity];
	error=Abs[N[mp-NIntegrate[f,{x,xmin,xmax}]]];
	Print["The integral is approximately ",N[mp]];
	Print["error=",error];
	Show[Graphics[Join[rectlist,linelist]],plot,\
		DisplayFunction->$DisplayFunction]
]

Midpoint[f_,{x_,xmin_,xmax_},n_,nodraw]:=
(* This routine will compute the numeric integral of the
function f(x) on the interval [xmin,xmax], using the 
midpoint method with n divisions. The error, or 
difference from the system NIntegrate, will be printed 
and the result returned will be the numeric result. *)
Block[{mp,error,i,j,rectlist,val,step}, 
	mp=0;
	step=(xmax-xmin)/n;
	For[i=0,i<n,i++,
		val[i]=f/. x-> xmin+(i+0.5) step;
		mp=mp+val[i] step;
	];
	error=Abs[N[mp-NIntegrate[f,{x,xmin,xmax}]]];
	Print["error=",error];
	N[mp]
]

MultiPlot3D[fcns_List,{x_,x0_,x1_},{y_,y0_,y1_},opts___]:=
(* This routine extends the function Plot3D by allowing the
user to plot several functions of two variables on the same
set of axes. The result is a Graphics3D object, not a 
SurfaceGraphics object. At present those options which are
valid for Graphics3D, as well as the Mesh option, are not
properly passed or acted on *)
Block[{plotopts,showopts,plotoptstest},
	(* Strip out those options which are unique to Plot3D, as
	opposed to those options understood by Graphics3D *)
	plotoptstest=(MatchQ[#,PlotPoints->_] || 
		MatchQ[#,ClipFill->_] || MatchQ[#,HiddenSurface->_] ||
		MatchQ[#,Mesh->_] || MatchQ[#,MeshStyle->_])&;
	plotopts=Cases[{opts},_?plotoptstest];
	showopts=Cases[{opts},_?(Not[plotoptstest[#]]&)];
	Show[Map[Graphics3D,Map[Plot3D[#,{x,x0,x1},{y,y0,y1},plotopts,\
		DisplayFunction->Identity]&,fcns]],showopts,\
		DisplayFunction->$DisplayFunction]
]
	
Newton[f_,{x_,xstart_},n_,nodraw]:=
(* This routine will use Newton's method to solve the equation f(x)=0 for x.
The initial guess, xstart, is supplied by the user, as is the desired number
of iterations, n. At each step the routine prints out the new estimate, xi, the
value of the function at xi, and the amount the new estimate differs from the
previous estimate. *)
Block[{fprime,xi,xiold,xlist},
	xlist = {xstart};	
	fprime:=D[f,x];
	xi=xstart;                (* We start out with our first guess *)
	For[i=1,i<n,i++,
		xiold=xi;                (* Keep track of our last guess *)
		(* Use Newton's Method to find a better guess. 
		We keep track of 60 digits internally. *)
		xi=xi-N[((f/fprime)/.x->xi),60]; 
		AppendTo[xlist,xi];   (* And add it to our list of guesses *)
		Print[i];
		Print["xi=",N[xi,10]];         (* Print guess to 10 digits *)
		Print["f(xi)=",N[(f /. x->xi),10]];(* Print function value *)
		Print["xi-x(i-1)=",N[xi-xiold,10]];(* Change in guess *)
		(* Print out the relevant information *)
	];
	N[xlist,10]                   (* Return 10 digits as a final value *)
]

Newton[f_,{x_,xstart_},n_]:=
(* This routine will use Newton's method to solve the equation f(x)=0 for x.
The initial guess, xstart, is supplied by the user, as is the desired number
of iterations, n. The output is a graph which shows a plot of the function f,
each successive estimate, xi, and the value of f at xi. The plot also draws
the tangent line to f at {xi,f(xi)} which is used to get the next estimate. *)
Block[{fprime,xi,xiold,i,pointlist,linelist,xmin,xmax,plot},
	(* Keep track of max and min x to get the plot bounds *)
	xmin = xstart;
	xmax = xstart;
	fprime := D[f,x];
	xi = N[xstart];
	(* Put in the initial elements of the graphics lists *)
	pointlist={Point[N[{xstart,f/.x->xstart}]]};
	linelist={};
	For[i=1,i<=n,i++,
		xiold = xi;             (* Save the old value of xi *)
		xi = xi-((f/fprime)/.x->xi); 
		(* Use Newton's Method to find a better guess *)
		(* Draw the line and the new point *)
		pointlist=Append[pointlist,Point[{xi,f/.x->xi}]];
		linelist=Append[linelist,Line[{{xiold,f/.x->xiold},{xi,0}}]];
		(* Keep track of max and min x to get the plot bounds *)
		If[xi<xmin,xmin=xi,];
		If[xi>xmax,xmax=xi,];
	];
	(* First we plot the graph invisibly, adding some space on each end *)
	plot=Plot[f,{x,xmin-0.2(xmax-xmin),xmax+0.2(xmax-xmin)},\
		DisplayFunction->Identity];
	(* Then we plot all the desired information *)
	Show[Graphics[Join[{PointSize[0.02]},pointlist,linelist]],plot\
		,DisplayFunction->$DisplayFunction]
]

Polyapprox[f_,x_,p_]:=
(* This function will find the polynomial of least degree which
passes through the points {x0,f(x0)},{x1,f(x1},... It will print
this polynomial and then plot the polynomial on the same graph 
with f(x). Actually, the command Fit can be used to do the same thing.*)
Block[{i,soln,pts,points,a,plot},
	pts=Table[{p[[i]],f/.x->p[[i]]},{i,Length[p]}];
	poly=Fit[pts,Table[x^i,{i,0,Length[p]-1}],x];
	points=Table[Point[{p[[i]],poly/.x->p[[i]]}],{i,1,Length[p]}];
	plot=Plot[{f,poly},{x,Min[p]-1,Max[p]+1},DisplayFunction->Identity];
	Show[Graphics[{PointSize[0.02],points}],plot,\
		DisplayFunction->$DisplayFunction];
	poly
	]
	
Trapezoid[f_,{x_,xmin_,xmax_},n_]:=
(* This routine will compute the numeric integral of the
function f(x) on the interval [xmin,xmax], using the 
trapezoid method with n divisions. The numeric result and
the error, or difference from the system NIntegrate, will
be printed and the result returned will be a graph of the
process.*)
Block[{trap,error,i,j,rectlist,linelist,val,step,plot},
Array[val,n,0];
	mp=0;
	step=(xmax-xmin)/n;
	val[0]=f/. x->xmin;
	For[j=0,j<n,j++,
		val[j+1]=f/. x-> xmin+(j+1)*step];
		j=.;
	trap=Sum[(val[i]+val[i+1])*step/2,{i,0,n-1}];
	rectlist=Table[Polygon[{{xmin+j*step,0},{xmin+j*step,val[j]}\
		,{xmin+(j+1) step,val[j+1]},{xmin+(j+1) step,0}}],{j,0,n-1}];
	linelist=Table[Line[{{xmin+j*step,0},{xmin+j*step,val[j]},\
		{xmin+(j+1) step,val[j+1]},{xmin+(j+1) step,0}}],{j,0,n-1}];
	rectlist=Prepend[rectlist,GrayLevel[0.6]];
	linelist=Prepend[linelist,GrayLevel[0]];
	plot=Plot[f,{x,xmin,xmax},DisplayFunction->Identity];
	error=Abs[N[trap-NIntegrate[f,{x,xmin,xmax}]]];
	Print["The integral is approximately ",N[trap]];
	Print["error=",error];
	N[trap];
	Show[Graphics[Join[rectlist,linelist]],plot,\
		DisplayFunction->$DisplayFunction]
]

Trapezoid[f_,{x_,xmin_,xmax_},n_,nodraw]:=
(* This routine will compute the numeric integral of the
function f(x) on the interval [xmin,xmax], using the 
trapezoid method with n divisions. The error, or 
difference from the system NIntegrate, will be printed 
and the result returned will be the numeric result. *)
Block[{trap,error,j,val,step},
Array[val,n,0];
	mp=0;
	step=(xmax-xmin)/n;
	val[0]=f/. x->xmin;
	For[j=0,j<n,j++,
		val[j+1]=f/. x-> xmin+(j+1)*step];
		j=.;
	trap=Sum[(val[i]+val[i+1])*step/2,{i,0,n-1}];
	error=Abs[N[trap-NIntegrate[f,{x,xmin,xmax}]]];
	Print["error=",error];
	N[trap]
]

End[]
EndPackage[]



  • Prev by Date: combining graphics into single plot
  • Next by Date: Speeding up Mathematica
  • Previous by thread: Plotting two surfaces
  • Next by thread: combining graphics into single plot