
(*:Version: Mathematica 2.0 *)

(*:Name: Graphics`ParametricPlot3D *)

(*:Title: Parametric Plots of 3D Objects *)

(*:Author:
	Roman E. Maeder
*)

(*:Keywords:
	Parametric, Spherical, Cylindrical Plot, 3D
*)

(*:Requirements: none. *)

(*:Warnings: none. *)

(*:Sources:
	Roman E. Maeder: Programming in Mathematica, 2nd Ed.,
	Addison-Wesley, 1991.
*)

(*:Summary:
*)


BeginPackage["Graphics`ParametricPlot3D`"]

ParametricPlot3D::usage = StringJoin[ ParametricPlot3D::usage, 
	" ParametricPlot3D[{x,y,z,(style)}, {u,u0,u1,du}, ({v,v0,v1,dv})]
	uses increments du and dv instead of the PlotPoints option." ]

PointParametricPlot3D::usage =
	"PointParametricPlot3D[{x,y,z}, {u,u0,u1,(du)}, (options..)]
	plots a one-parameter set of points in space.
	PointParametricPlot3D[{x,y,z}, {u,u0,u1,(du)}, {v,v0,v1,(dv)}, (options..)]
	plots a two-parameter set of points in space. Options are passed to Show[]."

SphericalPlot3D::usage = "SphericalPlot3D[r, {theta-range}, {phi-range}, (options...)]
	plots r as a function of the angles theta and phi.
	SphericalPlot3D[{r, style}, ...] uses style to render each surface patch"

CylindricalPlot3D::usage = "CylindricalPlot3D[z, {r-range}, {phi-range}, (options...)]
	plots z as a function of r and phi.
	CylindricalPlot3D[{z, style},  ...] uses style to render each surface patch"

Begin["`Private`"]

protected = Unprotect[ParametricPlot3D]

FilterOptions[ command_Symbol, opts___ ] :=
	Module[{keywords = First /@ Options[command]},
		Sequence @@ Select[ {opts}, MemberQ[keywords, First[#]]& ]
	]

(* overload ParametricPlot3D to allow increments in iterators *)

ParametricPlot3D[ fun_,
	{u_, u0_, u1_, du_:Automatic}, {v_, v0_, v1_, dv_:Automatic}, opts___ ] :=
	Module[{plotpoints},
		plotpoints = PlotPoints /. {opts} /. Options[ParametricPlot3D];
		If[ Head[plotpoints] =!= List, plotpoints = {plotpoints, plotpoints} ];
		If[ du =!= Automatic, plotpoints[[1]] = Round[N[(u1-u0)/du]] + 1 ];
		If[ dv =!= Automatic, plotpoints[[2]] = Round[N[(v1-v0)/dv]] + 1 ];
		ParametricPlot3D[ fun, {u, u0, u1}, {v, v0, v1},
			PlotPoints -> plotpoints, opts]
	]  /; du =!= Automatic || dv =!= Automatic

ParametricPlot3D[ fun_, {u_, u0_, u1_, du_}, opts___ ] :=
	ParametricPlot3D[ fun, {u, u0, u1}, PlotPoints -> Round[N[(u1-u0)/du]] + 1, opts]


Attributes[PointParametricPlot3D] = {HoldFirst}

PointParametricPlot3D[ fun_,
		{u_, u0_, u1_, du_:Automatic}, {v_, v0_, v1_, dv_:Automatic}, opts___ ] :=
	Module[{plotpoints, ndu = N[du], ndv = N[dv]},
		plotpoints = PlotPoints /. {opts} /. Options[ParametricPlot3D];
		If[ plotpoints === Automatic, plotpoints = 15];
		If[ Head[plotpoints] =!= List, plotpoints = {plotpoints, plotpoints} ];
		If[ du === Automatic, ndu = N[(u1-u0)/(plotpoints[[1]]-1)] ];
		If[ dv === Automatic, ndv = N[(v1-v0)/(plotpoints[[2]]-1)] ];
		Show[ Graphics3D[Table[ Point[N[fun]], {u, u0, u1, ndu}, {v, v0, v1, ndv} ]],
		      FilterOptions[Graphics3D, opts] ]
	]  /; NumberQ[N[u0]] && NumberQ[N[u1]] && NumberQ[N[v0]] && NumberQ[N[v1]]


(* point space curve *)

PointParametricPlot3D[ fun_, ul:{_, u0_, u1_, du_}, opts___ ] :=
	Show[ Graphics3D[Table[ Point[N[fun]], ul ]], FilterOptions[Graphics3D, opts] ] /;
			NumberQ[N[u0]] && NumberQ[N[u1]] && NumberQ[N[du]]

PointParametricPlot3D[ fun_, {u_, u0_, u1_}, opts___ ] :=
    Module[{plotpoints},
    	plotpoints = PlotPoints /. {opts} /. Options[ParametricPlot3D];
    	If[ Head[plotpoints] == List, plotpoints = plotpoints[[1]] ];
	PointSpaceCurve[ fun, {u, u0, u1, (u1-u0)/(plotpoints-1)}, opts ]
    ]


Attributes[SphericalPlot3D] = {HoldFirst}

SphericalPlot3D[ {r_, style_}, tlist:{theta_, __}, plist:{phi_, __}, opts___ ] :=
	Module[{rs},
		ParametricPlot3D[ {(rs = r) Sin[theta] Cos[phi],
		                   rs Sin[theta] Sin[phi],
		                   rs Cos[theta],
		                   style},
		                  tlist, plist, opts ]
	]

SphericalPlot3D[ r_, tlist:{theta_, __}, plist:{phi_, __}, opts___ ] :=
      ParametricPlot3D[ r{Sin[theta] Cos[phi],
                          Sin[theta] Sin[phi],
                          Cos[theta]},
                        tlist, plist, opts ]


Attributes[CylindricalPlot3D] = {HoldFirst}

CylindricalPlot3D[ {z_, style_}, rlist:{r_, __}, plist:{phi_, __}, opts___ ] :=
	ParametricPlot3D[{r Cos[phi], r Sin[phi], z, style}, rlist, plist, opts]

CylindricalPlot3D[ z_, rlist:{r_, __}, plist:{phi_, __}, opts___ ] :=
	ParametricPlot3D[{r Cos[phi], r Sin[phi], z}, rlist, plist, opts]

Protect[ Evaluate[protected] ]

End[]   (* Graphics`ParametricPlot3D`Private` *)

Protect[PointParametricPlot3D, SphericalPlot3D, CylindricalPlot3D]

EndPackage[]   (* Graphics`ParametricPlot3D` *)

(*:Limitations: none known. *)
