# How to speed up drawing a tangent plane?

I have this code to produce an interactive visualization of a tangent plane to a function:

Clear[f]
f[x_, y_] := x^3 + 2*y^3
Manipulate[
Show[
Plot3D[f[x, y], {x, -1, 1}, {y, -1, 1}, PlotStyle -> Opacity[0.8]],
Plot3D[f[point[[1]], point[[2]]] +
Limit[(f[point[[1]] + h, point[[2]]] - f[point[[1]], point[[2]]])/
h, h -> 0]*(x - point[[1]]) +
Limit[(f[point[[1]], point[[2]] + h] - f[point[[1]], point[[2]]])/
h, h -> 0]*(y - point[[2]]), {x, -1, 1}, {y, -1, 1},
PlotStyle -> Opacity[0.8], MeshStyle -> Gray]],
{{point, {0, 0}}, {-1, -1}, {1, 1}},
SaveDefinitions -> True]


It is, however, extremely slow. I suspect that the reason is that I unnecessarily compute the partial derivatives over and over again inside the second Plot3D, so my question is: how to change it?

Note: I am using the above code also for other functions as discussed here, and that is the reason for the Limit in computation of partial derivatives.

-

Simply move the derivative computation outside the scope of the Manipulate, using either D or Limit.

f[x_, y_] = x^3 + 2 y^3;
fx[x_, y_] = D[f[x, y], x];
fx[x_, y_] = Limit[(f[x + h, y] - f[x, y])/h, h -> 0];
fy[x_, y_] = D[f[x, y], y];
fy[x_, y_] = Limit[(f[x, y + h] - f[x, y])/h, h -> 0]
Manipulate[
x0 = p[[1]]; y0 = p[[2]];
Show[{
Plot3D[{f[x, y],
f[x0, y0] + fx[x0, y0] (x - x0) + fy[x0, y0] (y - y0)},
{x, -2, 2}, {y, -2, 2}, BoxRatios -> {1, 1, 1},
PlotRange -> {{-2, 2}, {-2, 2}, {-25, 25}},
PlotStyle -> {Directive[Opacity[0.6]],
Directive[Orange, Opacity[0.6]]},
ViewPoint -> {2.5, -2, 1}, ClippingStyle -> None],
Graphics3D[{PointSize[Large],
Point[{p[[1]], p[[2]], f[p[[1]], p[[2]]]}]}]
}],
{{p, {1, 1}}, {-1, -1}, {2, 2}}]

-
Interesting. Why do you provide two rules for fx[x_,y_]? –  mbork Sep 29 '12 at 19:36
@mbork Either definition works, although the second clearly overwrites the first. I was simply trying to emphasize the fact that you can use either the built in D operator or the Limit definition, as you indicated that you might need to. –  Mark McClure Sep 29 '12 at 19:40
OK, thanks. For the moment I thought that somehow the Limit one is chosen if the D doesn't work (e.g., when the function is given by a separate rule for one point). And thanks for the nicety - the large point! (I did it using a one-element list in ListPointPlot3D, definitely less elegant.) –  mbork Sep 29 '12 at 19:42
@mbork you could also show the Points using Epilog –  Simon Sep 30 '12 at 2:07
@Simon Epilog is really for 2D graphics. From the documentation: "In three-dimensional graphics, two-dimensional graphics primitives can be specified by the Epilog option. The graphics primitives are rendered in a 0,1 coordinate system." - Hence, the Show[{Plot3D[__], Graphics3D[__]}] construct. –  Mark McClure Sep 30 '12 at 2:38

The limits can be calculated analytically one time and then used inside your Manipulate. You can use With to place the final expression where you need them:

f[x_, y_] := x^3 + 2*y^3;
With[{l1 = Limit[(f[px + h, py] - f[px, py])/h, h -> 0],
l2 = Limit[(f[px, py + h] - f[px, py])/h, h -> 0]},
Manipulate[
{px, py} = point;
Show[Plot3D[f[x, y], {x, -1, 1}, {y, -1, 1},
PlotStyle -> Opacity[0.8]],
Plot3D[f[point[[1]], point[[2]]] + l1*(x - point[[1]]) +
l2*(y - point[[2]]), {x, -1, 1}, {y, -1, 1},
PlotStyle -> Opacity[0.8],
MeshStyle -> Gray]], {{point, {0, 0}}, {-1, -1}, {1, 1}},
SaveDefinitions -> True]
]

-
Thanks! I just discovered With myself, too, but I've put it inside Show; I guess this doesn't make much difference. –  mbork Sep 29 '12 at 19:36