2

私は実際に 3 次スプライン補間のコードを書こうとしています。3 次スプラインは一連のn-1セグメントに要約されます。ここnで、 は最初に指定された元の座標の数であり、セグメントはそれぞれ何らかの 3 次関数によって表されます。

vector に格納されている各セグメントのすべての係数と値を取得する方法を理解しましたがa,b,c,d、関数を区分関数として異なる間隔でプロットする方法がわかりません。これまでの私のコードは次のとおりです。最後の for ループは、各セグメントをプロットしようとした場所です。

%initializations
x = [1 1.3 1.9 2.1 2.6 3.0 3.9 4.4 4.7 5.0 6 7 8 9.2 10.5 11.3 11.6 12 12.6 13 13.3].';
y = [1.3 1.5 1.85 2.1 2.6 2.7 2.4 2.15 2.05 2.1 2.25 2.3 2.25 1.95 1.4 0.9 0.7 0.6 0.5 0.4 0.25].';

%n is the amount of coordinates
n = length(x);
%solving for a-d for all n-1 segments
a = zeros(n,1);
b = zeros(n,1);
d = zeros(n,1);

%%%%%%%%%%%%%% SOLVE FOR a's %%%%%%%%%%%%%
%Condition (b) in Definition 3.10 on pg 146
%Sj(xj) = f(xj) aka yj
for j = 1: n
    a(j) = y(j);
end

%initialize hj
h = zeros(n-1,1);

for j = 1: n-1
    h(j) = x(j+1) - x(j);
end

A = zeros(n,n);
bv = zeros(n,1); %bv = b vector

%initialize corners to 1
A(1,1) = 1;
A(n,n) = 1;

%set main diagonal
for k = 2: n-1
    A(k,k) = 2*(h(k-1) + h(k));
end

%set upper and then lower diagonals
for k = 2 : n-1
    A(k,k+1) = h(k); %h2, h3, h4...hn-1
    A(k,k-1) = h(k-1); %h1, h2, h3...hn
end

%fill up the b vector using equation in notes
%first and last spots are 0
for j = 2 : n-1
    bv(j) = 3*(((a(j+1)-a(j)) / h(j)) - ((a(j) - a(j-1)) / h(j-1)));
end

%augmented matrix
A = [A bv];



%%%%%%%%%%%% BEGIN GAUSSIAN ELIMINATION %%%%%%%%%%%%%%%
offset = 1;
%will only need n-1 iterations since "first" pivot row is unchanged
for k = 1: n-1
  %Searching from row p to row n for non-zero pivot
  for p = k : n
      if A(p,k) ~= 0;
          break;
      end
  end

  %row swapping using temp variable
  if p ~= k
      temp = A(p,:);
      A(p,:) = A(k,:);
      A(k,:) = temp;
  end


  %Eliminations to create Upper Triangular Form
  for j = k+1:n
     A(j,offset:n+1) = A(j,offset:n+1) - ((A(k, offset:n+1) * A(j,k)) / A(k,k));
  end
  offset = offset + 1;
end

c = zeros(n,1); %initializes vector of data of n rows, 1 column

%Backward Subsitution
%First, solve the nth equation
c(n) = A(n,n+1) / A(n,n);

%%%%%%%%%%%%%%%%% SOLVE FOR C's %%%%%%%%%%%%%%%%%%
%now solve the n-1 : 1 equations (the rest of them going backwards
for j = n-1:-1:1 %-1 means decrement
    c(j) = A(j,n+1);
    for k = j+1:n
        c(j) = c(j) - A(j,k)*c(k); 
    end
    c(j) = c(j)/A(j,j);
end

%%%%%%%%%%%%% SOLVE FOR B's and D's %%%%%%%%%%%%%%%%%%%%
for j = n-1 : -1 : 1
    b(j) = ((a(j+1)-a(j)) / h(j)) - (h(j)*(2*c(j) + c(j+1)) / 3);
    d(j) = (c(j+1) - c(j)) / 3*h(j);
end

%series of equation segments

for j = 1 : n-1
    f = @(x) a(j) + b(j)*(x-x(j)) + c(j)*(x-x(j))^2 + d(j)*(x-x(j))^3;
end
plot(x,y,'o');

a,b,c,d各セグメントのベクトルを正しく計算したと仮定しましょう。単一のプロットにすべてのグラフが表示されるように、各立方体セグメントをプロットするにはどうすればよいですか?

助けてくれてありがとう。

4

1 に答える 1

2

それはとても簡単です。各間隔の間の 3 次スプライン用の無名関数を定義することで、作業の半分は既に完了しています。ただし、関数内の操作が要素単位であることを確認する必要があります。現在、スカラーで操作しているか、行列演算を使用していると仮定しています。そうしないでください。.*の代わりに*との.^代わりに使用し^ます。これを行う必要がある理由は、スプライン上のポイントを簡単に生成できるようにするためです。次のポイントが続きます。

次に行う必要があるのはx、隣接するキー ポイントによって定義された間隔内に一連のポイントを定義し、xそれらを関数に代入して、結果をプロットすることです....次のようなもの:

figure;
hold on;
for j = 1 : n-1
    f = @(x) a(j) + b(j).*(x-x(j)) + c(j).*(x-x(j)).^2 + d(j)*(x-x(j)).^3; %// Change function to element-wise operations - be careful
    x0 = linspace(x(j), x(j+1)); %// Define set of points
    y0 = f(x0); %// Find output points
    plot(x0, y0, 'r'); %// Plot the line in between the key points
end
plot(x, y, 'bo');

新しい Figure を生成し、それを使用して、複数回hold on呼び出したときにplot結果を同じ Figure に追加します。次に、3 次スプライン係数の各セットに対して、スプライン関数を定義し、現在のキー ポイントとその横のキー ポイントの間にある一連のx値を生成します。デフォルトでは、始点 (つまり) と終点 (つまり ) の間に 100 ポイントが生成されます。3 番目のパラメーターを指定することで、生成するポイントの数を制御できます (つまり、25 ポイントを生成するようなものです)。これらの値を使用してスプライン方程式に代入し、linspacexlinspacex(j)x(j+1)linspace(x(j), x(j+1), 25);xy値。次に、赤い線を使用してこの結果を Figure にプロットします。完了したら、キー ポイントを曲線の上に青い白丸としてプロットします。

おまけとして、上記のプロット メカニズムを使用してコードを実行したところ、次のようになりました。

ここに画像の説明を入力

于 2015-03-10T04:41:09.527 に答える