8

I have produced a set of points in a variable of the type {{x1, y1}, z1},{{x2, y2}, z2}, ,... }, where {x, y} should be the arguments of the function and z is the associated value. What I need to obtain is the continuous function in order to generate z for any value of {x, y} in the domain implicit in the data.

As I understand it, a good way to do this would be to use a 2D Spline. At first I had an unstructured grid, but with the help of the community, now I've produced a grid and values of this form (the real list has been "thinned"):

{{{0.11, 0.1}, 0.621687}, {{0.11, 0.3}, 0.674455}, {{0.11, 0.5}, 0.743462}, 
 {{0.11, 0.7}, 0.803179}, {{0.11, 0.9}, 0.843444}, {{0.11, 1.1}, 0.866607}, 
 {{0.11, 1.3}, 0.881172}, {{0.11, 1.5}, 0.890488}, {{0.11, 1.7}, 0.896887}, 
 {{0.11, 1.9}, 0.901538}, {{0.11, 2.1}, 0.905067}, {{0.11, 2.3}, 0.907836}, 
 {{0.11, 2.5}, 0.910066}, {{0.11, 2.7}, 0.911902}, {{0.11, 2.9}, 0.913404},
 (*==============delimiter==================*) 
 {{0.15, 0.1}, 0.15}, {{0.15, 0.3}, 0.15}, {{0.15, 0.5}, 0.15}, 
 {{0.15,0.7}, 0.414754}, {{0.15, 0.9}, 0.648793}, {{0.15, 1.1}, 0.768185}, 
 {{0.15, 1.3}, 0.832127}, {{0.15, 1.5}, 0.862517}, {{0.15, 1.7}, 0.879246}, 
 {{0.15, 1.9}, 0.889989}, {{0.15, 2.1}, 0.897541}, {{0.15, 2.3}, 0.90316}, 
 {{0.15, 2.5}, 0.907512}, {{0.15, 2.7}, 0.910985}, {{0.15, 2.9}, 0.913761},
 (*==============delimiter==================*) 
 {{0.19, 0.1}, 0.19}, {{0.19, 0.3}, 0.19}, {{0.19, 0.5}, 0.19},
 {{0.19,0.7}, 0.19}, {{0.19, 0.9}, 0.402054}, {{0.19, 1.1}, 0.658819}, 
 {{0.19, 1.3}, 0.81877}, {{0.19, 1.5}, 0.871256}, {{0.19, 1.7}, 0.88874}, 
 {{0.19, 1.9}, 0.898598}, {{0.19, 2.1}, 0.905459}, {{0.19, 2.3}, 0.910567}, 
 {{0.19, 2.5}, 0.914527}, {{0.19, 2.7}, 0.917694}, {{0.19, 2.9}, 0.920228}}

Further, I use:

fspl = Interpolation[Xac, Method -> "Spline", InterpolationOrder -> 2]

and obtain, in principle, satisfying results if I could get the expression for the spline (for use outside Mathematica). Searching on stackexchange shows that people have had similar problems, but I found no evident solution. I tried to use fspl["Methods"], but the list it returns does not seem to be really helpful.

xyz
  • 605
  • 4
  • 38
  • 117
user14679
  • 81
  • 2
  • Look up Interpolation[]. – J. M.'s missing motivation Mar 15 '16 at 13:00
  • After I've transformed the data to {{x1,y1},z1},{{x2,y2},z2},... and use Interpolation I get the error "There are duplicated abscissa points in"... But I intend to have duplicate x or y values... – user14679 Mar 15 '16 at 13:37
  • 2
    @user14679 - but it wouldn't make sense for there to be exactly duplicated {x, y} pairs with different z values. Also, Interpolation will not give you the form of the interpolating function, it will just allow you to get values in between your grid points. To actually get the spline function is a nontrivial task. – Jason B. Mar 15 '16 at 14:03
  • Oh, but my real aim is to get the spline function expression, because I will further use it out of Mathematica. – user14679 Mar 15 '16 at 14:06
  • And I don't seem to have exactly equal {x,y} values, they are equal only separately... – user14679 Mar 15 '16 at 14:09
  • 1
    You do have equal ${x,y}$ pairs. With the above data assigned to dat then Select[# > 1 &]@Counts[Most /@ dat] selects one such duplicate pair. – Edmund Mar 15 '16 at 14:23
  • perhaps that was fixed in editing, but I don't see any dups. @user14697 I'd suggest you post an example dataset that is small enough to include in its entirety. – george2079 Mar 16 '16 at 17:25
  • Thank you, yes, the dups where removed, as you advise, I've edited the post, adding real, but thinned, data. – user14679 Mar 16 '16 at 18:01
  • fspl["InterpolationMethod"] (* BSpline *). I think the question is essentially how to get the control points for the b-spline surface. Unfortunately I don't know. – george2079 Mar 16 '16 at 18:20
  • @george2079 Please see my answer for solving the control points of the B-spline surface.-:) – xyz Mar 18 '16 at 07:47

1 Answers1

10

I have done this before in some previous spline-related threads, but here it is again:

fspl = Interpolation[Xac, Method -> "Spline", InterpolationOrder -> 2];

fb = First[Cases[fspl, _BSplineFunction, ∞]];
{sd, scpts, sk} = fb /@ {"Degree", "ControlPoints", "Knots"};

(* explicitly constructed B-spline surface *)
ip[x_, y_] = Fold[#2.#1 &, scpts, 
                  MapThread[Table[BSplineBasis[{#1, #2}, k - 1, #3], {k, #4}] &,
                            {sd, sk, {x, y}, Dimensions[scpts]}]];

Compare:

{fspl[0.16, 2.3], ip[0.16, 2.3]}
   {0.9038789687499998, 0.90387896875}
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574