Path: blob/master/sage/plot/plot3d/parametric_plot3d.py
4038 views
"""1Parametric Plots2"""34from parametric_surface import ParametricSurface5from shapes2 import line3d6from sage.misc.misc import xsrange, srange7from sage.structure.element import is_Vector89from sage.ext.fast_eval import fast_float, fast_float_constant1011def parametric_plot3d(f, urange, vrange=None, plot_points="automatic", boundary_style=None, **kwds):12r"""13Return a parametric three-dimensional space curve or surface.1415There are four ways to call this function:1617- ``parametric_plot3d([f_x, f_y, f_z], (u_min,18u_max))``:19`f_x, f_y, f_z` are three functions and20`u_{\min}` and `u_{\max}` are real numbers2122- ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,23u_max))``:24`f_x, f_y, f_z` can be viewed as functions of25`u`2627- ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max),28(v_min, v_max))``:29`f_x, f_y, f_z` are each functions of two variables3031- ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,32u_max), (v, v_min, v_max))``:33`f_x, f_y, f_z` can be viewed as functions of34`u` and `v`353637INPUT:3839- ``f`` - a 3-tuple of functions or expressions, or vector of size 34041- ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple42(u, u_min, u_max)4344- ``vrange`` - (optional - only used for surfaces) a452-tuple (v_min, v_max) or a 3-tuple (v, v_min, v_max)4647- ``plot_points`` - (default: "automatic", which is4875 for curves and [40,40] for surfaces) initial number of sample49points in each parameter; an integer for a curve, and a pair of50integers for a surface.5152- ``boundary_style`` - (default: None, no boundary) a dict that describes53how to draw the boundaries of regions by giving options that are passed54to the line3d command.5556- ``mesh`` - bool (default: False) whether to display57mesh grid lines5859- ``dots`` - bool (default: False) whether to display60dots at mesh grid points6162.. note::6364#. By default for a curve any points where `f_x`,65`f_y`, or `f_z` do not evaluate to a real number66are skipped.6768#. Currently for a surface `f_x`, `f_y`, and69`f_z` have to be defined everywhere. This will change.7071#. mesh and dots are not supported when using the Tachyon ray tracer72renderer.737475EXAMPLES: We demonstrate each of the four ways to call this76function.777879#. A space curve defined by three functions of 1 variable:8081::8283sage: parametric_plot3d( (sin, cos, lambda u: u/10), (0, 20))8485Note above the lambda function, which creates a callable Python86function that sends `u` to `u/10`.8788#. Next we draw the same plot as above, but using symbolic89functions:9091::9293sage: u = var('u')94sage: parametric_plot3d( (sin(u), cos(u), u/10), (u, 0, 20))9596#. We draw a parametric surface using 3 Python functions (defined97using lambda):9899::100101sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v))102sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi))103104#. The surface, but with a mesh:105106::107108sage: u, v = var('u,v')109sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True)110111#. The same surface, but where the defining functions are112symbolic:113114::115116sage: u, v = var('u,v')117sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi))118119We increase the number of plot points, and make the surface green120and transparent:121122::123124sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), color='green', opacity=0.1, plot_points=[30,30])125126127We call the space curve function but with polynomials instead of128symbolic variables.129130::131132sage: R.<t> = RDF[]133sage: parametric_plot3d( (t, t^2, t^3), (t, 0, 3) )134135Next we plot the same curve, but because we use (0, 3) instead of136(t, 0, 3), each polynomial is viewed as a callable function of one137variable::138139sage: parametric_plot3d( (t, t^2, t^3), (0, 3) )140141We do a plot but mix a symbolic input, and an integer::142143sage: t = var('t')144sage: parametric_plot3d( (1, sin(t), cos(t)), (t, 0, 3) )145146We specify a boundary style to show us the values of the function at its147extrema::148149sage: u, v = var('u,v')150sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, pi), (v, 0, pi), \151... boundary_style={"color": "black", "thickness": 2})152153We can plot vectors::154155sage: x,y=var('x,y')156sage: parametric_plot3d(vector([x-y,x*y,x*cos(y)]), (x,0,2), (y,0,2))157sage: t=var('t')158sage: p=vector([1,2,3])159sage: q=vector([2,-1,2])160sage: parametric_plot3d(p*t+q, (t, 0, 2))161162163Any options you would normally use to specify the appearance of a curve are164valid as entries in the boundary_style dict.165166MANY MORE EXAMPLES:167168We plot two interlinked tori::169170sage: u, v = var('u,v')171sage: f1 = (4+(3+cos(v))*sin(u), 4+(3+cos(v))*cos(u), 4+sin(v))172sage: f2 = (8+(3+cos(v))*cos(u), 3+sin(v), 4+(3+cos(v))*sin(u))173sage: p1 = parametric_plot3d(f1, (u,0,2*pi), (v,0,2*pi), texture="red")174sage: p2 = parametric_plot3d(f2, (u,0,2*pi), (v,0,2*pi), texture="blue")175sage: p1 + p2176177A cylindrical Star of David::178179sage: u,v = var('u v')180sage: f_x = cos(u)*cos(v)*(abs(cos(3*v/4))^500 + abs(sin(3*v/4))^500)^(-1/260)*(abs(cos(4*u/4))^200 + abs(sin(4*u/4))^200)^(-1/200)181sage: f_y = cos(u)*sin(v)*(abs(cos(3*v/4))^500 + abs(sin(3*v/4))^500)^(-1/260)*(abs(cos(4*u/4))^200 + abs(sin(4*u/4))^200)^(-1/200)182sage: f_z = sin(u)*(abs(cos(4*u/4))^200 + abs(sin(4*u/4))^200)^(-1/200)183sage: parametric_plot3d([f_x, f_y, f_z], (u, -pi, pi), (v, 0, 2*pi))184185Double heart::186187sage: u, v = var('u,v')188sage: f_x = ( abs(v) - abs(u) - abs(tanh((1/sqrt(2))*u)/(1/sqrt(2))) + abs(tanh((1/sqrt(2))*v)/(1/sqrt(2))) )*sin(v)189sage: f_y = ( abs(v) - abs(u) - abs(tanh((1/sqrt(2))*u)/(1/sqrt(2))) - abs(tanh((1/sqrt(2))*v)/(1/sqrt(2))) )*cos(v)190sage: f_z = sin(u)*(abs(cos(4*u/4))^1 + abs(sin(4*u/4))^1)^(-1/1)191sage: parametric_plot3d([f_x, f_y, f_z], (u, 0, pi), (v, -pi, pi))192193Heart::194195sage: u, v = var('u,v')196sage: f_x = cos(u)*(4*sqrt(1-v^2)*sin(abs(u))^abs(u))197sage: f_y = sin(u) *(4*sqrt(1-v^2)*sin(abs(u))^abs(u))198sage: f_z = v199sage: parametric_plot3d([f_x, f_y, f_z], (u, -pi, pi), (v, -1, 1), frame=False, color="red")200201Green bowtie::202203sage: u, v = var('u,v')204sage: f_x = sin(u) / (sqrt(2) + sin(v))205sage: f_y = sin(u) / (sqrt(2) + cos(v))206sage: f_z = cos(u) / (1 + sqrt(2))207sage: parametric_plot3d([f_x, f_y, f_z], (u, -pi, pi), (v, -pi, pi), frame=False, color="green")208209Boy's surface http://en.wikipedia.org/wiki/Boy's_surface210211::212213sage: u, v = var('u,v')214sage: fx = 2/3* (cos(u)* cos(2*v) + sqrt(2)* sin(u)* cos(v))* cos(u) / (sqrt(2) - sin(2*u)* sin(3*v))215sage: fy = 2/3* (cos(u)* sin(2*v) - sqrt(2)* sin(u)* sin(v))* cos(u) / (sqrt(2) - sin(2*u)* sin(3*v))216sage: fz = sqrt(2)* cos(u)* cos(u) / (sqrt(2) - sin(2*u)* sin(3*v))217sage: parametric_plot3d([fx, fy, fz], (u, -2*pi, 2*pi), (v, 0, pi), plot_points = [90,90], frame=False, color="orange") # long time -- about 30 seconds218219Maeder's_Owl (pretty but can't find an internet reference)::220221sage: u, v = var('u,v')222sage: fx = v *cos(u) - 0.5* v^2 * cos(2* u)223sage: fy = -v *sin(u) - 0.5* v^2 * sin(2* u)224sage: fz = 4 *v^1.5 * cos(3 *u / 2) / 3225sage: parametric_plot3d([fx, fy, fz], (u, -2*pi, 2*pi), (v, 0, 1),plot_points = [90,90], frame=False, color="purple")226227Bracelet::228229sage: u, v = var('u,v')230sage: fx = (2 + 0.2*sin(2*pi*u))*sin(pi*v)231sage: fy = 0.2*cos(2*pi*u) *3*cos(2*pi*v)232sage: fz = (2 + 0.2*sin(2*pi*u))*cos(pi*v)233sage: parametric_plot3d([fx, fy, fz], (u, 0, pi/2), (v, 0, 3*pi/4), frame=False, color="gray")234235Green goblet236237::238239sage: u, v = var('u,v')240sage: fx = cos(u)*cos(2*v)241sage: fy = sin(u)*cos(2*v)242sage: fz = sin(v)243sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, pi), frame=False, color="green")244245Funny folded surface - with square projection::246247sage: u, v = var('u,v')248sage: fx = cos(u)*sin(2*v)249sage: fy = sin(u)*cos(2*v)250sage: fz = sin(v)251sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="green")252253Surface of revolution of figure 8::254255sage: u, v = var('u,v')256sage: fx = cos(u)*sin(2*v)257sage: fy = sin(u)*sin(2*v)258sage: fz = sin(v)259sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="green")260261Yellow Whitney's umbrella262http://en.wikipedia.org/wiki/Whitney_umbrella::263264sage: u, v = var('u,v')265sage: fx = u*v266sage: fy = u267sage: fz = v^2268sage: parametric_plot3d([fx, fy, fz], (u, -1, 1), (v, -1, 1), frame=False, color="yellow")269270Cross cap http://en.wikipedia.org/wiki/Cross-cap::271272sage: u, v = var('u,v')273sage: fx = (1+cos(v))*cos(u)274sage: fy = (1+cos(v))*sin(u)275sage: fz = -tanh((2/3)*(u-pi))*sin(v)276sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="red")277278Twisted torus::279280sage: u, v = var('u,v')281sage: fx = (3+sin(v)+cos(u))*cos(2*v)282sage: fy = (3+sin(v)+cos(u))*sin(2*v)283sage: fz = sin(u)+2*cos(v)284sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="red")285286Four intersecting discs::287288sage: u, v = var('u,v')289sage: fx = v *cos(u) -0.5*v^2*cos(2*u)290sage: fy = -v*sin(u) -0.5*v^2*sin(2*u)291sage: fz = 4* v^1.5 *cos(3* u / 2) / 3292sage: parametric_plot3d([fx, fy, fz], (u, 0, 4*pi), (v, 0,2*pi), frame=False, color="red", opacity=0.7)293294Steiner surface/Roman's surface (see295http://en.wikipedia.org/wiki/Roman_surface and296http://en.wikipedia.org/wiki/Steiner_surface)::297298sage: u, v = var('u,v')299sage: fx = (sin(2 * u) * cos(v) * cos(v))300sage: fy = (sin(u) * sin(2 * v))301sage: fz = (cos(u) * sin(2 * v))302sage: parametric_plot3d([fx, fy, fz], (u, -pi/2, pi/2), (v, -pi/2,pi/2), frame=False, color="red")303304Klein bottle? (see http://en.wikipedia.org/wiki/Klein_bottle)::305306sage: u, v = var('u,v')307sage: fx = (3*(1+sin(v)) + 2*(1-cos(v)/2)*cos(u))*cos(v)308sage: fy = (4+2*(1-cos(v)/2)*cos(u))*sin(v)309sage: fz = -2*(1-cos(v)/2) * sin(u)310sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="green")311312A Figure 8 embedding of the Klein bottle (see313http://en.wikipedia.org/wiki/Klein_bottle)::314315sage: u, v = var('u,v')316sage: fx = (2 + cos(v/2)* sin(u) - sin(v/2)* sin(2 *u))* cos(v)317sage: fy = (2 + cos(v/2)* sin(u) - sin(v/2)* sin(2 *u))* sin(v)318sage: fz = sin(v/2)* sin(u) + cos(v/2) *sin(2* u)319sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi), frame=False, color="red")320321Enneper's surface (see322http://en.wikipedia.org/wiki/Enneper_surface)::323324sage: u, v = var('u,v')325sage: fx = u -u^3/3 + u*v^2326sage: fy = v -v^3/3 + v*u^2327sage: fz = u^2 - v^2328sage: parametric_plot3d([fx, fy, fz], (u, -2, 2), (v, -2, 2), frame=False, color="red")329330Henneberg's surface (see331http://xahlee.org/surface/gallery_m.html)332333::334335sage: u, v = var('u,v')336sage: fx = 2*sinh(u)*cos(v) -(2/3)*sinh(3*u)*cos(3*v)337sage: fy = 2*sinh(u)*sin(v) +(2/3)*sinh(3*u)*sin(3*v)338sage: fz = 2*cosh(2*u)*cos(2*v)339sage: parametric_plot3d([fx, fy, fz], (u, -1, 1), (v, -pi/2, pi/2), frame=False, color="red")340341Dini's spiral342343::344345sage: u, v = var('u,v')346sage: fx = cos(u)*sin(v)347sage: fy = sin(u)*sin(v)348sage: fz = (cos(v)+log(tan(v/2))) + 0.2*u349sage: parametric_plot3d([fx, fy, fz], (u, 0, 12.4), (v, 0.1, 2),frame=False, color="red")350351Catalan's surface (see352http://xahlee.org/surface/catalan/catalan.html)::353354sage: u, v = var('u,v')355sage: fx = u-sin(u)*cosh(v)356sage: fy = 1-cos(u)*cosh(v)357sage: fz = 4*sin(1/2*u)*sinh(v/2)358sage: parametric_plot3d([fx, fy, fz], (u, -pi, 3*pi), (v, -2, 2), frame=False, color="red")359360A Conchoid::361362sage: u, v = var('u,v')363sage: k = 1.2; k_2 = 1.2; a = 1.5364sage: f = (k^u*(1+cos(v))*cos(u), k^u*(1+cos(v))*sin(u), k^u*sin(v)-a*k_2^u)365sage: parametric_plot3d(f, (u,0,6*pi), (v,0,2*pi), plot_points=[40,40], texture=(0,0.5,0))366367A Mobius strip::368369sage: u,v = var("u,v")370sage: parametric_plot3d([cos(u)*(1+v*cos(u/2)), sin(u)*(1+v*cos(u/2)), 0.2*v*sin(u/2)], (u,0, 4*pi+0.5), (v,0, 0.3),plot_points=[50,50])371372A Twisted Ribbon373374::375376sage: u, v = var('u,v')377sage: parametric_plot3d([3*sin(u)*cos(v), 3*sin(u)*sin(v), cos(v)], (u,0, 2*pi), (v, 0, pi),plot_points=[50,50])378379An Ellipsoid::380381sage: u, v = var('u,v')382sage: parametric_plot3d([3*sin(u)*cos(v), 2*sin(u)*sin(v), cos(u)], (u,0, 2*pi), (v, 0, 2*pi),plot_points=[50,50], aspect_ratio=[1,1,1])383384A Cone::385386sage: u, v = var('u,v')387sage: parametric_plot3d([u*cos(v), u*sin(v), u], (u, -1, 1), (v, 0, 2*pi+0.5), plot_points=[50,50])388389A Paraboloid::390391sage: u, v = var('u,v')392sage: parametric_plot3d([u*cos(v), u*sin(v), u^2], (u, 0, 1), (v, 0, 2*pi+0.4), plot_points=[50,50])393394A Hyperboloid::395396sage: u, v = var('u,v')397sage: plot3d(u^2-v^2, (u, -1, 1), (v, -1, 1), plot_points=[50,50])398399A weird looking surface - like a Mobius band but also an O::400401sage: u, v = var('u,v')402sage: parametric_plot3d([sin(u)*cos(u)*log(u^2)*sin(v), (u^2)^(1/6)*(cos(u)^2)^(1/4)*cos(v), sin(v)], (u, 0.001, 1), (v, -pi, pi+0.2), plot_points=[50,50])403404A heart, but not a cardioid (for my wife)::405406sage: u, v = var('u,v')407sage: p1 = parametric_plot3d([sin(u)*cos(u)*log(u^2)*v*(1-v)/2, ((u^6)^(1/20)*(cos(u)^2)^(1/4)-1/2)*v*(1-v), v^(0.5)], (u, 0.001, 1), (v, 0, 1), plot_points=[70,70], color='red')408sage: p2 = parametric_plot3d([-sin(u)*cos(u)*log(u^2)*v*(1-v)/2, ((u^6)^(1/20)*(cos(u)^2)^(1/4)-1/2)*v*(1-v), v^(0.5)], (u, 0.001, 1), (v, 0, 1), plot_points=[70,70], color='red')409sage: show(p1+p2, frame=False)410411A Hyperhelicoidal::412413sage: u = var("u")414sage: v = var("v")415sage: fx = (sinh(v)*cos(3*u))/(1+cosh(u)*cosh(v))416sage: fy = (sinh(v)*sin(3*u))/(1+cosh(u)*cosh(v))417sage: fz = (cosh(v)*sinh(u))/(1+cosh(u)*cosh(v))418sage: parametric_plot3d([fx, fy, fz], (u, -pi, pi), (v, -pi, pi), plot_points = [50,50], frame=False, color="red")419420A Helicoid (lines through a helix,421http://en.wikipedia.org/wiki/Helix)::422423sage: u, v = var('u,v')424sage: fx = sinh(v)*sin(u)425sage: fy = -sinh(v)*cos(u)426sage: fz = 3*u427sage: parametric_plot3d([fx, fy, fz], (u, -pi, pi), (v, -pi, pi), plot_points = [50,50], frame=False, color="red")428429Kuen's surface430(http://www.math.umd.edu/research/bianchi/Gifccsurfs/ccsurfs.html)::431432sage: fx = (2*(cos(u) + u*sin(u))*sin(v))/(1+ u^2*sin(v)^2)433sage: fy = (2*(sin(u) - u*cos(u))*sin(v))/(1+ u^2*sin(v)^2)434sage: fz = log(tan(1/2 *v)) + (2*cos(v))/(1+ u^2*sin(v)^2)435sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0.01, pi-0.01), plot_points = [50,50], frame=False, color="green")436437A 5-pointed star::438439sage: fx = cos(u)*cos(v)*(abs(cos(1*u/4))^0.5 + abs(sin(1*u/4))^0.5)^(-1/0.3)*(abs(cos(5*v/4))^1.7 + abs(sin(5*v/4))^1.7)^(-1/0.1)440sage: fy = cos(u)*sin(v)*(abs(cos(1*u/4))^0.5 + abs(sin(1*u/4))^0.5)^(-1/0.3)*(abs(cos(5*v/4))^1.7 + abs(sin(5*v/4))^1.7)^(-1/0.1)441sage: fz = sin(u)*(abs(cos(1*u/4))^0.5 + abs(sin(1*u/4))^0.5)^(-1/0.3)442sage: parametric_plot3d([fx, fy, fz], (u, -pi/2, pi/2), (v, 0, 2*pi), plot_points = [50,50], frame=False, color="green")443444A cool self-intersecting surface (Eppener surface?)::445446sage: fx = u - u^3/3 + u*v^2447sage: fy = v - v^3/3 + v*u^2448sage: fz = u^2 - v^2449sage: parametric_plot3d([fx, fy, fz], (u, -25, 25), (v, -25, 25), plot_points = [50,50], frame=False, color="green")450451The breather surface452(http://en.wikipedia.org/wiki/Breather_surface)::453454sage: fx = (2*sqrt(0.84)*cosh(0.4*u)*(-(sqrt(0.84)*cos(v)*cos(sqrt(0.84)*v)) - sin(v)*sin(sqrt(0.84)*v)))/(0.4*((sqrt(0.84)*cosh(0.4*u))^2 + (0.4*sin(sqrt(0.84)*v))^2))455sage: fy = (2*sqrt(0.84)*cosh(0.4*u)*(-(sqrt(0.84)*sin(v)*cos(sqrt(0.84)*v)) + cos(v)*sin(sqrt(0.84)*v)))/(0.4*((sqrt(0.84)*cosh(0.4*u))^2 + (0.4*sin(sqrt(0.84)*v))^2))456sage: fz = -u + (2*0.84*cosh(0.4*u)*sinh(0.4*u))/(0.4*((sqrt(0.84)*cosh(0.4*u))^2 + (0.4*sin(sqrt(0.84)*v))^2))457sage: parametric_plot3d([fx, fy, fz], (u, -13.2, 13.2), (v, -37.4, 37.4), plot_points = [90,90], frame=False, color="green")458459TESTS::460461sage: u, v = var('u,v')462sage: plot3d(u^2-v^2, (u, -1, 1), (u, -1, 1))463Traceback (most recent call last):464...465ValueError: range variables should be distinct, but there are duplicates466467468From Trac #2858::469470sage: parametric_plot3d((u,-u,v), (u,-10,10),(v,-10,10))471sage: f(u)=u; g(v)=v^2; parametric_plot3d((g,f,f), (-10,10),(-10,10))472473From Trac #5368::474475sage: x, y = var('x,y')476sage: plot3d(x*y^2 - sin(x), (x,-1,1), (y,-1,1))477478"""479# TODO:480# * Surface -- behavior of functions not defined everywhere -- see note above481# * Iterative refinement482483484# color_function -- (default: "automatic") how to determine the color of curves and surfaces485# color_function_scaling -- (default: True) whether to scale the input to color_function486# exclusions -- (default: "automatic") u points or (u,v) conditions to exclude.487# (E.g., exclusions could be a function e = lambda u, v: False if u < v else True488# exclusions_style -- (default: None) what to draw at excluded points489# max_recursion -- (default: "automatic") maximum number of recursive subdivisions,490# when ...491# mesh -- (default: "automatic") how many mesh divisions in each direction to draw492# mesh_functions -- (default: "automatic") how to determine the placement of mesh divisions493# mesh_shading -- (default: None) how to shade regions between mesh divisions494# plot_range -- (default: "automatic") range of values to include495496if is_Vector(f):497f = tuple(f)498499if isinstance(f, (list,tuple)) and len(f) > 0 and isinstance(f[0], (list,tuple)):500return sum([parametric_plot3d(v, urange, vrange, plot_points=plot_points, **kwds) for v in f])501502if not isinstance(f, (tuple, list)) or len(f) != 3:503raise ValueError, "f must be a list, tuple, or vector of length 3"504505if vrange is None:506if plot_points == "automatic":507plot_points = 75508G = _parametric_plot3d_curve(f, urange, plot_points=plot_points, **kwds)509else:510if plot_points == "automatic":511plot_points = [40,40]512G = _parametric_plot3d_surface(f, urange, vrange, plot_points=plot_points, boundary_style=boundary_style, **kwds)513G._set_extra_kwds(kwds)514return G515516def _parametric_plot3d_curve(f, urange, plot_points, **kwds):517r"""518Return a parametric three-dimensional space curve.519This function is used internally by the520:func:`parametric_plot3d` command.521522There are two ways this function is invoked by523:func:`parametric_plot3d`.524525- ``parametric_plot3d([f_x, f_y, f_z], (u_min,526u_max))``:527`f_x, f_y, f_z` are three functions and528`u_{\min}` and `u_{\max}` are real numbers529530- ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,531u_max))``:532`f_x, f_y, f_z` can be viewed as functions of533`u`534535INPUT:536537- ``f`` - a 3-tuple of functions or expressions, or vector of size 3538539- ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple540(u, u_min, u_max)541542- ``plot_points`` - (default: "automatic", which is 75) initial543number of sample points in each parameter; an integer.544545EXAMPLES:546547We demonstrate each of the two ways of calling this. See548:func:`parametric_plot3d` for many more examples.549550We do the first one with a lambda function, which creates a551callable Python function that sends `u` to `u/10`::552553sage: parametric_plot3d( (sin, cos, lambda u: u/10), (0, 20)) # indirect doctest554555Now we do the same thing with symbolic expressions::556557sage: u = var('u')558sage: parametric_plot3d( (sin(u), cos(u), u/10), (u, 0, 20))559"""560from sage.plot.misc import setup_for_eval_on_grid561g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)562f_x,f_y,f_z = g563w = [(f_x(u), f_y(u), f_z(u)) for u in xsrange(*ranges[0], include_endpoint=True)]564return line3d(w, **kwds)565566def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds):567r"""568Return a parametric three-dimensional space surface.569This function is used internally by the570:func:`parametric_plot3d` command.571572There are two ways this function is invoked by573:func:`parametric_plot3d`.574575- ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max),576(v_min, v_max))``:577`f_x, f_y, f_z` are each functions of two variables578579- ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,580u_max), (v, v_min, v_max))``:581`f_x, f_y, f_z` can be viewed as functions of582`u` and `v`583584INPUT:585586- ``f`` - a 3-tuple of functions or expressions, or vector of size 3587588- ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple589(u, u_min, u_max)590591- ``vrange`` - a 2-tuple (v_min, v_max) or a 3-tuple592(v, v_min, v_max)593594- ``plot_points`` - (default: "automatic", which is [40,40]595for surfaces) initial number of sample points in each parameter;596a pair of integers.597598- ``boundary_style`` - (default: None, no boundary) a dict that describes599how to draw the boundaries of regions by giving options that are passed600to the line3d command.601602EXAMPLES:603604We demonstrate each of the two ways of calling this. See605:func:`parametric_plot3d` for many more examples.606607We do the first one with lambda functions::608609sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v))610sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) # indirect doctest611612Now we do the same thing with symbolic expressions::613614sage: u, v = var('u,v')615sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True)616"""617from sage.plot.misc import setup_for_eval_on_grid618g, ranges = setup_for_eval_on_grid(f, [urange,vrange], plot_points)619urange = srange(*ranges[0], include_endpoint=True)620vrange = srange(*ranges[1], include_endpoint=True)621G = ParametricSurface(g, (urange, vrange), **kwds)622623if boundary_style is not None:624for u in (urange[0], urange[-1]):625G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style)626for v in (vrange[0], vrange[-1]):627G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style)628return G629630631