# Contour Line Parametrization or Interpolation

Is there a way to obtain a parametrization from a level set of a 2D scalar field? Perhaps somehow using some interpolation, for instance?

I have a 2D scalar field, f[x,y,coeff], a Fourier expansion. The 3rd argument is a list of coefficients for the Fourier terms. For instance with a list coeff = {{5,6},{7,8}}, the function is something like 5*sin(x)cos(y) + 6*sin(x)cos(2y) + 7*sin(2x)cos(y) + 8*sin(2x)cos(2y)

• Firstly I need to contour this function, which I can easily accomplish with ContourPlot (see example code and plot below). In the example, the expansion is of the kind {{constant,0},{0,0}}.

• Then, I would like to be able to somehow parameterize the contours for any order of the expansion. In practice up to order 10 would be more than enough, i.e., 10*10 terms). For a very low order, I can solve f[x,y,coeff]==constant for x or y, whichever I can isolate, which is not possible in general.

Ncontours = 10;
cplot = With[{options = {PlotLegends -> Automatic, FrameLabel -> Automatic, ColorFunction -> "ThermometerColors", ImageSize -> {400, 350}}},
ContourPlot[Evaluate[f[x, y, coeff]], {x, -Lx, Lx}, {y, -Ly, Ly}, options,
Contours -> Ncontours]] Actually what I want to do is to somehow define a curve that would connect the level sets. And I thought that I could maybe do it by parameterizing them and then defining a piecewise function including some lines leading from one contour to the other one. Something like this: So in black are the contour lines and in faint red is a very poor sketch of what I am aiming that. To get there, I would need a parametrization of the contour lines (B-C, D-E, F-G), and having those I would define a piecewise parametric function g(t) like a straight line in the pieces connecting A-B, C-D, E-F and G-H; and going around the contours at B-C, D-E and F-G.

• Without the expression for f, or a relevant toy example, this will not get much attention. I also do not understand what you mena by "a curve that would connect the level set". Could you perhaps explain further or, even better, give an example? – MarcoB May 7 '18 at 14:52
• Thanks for the feedback! Let me try to make it clearer: In this case, rounding up the constants, the function is f[x_,y_] := 0.0026*Sin[Pi*(x+0.02)/0.04]*Cos[Pi*(y+0.02)/0.04] The level sets are a series of concentric sort-of-rings. I would like to define some piecewise parametrization g(t) = (g1(t),g2(t)), such that, for instance for t belonging to [0,1.9pi[, this would draw the innermost contour (or almost all of it). Then for [1.9pi,2.1pi[ it would be a curve leading from the innermost contour to the next one. Then, for [2.1pi,3.9pi[ it would draw the 2nd contour, and so on. – miguel May 8 '18 at 7:32
• e.g., I would like to turn the separate contours into a single track going in/outwards. But firstly I need some way to parameterize each contour, and then I'll find some way of joining them. Right now, the only way I have of defining these contours is by using implicit equations such as f(x,y)=constant, which are analytically solvable only in the simplest cases, with very little terms in the expansion, so I am trying to figure out other ways to define the contours. Maybe by defining interpolations of the curve, or some other numerical methods. I'm not sure if it is a little clearer now. – miguel May 8 '18 at 7:47
• Ups, 3rd comment in a row, the previous definition of f was wrong, both functions are sines, sorry about that. The function f is actually: f[x_,y_] := 0.0026*Sin[Pi*(x+0.02)/0.04]*Sin[Pi*(y+0.02)/0.04] – miguel May 8 '18 at 8:52

Maybe something like

ClearAll[joinContours]
joinContours = Module[{cp = #, pr = PlotRange[#], nf, pts,
contours = Cases[Normal@#, Tooltip[tip_, v_] :> v, Infinity]},
Cases[Normal @ cp, Tooltip[tip_, v_] :>
(nf[v] = Nearest[Join @@ Cases[tip, Line[x_] :> x]]),  ∞];
pts = Rest @ FoldList[#2[#][]&, Mean[Transpose @ pr], nf /@ Sort[contours]];
Show[cp,
ListLinePlot[pts, PlotStyle -> Directive[Green, Thickness[.01]]],
ListPlot[List /@ pts,
PlotLegends -> SwatchLegend[Automatic, contours, LegendMarkers -> "Bubble"]]]] &;


Examples:

ClearAll[f1, f2]
SeedRandom
f1[x_, y_] := 100. - (x^2 + y^2 + 10 RandomReal[{-.2, .2}])
f2[x_, y_] := (SeedRandom; Sum[Sin[RandomReal[2, 2].{x, y}], {5}])

cp1 = ContourPlot[f1[x, y], {x, -2 Pi, 2 Pi}, {y, -2 Pi, 2 Pi},
Contours -> 7, ImageSize -> 400, PlotPoints -> 3,
Row[{cp1, joinContours@cp1}, Spacer] cp2 = ContourPlot[Evaluate @ f2[x, y], {x, -Pi/2, Pi/2}, {y, -Pi/2, Pi/2},
Contours -> 7, ImageSize -> 400, • the shape of the f function should have nice symmetries, so the more complicated shapes could be reduced to figuring out the parametrization on a single quadrant, for instance, and then just replicating it over the remaining regions. So far, the non closed curves I have encountered are splitting such regions. For example: f[x_,y_]:=-0.0018*Sin[Pi*(y + 0.02)/0.04]*Sin[Pi*2*(x + 0.02)/0.04]; ContourPlot[f[x, y], {x, -0.02, 0.02}, {y, -0.02, 0.02}, PlotLegends -> Automatic, FrameLabel -> Automatic, ColorFunction -> "ThermometerColors", ImageSize -> 400, Contours -> 11] – miguel May 8 '18 at 21:33