# Parametric differentiable interpolation of a 2D data set

I have a set of data

table = Reverse[{
{0, -947}, {-212, -947}, {-424, -950}, {-635, -963}, {-845, -995}, {-1051, -1044},
{-1248, -1119}, {-1432, -1224}, {-1591,-1365}, {-1715, -1537}, {-1796, -1732},
{-1828, -1942}, {-1810,-2153}, {-1755, -2357}, {-1668, -2551}, {-1556, -2730},
{-1423,-2895}, {-1278, -3050}, {-1126, -3197}, {-973, -3343}, {-803,-3506}
}];


which I need to interpolate with a parametric curve. Endpoints and tangent vectors at them are critical. Trying independent polynomial fits for X and Y leads to a wavy curve which is unacceptable. BSplineFunction of degree around 3 leads to a very good-looking curve:

interp = BSplineFunction[table, SplineDegree -> 3];
Show[ListPlot[table], ParametricPlot[interp[t], {t, 0, 1}], AspectRatio -> 1]


but has a discontinuous derivative (btw: why? help promises that it should be a BSplineFunction of one lesser degree but it's a scary jump-step function if you plot it):

x1[t_?NumericQ] := Module[{val}, val = interp[t]; First@val]
y1[t_?NumericQ] := Module[{val}, val = interp[t]; Last@val]
Plot[Norm[{x1'[t], y1'[t]}], {t, 0, 1}, PlotRange -> All]


I then intend to use these functions in NDSolve, NIntegrate etc., therefore behaviour like above is too bad. What parametric interpolation is better in this case?

-
What are x1 and y1? – VLC Feb 7 '13 at 15:21
@VLC check the x and y in mathematica.stackexchange.com/questions/19229/… – PlatoManiac Feb 7 '13 at 15:41
@PlatoManiac Ah, ok. – VLC Feb 7 '13 at 15:55
By extracting the values from the BSplineFunction and then differentiating, you are taking a finite difference derivative sampled at whatever points Plot feels like using. Try e.g. Plot[Norm[interp'[t]], {t, 0, 1}], which I think you will find much better. – Oleksandr R. Feb 8 '13 at 1:41
You may want to look at this method mathematica.stackexchange.com/a/33262/1364 It works for me. – xslittlegrass May 29 '14 at 20:08

Borrowing the parametrizeCurve[] routine from this answer (it's amazing what searching can do...), you can do this:

tvals = parametrizeCurve[table];
{ft, gt} = Interpolation[Transpose[{tvals, #}], Method -> "Spline"] & /@ Transpose[table];

ParametricPlot[{ft[u], gt[u]}, {u, 0, 1}, Axes -> None, Frame -> True,
Epilog -> {AbsolutePointSize[4], Magenta, Point /@ table}]


Verify the $C^2$ continuity:

{Plot[{ft'[u], gt'[u]}, {u, 0, 1}], Plot[{ft''[u], gt''[u]}, {u, 0, 1}]} // GraphicsRow


-
There turns out to be some substantial wavering at the lower end, so I had to come up with some crazy Fit with basis {1,t,t^2,...,t^6,Exp[0.05 t],Cos[t]} which magically led to incredibly smooth curve with constant-signed curvature. – level1807 Feb 20 '13 at 14:14
All this is so important because of its architectural nature. – level1807 Feb 20 '13 at 14:15

(1) I get a reasonable result interpolating separately.

(2) I don't think your derivatives are doing what you expect.

x1 = Interpolation[table[[All, 1]]];
y1 = Interpolation[table[[All, 2]]];

Show[ListPlot[table], ParametricPlot[{x1[t], y1[t]}, {t, 1, 21}],
AspectRatio -> 1]


Here are those derivatives.

Plot[{x1'[t], y1'[t]}, {t, 0, 21}, PlotRange -> All]


If you raise the InterpolationOrder then those derivative curves get smoother.

-
Problem with Interpolation is that as soon as no points are close to each other, everything seems fine. But if data is not equidistant like this, the curve breaks between close points - something that doesn't happen with BezierFunction for example (though it's not an interpolation at all). – level1807 Feb 8 '13 at 6:30