Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/plot/plot3d/revolution_plot3d.py
4036 views
1
"""
2
Surfaces of revolution
3
4
AUTHORS:
5
6
- Oscar Gerardo Lazo Arjona (2010): initial version.
7
"""
8
9
#*****************************************************************************
10
# Copyright (C) 2010 Oscar Gerardo Lazo Arjona [email protected]
11
#
12
# Distributed under the terms of the GNU General Public License (GPL)
13
#
14
# This code is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
# General Public License for more details.
18
#
19
# The full text of the GPL is available at:
20
#
21
# http://www.gnu.org/licenses/
22
#*****************************************************************************
23
24
from sage.plot.plot3d.parametric_plot3d import parametric_plot3d
25
def revolution_plot3d(curve,trange,phirange=None,parallel_axis='z',axis=(0,0),print_vector=False,show_curve=False,**kwds):
26
"""
27
Return a plot of a revolved curve.
28
29
There are three ways to call this function:
30
31
- ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.
32
33
- ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.
34
35
- ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.
36
37
INPUT:
38
39
- ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.
40
41
- ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.
42
43
- ``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.
44
45
- ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.
46
47
- ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:
48
49
- 'z' - then axis is the point in which the revolution axis intersects the `x y` plane.
50
51
- 'x' - then axis is the point in which the revolution axis intersects the `y z` plane.
52
53
- 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.
54
55
- ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.
56
57
- ``show_curve`` - If True, the curve will be displayed.
58
59
60
EXAMPLES:
61
62
Let's revolve a simple function around different axes::
63
64
sage: u = var('u')
65
sage: f=u^2
66
sage: revolution_plot3d(f,(u,0,2),show_curve=True,opacity=0.7).show(aspect_ratio=(1,1,1))
67
68
If we move slightly the axis, we get a goblet-like surface::
69
70
sage: revolution_plot3d(f,(u,0,2),axis=(1,0.2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))
71
72
A common problem in calculus books, find the volume within the following revolution solid::
73
74
sage: line=u
75
sage: parabola=u^2
76
sage: sur1=revolution_plot3d(line,(u,0,1),opacity=0.5,rgbcolor=(1,0.5,0),show_curve=True,parallel_axis='x')
77
sage: sur2=revolution_plot3d(parabola,(u,0,1),opacity=0.5,rgbcolor=(0,1,0),show_curve=True,parallel_axis='x')
78
sage: (sur1+sur2).show()
79
80
81
Now 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::
82
83
sage: u = var('u')
84
sage: circle=(cos(u),sin(u))
85
sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))
86
87
An axis on `(0,y)` will produce a cylinder-like surface::
88
89
sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))
90
91
And any other axis will produce a torus-like surface::
92
93
sage: revolution_plot3d(circle,(u,0,2*pi),axis=(2,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))
94
95
Now, we can get another goblet-like surface by revolving a curve in 3d::
96
97
sage: u = var('u')
98
sage: curve=(u,cos(4*u),u^2)
99
sage: revolution_plot3d(curve,(u,0,2),show_curve=True,parallel_axis='z',axis=(1,.2),opacity=0.5).show(aspect_ratio=(1,1,1))
100
101
A curvy curve with only a quarter turn::
102
103
sage: u = var('u')
104
sage: curve=(sin(3*u),.8*cos(4*u),cos(u))
105
sage: 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)
106
"""
107
from sage.symbolic.ring import var
108
from sage.symbolic.constants import pi
109
from sage.functions.other import sqrt
110
from sage.functions.trig import sin
111
from sage.functions.trig import cos
112
from sage.functions.trig import atan2
113
114
115
if parallel_axis not in ['x','y','z']:
116
raise ValueError, "parallel_axis must be either 'x', 'y', or 'z'."
117
118
vart=trange[0]
119
120
121
if str(vart)=='phi':
122
phi=var('fi')
123
else:
124
phi=var('phi')
125
126
127
if phirange is None:#this if-else provides a phirange
128
phirange=(phi,0,2*pi)
129
elif len(phirange)==3:
130
phi=phirange[0]
131
pass
132
else:
133
phirange=(phi,phirange[0],phirange[1])
134
135
if isinstance(curve,tuple) or isinstance(curve,list):
136
#this if-else provides a vector v to be plotted
137
#if curve is a tuple or a list of length 2, it is interpreted as a parametric curve
138
#in the x-z plane.
139
#if it is of length 3 it is interpreted as a parametric curve in 3d space
140
141
if len(curve) ==2:
142
x=curve[0]
143
y=0
144
z=curve[1]
145
elif len(curve)==3:
146
x=curve[0]
147
y=curve[1]
148
z=curve[2]
149
else:
150
x=vart
151
y=0
152
z=curve
153
154
if parallel_axis=='z':
155
x0=axis[0]
156
y0=axis[1]
157
# (0,0) must be handled separately for the phase value
158
phase=0
159
if x0!=0 or y0!=0:
160
phase=atan2((y-y0),(x-x0))
161
R=sqrt((x-x0)**2+(y-y0)**2)
162
v=(R*cos(phi+phase)+x0,R*sin(phi+phase)+y0,z)
163
elif parallel_axis=='x':
164
y0=axis[0]
165
z0=axis[1]
166
# (0,0) must be handled separately for the phase value
167
phase=0
168
if z0!=0 or y0!=0:
169
phase=atan2((z-z0),(y-y0))
170
R=sqrt((y-y0)**2+(z-z0)**2)
171
v=(x,R*cos(phi+phase)+y0,R*sin(phi+phase)+z0)
172
elif parallel_axis=='y':
173
x0=axis[0]
174
z0=axis[1]
175
# (0,0) must be handled separately for the phase value
176
phase=0
177
if z0!=0 or x0!=0:
178
phase=atan2((z-z0),(x-x0))
179
R=sqrt((x-x0)**2+(z-z0)**2)
180
v=(R*cos(phi+phase)+x0,y,R*sin(phi+phase)+z0)
181
182
if print_vector:
183
print v
184
if show_curve:
185
curveplot=parametric_plot3d((x,y,z),trange,thickness=2,rgbcolor=(1,0,0))
186
return parametric_plot3d(v,trange,phirange,**kwds)+curveplot
187
return parametric_plot3d(v,trange,phirange,**kwds)
188
189