# How do I draw lines perpendicular to contour lines on ListPlot3D?

I am plotting the voltage in a pool of water with two electrodes.

I have contour lines on my graph at every volt, but I would like to show the electric field lines which are going to be perpendicular to the contour lines. How can I do that?

-
Have a look at this. It's 2D, so not a duplicate, but related. – Jens Jan 30 '13 at 16:21

What you're asking for could be done, but perpendicular contour lines are not a good way to represent the electric field in a 3D plot of a 2D potential. The electric field (or negative gradient) will be a vector field in the plane, and its field lines will be planar too. The third dimension in your 3d plot is geometrically meaningless because it doesn't have dimension length.

So instead what I'd strongly suggest is to either plot your potential and field in 2D, or plot the electric field as planar vectors attached to the 3D plot of the potential. The latter is what I'm illustrating below, because it's most closely matched to your starting point:

fieldArrow[pos_, field_, scale_] := {Hue[Norm[field]],
Arrowheads[.02], Arrow[Tube[{{pos, pos + scale field}}]]};

grid = Table[{x, y}, {y, 0, 10, .5}, {x, 0, 10, .5}];

gridData =
Table[Sin[y/10] ArcTan[x - 5], {y, 0, 10, .5}, {x, 0, 10, .5}];

fieldX = -DerivativeFilter[gridData, {0, 1},
InterpolationOrder -> 3];
fieldY = -DerivativeFilter[gridData, {1, 0},
InterpolationOrder -> 3];
data3D = MapThread[Append[#1, #2] &, {grid, gridData}, 2];

vectorField =
fieldArrow[Append[#1, #2], {#3, #4, 0}, 3] &, {grid, gridData,
fieldX, fieldY}, 2];

arrows = Graphics3D[vectorField];

Show[ListPlot3D[Flatten[data3D, 1], MeshFunctions -> (#3 &)], arrows]


Here, I take the gradient of a made-up potential given as data, by using GradientFilter. Then I make arrows out of the field vectors and superimpose them on your original plot with Show.

It's up to you to style the arrows differently - I colored them by the field strength and scaled them by a parameter scale in the function fieldArrow. You may also want to shrink the arrowheads proportionally to the arrow length. But I left that out so you can see the smaller arrows better.

-

One can do what you ask, but you might prefer to follow the advice of @Jens. Here's how, anyway. First, I made up some data for a similar potential function.

data = Table[10 + (3 ((20 - j)^2 - (j + 5)^2))/(75 + (i - 10)^2 + 2 (j - 10)^2),
{j, 0, 20}, {i, 0, 20}];
f = ListInterpolation[data, {{0, 20}, {0, 20}}];


Then we combine a plot of the potential and a stream plot of the negative gradient field, mapping the streamlines onto the graph of the potential (edited).

pot = Plot3D[f[x, y], {x, 0, 20}, {y, 0, 20}, MeshFunctions -> {#3 &},
Mesh -> 14, FaceGrids -> All];
vf = StreamPlot[Evaluate[-D[f[x, y], {{x, y}}]], {x, 0, 20}, {y, 0, 20},
StreamStyle -> "Line"];
Show[pot,
Graphics3D[vf[[1]] /. {{x_Real, y_Real} :> {x, y, f[x, y]}}]
]


An alternative presentation might be the graph of the potential alongside a combined plot of the contours/gradient paths.

vf = StreamPlot[Evaluate[-D[f[x, y], {{x, y}}]], {x, 0, 20}, {y, 0, 20},
StreamStyle -> ColorData[1][3]];
cp = Show[ContourPlot[f[x, y], {x, 0, 20}, {y, 0, 20}, Contours -> 14], vf];
Row[{Show[pot, ImageSize -> 300], Show[cp, ImageSize -> 250]}]


-
It does look nice, though (+1). – Jens Jan 31 '13 at 4:48
+1 btw maybe an option of StreamStyle -> "Line" would make it more accordant with what OP asked for lines. – Silvia Feb 1 '13 at 15:49
@Silvia Thanks. I'd forgotten about such options and had to replace Arrow by Line. It's simpler now (in the edit), although I kept the arrows for the plane contour plot. Maybe someday Mathematica will have an option Mesh -> "Gradient" :) – Michael E2 Feb 2 '13 at 16:59