Path: blob/master/sage/plot/plot3d/revolution_plot3d.py
4036 views
"""1Surfaces of revolution23AUTHORS:45- Oscar Gerardo Lazo Arjona (2010): initial version.6"""78#*****************************************************************************9# Copyright (C) 2010 Oscar Gerardo Lazo Arjona [email protected]10#11# Distributed under the terms of the GNU General Public License (GPL)12#13# This code is distributed in the hope that it will be useful,14# but WITHOUT ANY WARRANTY; without even the implied warranty of15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16# General Public License for more details.17#18# The full text of the GPL is available at:19#20# http://www.gnu.org/licenses/21#*****************************************************************************2223from sage.plot.plot3d.parametric_plot3d import parametric_plot3d24def revolution_plot3d(curve,trange,phirange=None,parallel_axis='z',axis=(0,0),print_vector=False,show_curve=False,**kwds):25"""26Return a plot of a revolved curve.2728There are three ways to call this function:2930- ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.3132- ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.3334- ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.3536INPUT:3738- ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.3940- ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.4142- ``phirange`` - A 2-tuple of the form `(\phi_{\min},\phi_{\max})`, (default `(0,\pi)`) that specifies the angle in which the curve is to be revolved.4344- ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.4546- ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:4748- 'z' - then axis is the point in which the revolution axis intersects the `x y` plane.4950- 'x' - then axis is the point in which the revolution axis intersects the `y z` plane.5152- 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.5354- ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.5556- ``show_curve`` - If True, the curve will be displayed.575859EXAMPLES:6061Let's revolve a simple function around different axes::6263sage: u = var('u')64sage: f=u^265sage: revolution_plot3d(f,(u,0,2),show_curve=True,opacity=0.7).show(aspect_ratio=(1,1,1))6667If we move slightly the axis, we get a goblet-like surface::6869sage: revolution_plot3d(f,(u,0,2),axis=(1,0.2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))7071A common problem in calculus books, find the volume within the following revolution solid::7273sage: line=u74sage: parabola=u^275sage: sur1=revolution_plot3d(line,(u,0,1),opacity=0.5,rgbcolor=(1,0.5,0),show_curve=True,parallel_axis='x')76sage: sur2=revolution_plot3d(parabola,(u,0,1),opacity=0.5,rgbcolor=(0,1,0),show_curve=True,parallel_axis='x')77sage: (sur1+sur2).show()787980Now let's revolve a parametrically defined circle. We can play with the topology of the surface by changing the axis, an axis in `(0,0)` (as the previous one) will produce a sphere-like surface::8182sage: u = var('u')83sage: circle=(cos(u),sin(u))84sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))8586An axis on `(0,y)` will produce a cylinder-like surface::8788sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))8990And any other axis will produce a torus-like surface::9192sage: revolution_plot3d(circle,(u,0,2*pi),axis=(2,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))9394Now, we can get another goblet-like surface by revolving a curve in 3d::9596sage: u = var('u')97sage: curve=(u,cos(4*u),u^2)98sage: revolution_plot3d(curve,(u,0,2),show_curve=True,parallel_axis='z',axis=(1,.2),opacity=0.5).show(aspect_ratio=(1,1,1))99100A curvy curve with only a quarter turn::101102sage: u = var('u')103sage: curve=(sin(3*u),.8*cos(4*u),cos(u))104sage: revolution_plot3d(curve,(u,0,pi),(0,pi/2),show_curve=True,parallel_axis='z',opacity=0.5).show(aspect_ratio=(1,1,1),frame=False)105"""106from sage.symbolic.ring import var107from sage.symbolic.constants import pi108from sage.functions.other import sqrt109from sage.functions.trig import sin110from sage.functions.trig import cos111from sage.functions.trig import atan2112113114if parallel_axis not in ['x','y','z']:115raise ValueError, "parallel_axis must be either 'x', 'y', or 'z'."116117vart=trange[0]118119120if str(vart)=='phi':121phi=var('fi')122else:123phi=var('phi')124125126if phirange is None:#this if-else provides a phirange127phirange=(phi,0,2*pi)128elif len(phirange)==3:129phi=phirange[0]130pass131else:132phirange=(phi,phirange[0],phirange[1])133134if isinstance(curve,tuple) or isinstance(curve,list):135#this if-else provides a vector v to be plotted136#if curve is a tuple or a list of length 2, it is interpreted as a parametric curve137#in the x-z plane.138#if it is of length 3 it is interpreted as a parametric curve in 3d space139140if len(curve) ==2:141x=curve[0]142y=0143z=curve[1]144elif len(curve)==3:145x=curve[0]146y=curve[1]147z=curve[2]148else:149x=vart150y=0151z=curve152153if parallel_axis=='z':154x0=axis[0]155y0=axis[1]156# (0,0) must be handled separately for the phase value157phase=0158if x0!=0 or y0!=0:159phase=atan2((y-y0),(x-x0))160R=sqrt((x-x0)**2+(y-y0)**2)161v=(R*cos(phi+phase)+x0,R*sin(phi+phase)+y0,z)162elif parallel_axis=='x':163y0=axis[0]164z0=axis[1]165# (0,0) must be handled separately for the phase value166phase=0167if z0!=0 or y0!=0:168phase=atan2((z-z0),(y-y0))169R=sqrt((y-y0)**2+(z-z0)**2)170v=(x,R*cos(phi+phase)+y0,R*sin(phi+phase)+z0)171elif parallel_axis=='y':172x0=axis[0]173z0=axis[1]174# (0,0) must be handled separately for the phase value175phase=0176if z0!=0 or x0!=0:177phase=atan2((z-z0),(x-x0))178R=sqrt((x-x0)**2+(z-z0)**2)179v=(R*cos(phi+phase)+x0,y,R*sin(phi+phase)+z0)180181if print_vector:182print v183if show_curve:184curveplot=parametric_plot3d((x,y,z),trange,thickness=2,rgbcolor=(1,0,0))185return parametric_plot3d(v,trange,phirange,**kwds)+curveplot186return parametric_plot3d(v,trange,phirange,**kwds)187188189