f1[x_] = a1 + b1*x + c1*x^2 + d1*x^3;
f2[x_] = a2 + b2*x + c2*x^2 + d2*x^3;
s = Solve[{f1 @ dat[[1,1]] == dat[[1,2]],
f1 @ dat[[2,1]] == dat[[2,2]],
f2 @ dat[[2,1]] == dat[[2,2]],
f2 @ dat[[3,1]] == dat[[3,2]],
f1' @ dat[[2,1]] == f2' @ dat[[2,1]],
f1'' @ dat[[2,1]] == f2'' @ dat[[2,1]],
f1'' @ dat[[1,1]] == 0,
f2'' @ dat[[3,1]] == 0},
{a1, b1, c1, d1, a2, b2, c2, d2}]
(* {{a1 -> 0.438903, b1 -> -2.46492, c1 -> 0.221098, d1 -> 2.97775,
a2 -> 0.603324, b2 -> -3.93762, c2 -> 4.61804, d2 -> -1.39813}} *)
f[x_] = Piecewise[{{f1[x], x ≤ dat[[2, 1]]}}, f2[x]] /. s;
Plot[f[x], {x, dat[[1, 1]], dat[[3, 1]]}, Frame -> True, Axes -> None,
Prolog -> {PointSize[.02], Point /@ dat}]
EDIT, Re the comment by @george2079 -- SplineFit
uses the same algebra that I used, but instead of fitting y
to x
, which is what I did, it fits x
and y
separately to their (zero-based) indices, Range[0, Length @ dat - 1]
.
( spline = SplineFit[dat, Cubic] ) // InputForm
gives the following, which I have formatted, rounded, and annotated:
SplineFunction[Cubic,
{0., 2.}, (* index range *)
{{-0.02475, 0.5 }, (* x[[1]], y[[1]] *)
{ 0.3349375, -0.25}, (* x[[2]], y[[2]] *)
{ 1.101, 0 }}, (* x[[3]], y[[3]] *)
{{{-0.02475, 0.25809375, 0., 0.10159375}, (* coeffs for fitting x[[{1,2}]] *)
{ 0.5, -1., 0., 0.25 }}, (* " " " y[[{1,2}]] *)
{{ 0.3349375, 0.562875, 0.30478125, -0.10159375}, (* " " x[[{2,3}]] *)
{-0.25, -0.25, 0.75, -0.25 }} (* " " y[[{2,3}]] *) }]
There are two splines implicit in the above:
X[u_] = Piecewise[{{-.02475 + .25809375 u + .10159375 u^3, 0 ≤ u ≤ 1},
{.3349375 + .562875 (u-1) + .30478125 (u-1)^2 - .10159375 (u-1)^3, 1 < u ≤ 2}}];
Y[u_] = Piecewise[{{.5 - u + .25 u^3, 0 ≤ u ≤ 1},
{-.25 - .25 (u-1) + .75 (u-1)^2 - .25 (u-1)^3, 1 < u ≤ 2}}];
Note that u
is shifted so that the argument of the polynomial is always in $[0,1]$.
In the following, changing spline[u]
to {X[u], Y[u]}
does not change the plot:
ParametricPlot[spline[u],{u, 0, 2}, Frame -> True, Axes -> None,
AspectRatio -> Automatic, Prolog -> {PointSize[.02],Point /@ dat}]