# Plotting perpendicular lines to a contour plot (electric field from equipotential curves)

I'm currently working on a experiment about Electric Fields and Equipotential Curves. The problem is that I want to plot (estimate) the curves of electric field using the fact that every one of these curves must be perpendicular to equipotential ones.

To make it short, I have values (V) in a plane, and everywhere there's the same value of V, I have to conect these points and get a curve. The problem is that these V values are experimental, so they aren't exactly the same, but I can get a relation with a contour plot:

ListContourPlot[Data, InterpolationOrder -> 7,
PlotLegends -> Automatic, PlotRange -> All]


where Data is an array with 15x8 intensity V values:

Data = {{3.3, 2.97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.8, 4.2}, {3.85, 3.65,
3.76, 3.41, 3.31, 3.33, 3.35, 3.3, 3.38, 3.44, 3.6, 3.65, 4., 4.2,
4.45}, {4.48, 4.35, 4.45, 4.28, 4.22, 4.25, 4.31, 4.3, 4.32, 4.37,
4.45, 4.46, 4.6, 4.67, 4.76}, {5.08, 5.09, 5.17, 5.25, 5.23, 5.27,
5.27, 5.28, 5.3, 5.3, 5.35, 5.3, 5.27, 5.23, 5.22}, {5.75, 5.85,
5.25, 6.18, 6.31, 6.30, 6.45, 6.44, 6.65, 6.62, 6.52, 6.41, 6.17,
6.02, 5.86}, {7.5, 7.22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.33,
6.22}, {6.56, 6.74, 7.01, 7.28, 7.41, 7.52, 7.52, 7.53, 7.51, 7.45,
7.36, 7.22, 6.95, 6.63, 6.5}, {6.9, 7.03, 7.08, 7.22, 7.3, 7.32,
7.35, 7.34, 7.29, 7.23, 7.18, 7.12, 7.0, 6.84, 6.7}}


Before anyone wonders why, I've used an Interpolation because the data is not enough to create curved shapes, and from theory I know that these lines aren't usually straight lines.

The problem is: I need to get the perpendicular vector plot of this contourplot, or parametrize the contour curves to apply a gradient relation (E=-grad(V)).

What could I do? Any suggestions? I'm adding pictures of the result I got and what I want it to be, for this same specific configuration (2 parallel charged plates).

(1) Use Interpolation to get an interpolating function intF.

intF = Interpolation[Flatten[MapIndexed[{#2, #} &, Transpose@data, {2}], 1],
InterpolationOrder -> 7];


(2) Use intF to get a ContourPlot and a StreamPlot (using the approach from this answer by Michael E2 and combine the two plots with Show:

cp = ContourPlot[intF[x, y], {x, 1, 15}, {y, 1, 8},
Contours -> Range[0, 7], AspectRatio -> Automatic, ImageSize -> Large];

sp = StreamPlot[Evaluate[-D[intF[x, y], {{x, y}}]], {x, 1, 15}, {y, 1, 8},
StreamScale -> None,
StreamStyle -> {"Arrow", Directive[Thick, Red]},
StreamPoints -> Fine, AspectRatio -> Automatic];

Show[cp, sp]


• This is exactly what I was looking for. Thanks! Do you think there's any way to limit the interpolation in the vecinity of the electrode planes? I mean, the program is interpretating there's a wider area with low Voltage (blue) than actually is. Is there any way to get thin bars ?
– nuwe
Aug 28 '19 at 16:48
• @StefanQuandt, you can play with the values a and b InterpolationOrder ->{a,b}. Also you can replace Range[0, 7] in Contours option setting with a list which is more finely divided in areas of interest.
– kglr
Aug 28 '19 at 20:32

Due to @kgir 's response, I made it to get very decent results. I'd like to share it with you, in any case there's someone trying to do the same.

intF = Interpolation[
Flatten[MapIndexed[{#2, #} &, Transpose@data1, {2}], 1],
InterpolationOrder -> {1, 1}];
cp = ContourPlot[intF[x, y], {x, 1, 15}, {y, 0.9, 8},
Contours -> Range[0.1, 12], AspectRatio -> Automatic,
ImageSize -> Medium, PlotLegends -> {Automatic}];

sp = StreamPlot[
Evaluate[-D[intF[x, y], {{x, y}}]], {x, 1, 15}, {y, 1.5, 8} ,
StreamScale -> Coarse,
StreamStyle -> {"Arrow", Directive[Thin, Blue]},
StreamPoints -> Fine, AspectRatio -> Automatic,
VectorScale -> Automatic];
vp := VectorPlot[
Evaluate[-D[intF[x, y], {{x, y}}]], {x, 1, 15}, {y, 1.5, 5.9},
VectorScale -> Automatic, AspectRatio -> Automatic,
VectorStyle -> {LightGreen}, VectorPoints -> 15]
vp2 := VectorPlot[
Evaluate[-D[intF[x, y], {{x, y}}]], {x, 1, 15}, {y, 6.1, 8},
VectorScale -> Automatic, AspectRatio -> Automatic,
VectorStyle -> {LightGreen}, VectorPoints -> 15]
sp2 = MapAt[{Opacity[0.25], #} &, sp, 1];
Show[cp, vp, vp2, sp2]}

Show[%169, ImageSize -> Large, FrameLabel -> {"Posición en eje x (cm)",
HoldForm["Posición en eje y (cm)"], "", "valores de Voltaje (V)"}, Ticks ->
Automatic,FrameStyle -> Directive[Black, Thickness[Medium]],
LabelStyle -> {FontFamily->"Arial", 16, GrayLevel[0]}]


Results in: