# 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? Commented May 7, 2018 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. Commented May 8, 2018 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. Commented May 8, 2018 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] Commented May 8, 2018 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[#][[1]]&, 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[1]
f1[x_, y_] := 100. - (x^2 + y^2 + 10 RandomReal[{-.2, .2}])
f2[x_, y_] := (SeedRandom[1]; 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[5]]


cp2 = ContourPlot[Evaluate @ f2[x, y], {x, -Pi/2, Pi/2}, {y, -Pi/2, Pi/2},
Contours -> 7, ImageSize -> 400,
Row[{cp2, joinContours@cp2}, Spacer[5]]


• Thank you for the input! I edited the original post so that it better describes my objective, what I wrote was very unclear. The goal is to arrive at a single continuous curve, going around the contour lines and progressively moving inwards. Commented May 8, 2018 at 17:58
• @miguel, thaks for the clarification. Could you please also add an example on how you want to handle contour lines that are not closed curves?
– kglr
Commented May 8, 2018 at 18:17
• 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] Commented May 8, 2018 at 21:33