Interpolation function rejected by ParametricPlot3D

I was playing around with the bouncing ball example, and decided to make a 3d version.

I decided to use ParametricPlot3D for a simple independent 3D presentation. However, I found that having an interpolating function as the the first element in the list of three functions passed to ParametricPlot3D doesn't work.

ballz = NDSolve[{z''[t] == -9.81, z[0] == 5, z'[0] == 0,
WhenEvent[z[t] == 0.2, z'[t] -> -0.9 z'[t]]}, z, {t, 0, 10}];

bally = NDSolve[{y''[t] == 0, y[0] == -2, y'[0] == 4,
WhenEvent[y[t] == 4.8, y'[t] -> -0.9 y'[t]],
WhenEvent[y[t] == -4.8, y'[t] -> -0.9 y'[t]]}, y, {t, 0, 10}];

Manipulate[
ParametricPlot3D[{t - 2, y[t] /. bally, z[t] /. ballz}, {t, 0, a},
PlotStyle -> {Gray, Dashed, Thick},
PlotRange -> {{-5, 5}, {-5, 5}, {0, 10}}],
{a, 0.025, 10, 0.025}]


The above code works fine, but when I substitute by an interpolation function for the t - 2 term, the function doesn't work. Can this be fixed?

-
While you use the term Contourplot3D in your title and text, your code uses ParametricPlot3D , which is not the same thing. –  m_goldberg Jul 28 '14 at 1:02
I don't see how we can help you without seeing the code you used to build your interpolating function and the real plot code that failed. Posting code that worked and then giving a vague description about changes you made doesn't cut it. –  m_goldberg Jul 28 '14 at 1:18
Corrected the title. The interpolating functions are the ones you get from the NDSolve. So, replacin t-2 with y[t] /. bally doesn't work, but it doesn't work with ANY interpolating function in the first term. –  Feyre Jul 28 '14 at 10:20
It works for me in V10. Exactly what code did not work? –  Michael E2 Jul 28 '14 at 10:28
y[t] /. bally is a list. Use y[t] /. First[bally] to extract the actual interpolating function. –  Simon Woods Jul 28 '14 at 11:02

ParametricPlot3D and ParametricPlot accept a wide range of nested lists of expressions to specify a function or functions to be graphed. Let's discuss ParametricPlot3D. ParametricPlot is similar, with lists of length 2 replacing lists of length 3 where appropriate. There are two types of specifications

List[expr,...]
List[List[...],...]


where expr represents an expression with a head other than List and ... represents expressions possibly nested inside List. Not all inputs will result in a plot, but neither will they result in an error message. My feeling after looking at the plotting examples in the NDSolve documentation is that this flexibility was chosen over a having a more rigorous argument checking, for the convenience of visualization. The output of a simple NDSolve such as in the OP's examples is

List[List[y -> InterpolatingFunction[...]]]


and the result of y[t] /. bally is

List[InterpolatingFunction[...][t]]


so that the y coordinate ends up wrapped in a List. I suppose most people learn to use y[t] /. First[bally] to avoid the extra {}. However, for plotting, it's not strictly necessary.

For each type of input to ParametricPlot3D to produce a plot, it has to satisfy one of the following.

1. In the first case fn = List[expr,...] where expr is not a List, then Flatten[fn] should be a List of three expressions that are functions of the parameter(s) passed to ParametricPlot3D.

2. In the second case, fns = List[list1, list2,...], each of list1, etc. should be a List; and for list1 to produce a curve, Flatten[list1] should be a List of three expressions that are functions of the parameter(s), and so on for the other lists.

Here are a few examples:

ParametricPlot3D[{t, {t^2}, {t^3}}, {t, 0, 1}]            (* works -- OP's case *)
ParametricPlot3D[{{t}, {t^2}, {t^3}}, {t, 0, 1}]          (* fails criterion 2 -- no curve *)
ParametricPlot3D[{{{t}, {t^2}, {t^3}}}, {t, 0, 1}]        (* works -- note {{...}} *)
ParametricPlot3D[{{{t}, {t^2}, {t^3}}, {t^2, {{{t^3}}}, {t}}}, {t, 0, 1}] (* works *)


The OP's example

ParametricPlot3D[{t - 2, y[t] /. bally, z[t] /. ballz}, {t, 0, a}]


meets the criterion 1, just as does the first example above. If ballx was another solution to a similar NDSolve, then

ParametricPlot3D[{x[t] /. ballx, y[t] /. bally, z[t] /. ballz}, {t, 0, a}]


would be of the form of the second example,

ParametricPlot3D[{{x[t]}, {y[t]}, {z[t]}}, {t, 0, a}]


which will not produce a plot. (The input is, probably, interpreted as three 1D parametrizations.) To fix it, one could wrap the NDSolve outputs in First: First[ballx], etc. as @SimonWoods mentions in a comment. Or one could put in extra {} as in the third example above:

ballx = NDSolve[{x'[t] == 1, x[0] == -2}, x, {t, 0, 10}];
ParametricPlot3D[{{x[t] /. ballx, y[t] /. bally, z[t] /. ballz}}, {t, 0, 10}]


-
I had tried the IPF of the y-function in the x-function first, (which didn't work) and thought it was a more generalized issue. Guess I should have been more thorough when I didn't get what the issue was. Regardless, good explanation, I see the issue now, thanks. –  Feyre Jul 29 '14 at 8:33
@Feyre What a coincidence, I tried bally for x at first, too. :) Actually, the issue is not explained in the docs, ASAIK. I didn't really know how extensively forgiving ParametricPlot is of extra {} until I explored your question -- one usually does the simplest thing after all. So thanks for that. –  Michael E2 Jul 29 '14 at 12:54