Как создать сплайны

В этом примере показано, как создать сплайны различными способами с помощью функций сплайна в Curve Fitting Toolbox™.

Интерполяция

Можно создать кубическую сплайн интерполяцию, которая совпадает с функцией косинуса в следующих сайтах x, с использованием csapi команда.

x = 2*pi*[0 1 .1:.2:.9];
y = cos(x);
cs = csapi(x,y);

Затем можно просмотреть интерполяцию сплайна при помощи fnplt.

fnplt(cs,2);
axis([-1 7 -1.2 1.2])
hold on
plot(x,y,'o')
hold off

Figure contains an axes. The axes contains 2 objects of type line.

Проверка интерполяции

Функция косинуса является 2 * pi-периодической. Насколько хорошо наша кубическая сплайн интерполяция делает в этом отношении? Один из способов проверки - вычислить различие в первой производной в двух конечных точках.

diff( fnval( fnder(cs), [0 2*pi] ) )
ans = -0.1375

Для обеспечения периодичности используйте csape вместо csapi.

csp = csape( x, y, 'periodic' );
hold on
fnplt(csp,'g')
hold off

Figure contains an axes. The axes contains 3 objects of type line.

Теперь чек дает

diff( fnval( fnder(csp), [0 2*pi] ) )
ans = -2.2806e-17

Даже вторая производная сейчас совпадает в конечных точках.

diff( fnval( fnder(csp, 2), [0 2*pi] ) )
ans = -2.2204e-16

Кусочно-линейная интерполяция тех же данных доступна через spapi. Вот добавим его к предыдущему графику, красным цветом.

pl = spapi(2, x, y);
hold on
fnplt(pl, 'r', 2)
hold off

Figure contains an axes. The axes contains 4 objects of type line.

Сглаживание

Если данные зашумлены, обычно нужно аппроксимировать, а не интерполировать. Для примера с этими данными

x = linspace(0,2*pi,51);
noisy_y = cos(x) + .2*(rand(size(x))-.5);
plot(x,noisy_y,'x')
axis([-1 7 -1.2 1.2])

Figure contains an axes. The axes contains an object of type line.

интерполяция даст блестящую интерполяцию, показанную ниже синим цветом.

hold on
fnplt( csapi(x, noisy_y) )
hold off

Figure contains an axes. The axes contains 2 objects of type line.

Напротив, сглаживание с правильным допуском

tol = (.05)^2*(2*pi)
tol = 0.0157

приводит сглаженное приближение, показанную ниже красным цветом.

hold on
fnplt( spaps(x, noisy_y,  tol), 'r', 2 )
hold off

Figure contains an axes. The axes contains 3 objects of type line.

Приближение намного хуже около концов интервала, и далеко не периодическое. Чтобы обеспечить периодичность, аппроксимируйте к периодически расширяемым данным, затем ограничьте приближение исходным интервалом.

noisy_y([1 end]) = mean( noisy_y([1 end]) );
lx = length(x);
lx2 = round(lx/2);
range = [lx2:lx 2:lx 2:lx2];
sps = spaps([x(lx2:lx)-2*pi x(2:lx) x(2:lx2)+2*pi],noisy_y(range),2*tol);

Это дает более близкое периодическое приближение, показанное черным цветом.

hold on
fnplt(sps, [0 2*pi], 'k', 2)
hold off

Figure contains an axes. The axes contains 4 objects of type line.

Метод наименьших квадратов Приближения

Кроме того, можно использовать приближение методом наименьших квадратов к зашумленным данным сплайном с несколькими степенями свободы.

Например, можно попробовать кубический сплайн с четырьмя частями.

spl2 = spap2(4, 4, x, noisy_y);
fnplt(spl2,'b',2);
axis([-1 7 -1.2 1.2])
hold on
plot(x,noisy_y,'x')
hold off

Figure contains an axes. The axes contains 2 objects of type line.

Выбор узла

При использовании spapi или spap2обычно необходимо задать конкретный сплайн пространства. Это делается путем определения последовательности узлов и порядка, и это может быть немного проблемой. Однако при выполнении сплайн интерполяции в x,y данные с использованием сплайна порядка kможно использовать функцию optknt для обеспечения хорошей последовательности узлов, как в следующем примере.

k = 5;   % order 5, i.e., we are working with quartic splines
x = 2*pi*sort([0 1 rand(1,10)]);
y = cos(x);
sp = spapi( optknt(x,k), x, y );
fnplt(sp,2,'g');
hold on
plot(x,y,'o')
hold off
axis([-1 7 -1.1 1.1])

Figure contains an axes. The axes contains 2 objects of type line.

При выполнении аппроксимации методом наименьших квадратов можно использовать текущее приближение, чтобы определить, возможно, лучший выбор узла с помощью newknt. Например, следующее приближение к экспоненциальной функции не так хорошо, как видно из ее ошибки, нанесенной красным цветом.

x = linspace(0,10,101);
y = exp(x);
sp0 = spap2( augknt(0:2:10,4), 4, x, y );
plot(x,y-fnval(sp0,x),'r','LineWidth',2)

Figure contains an axes. The axes contains an object of type line.

Однако можно использовать это начальное приближение, чтобы создать другое с таким же количеством узлов, но которые лучше распределены. Его ошибка нанесена черным цветом.

sp1 = spap2( newknt(sp0), 4, x, y );
hold on
plot(x,y-fnval(sp1,x),'k','LineWidth',2)
hold off

Figure contains an axes. The axes contains 2 objects of type line.

Сетчатые данные

Все команды сплайн интерполяции и приближения в Curve Fitting Toolbox могут также обрабатывать данные с сеткой в любом количестве переменных.

Например, вот бикубическая сплайн интерполяция в мексиканскую функцию Hat.

x =.0001+(-4:.2:4);
y = -3:.2:3;
[yy,xx] = meshgrid(y,x);
r = pi*sqrt(xx.^2+yy.^2);
z = sin(r)./r;
bcs = csapi({x,y}, z);
fnplt(bcs)
axis([-5 5 -5 5 -.5 1])

Figure contains an axes. The axes contains an object of type surface.

Вот приближение наименьших квадратов к зашумленным значениям той же функции на той же сетке.

knotsx = augknt(linspace(x(1), x(end), 21), 4);
knotsy = augknt(linspace(y(1), y(end), 15), 4);
bsp2 =  spap2({knotsx,knotsy},[4 4], {x,y},z+.02*(rand(size(z))-.5));
fnplt(bsp2)
axis([-5 5 -5 5 -.5 1])

Figure contains an axes. The axes contains an object of type surface.

Кривые

Сетчатые данные могут обрабатываться легко, потому что Curve Fitting Toolbox может иметь дело с векторными сплайнами. Это также облегчает работу с параметрическими кривыми.

Вот, например, приближение к бесконечности, полученное путем размещения кубической сплайн кривой через точки, отмеченные на следующем рисунке.

t = 0:8;
xy = [0 0;1 1; 1.7 0;1 -1;0 0; -1 1; -1.7 0; -1 -1; 0 0].';
infty = csape(t, xy, 'periodic');
fnplt(infty, 2)
axis([-2 2 -1.1 1.1])
hold on
plot(xy(1,:),xy(2,:),'o')
hold off

Figure contains an axes. The axes contains 2 objects of type line.

Вот та же кривая, но с движением в третьей размерности.

roller = csape( t , [ xy ;0 1/2 1 1/2 0 1/2 1 1/2 0], 'periodic');
fnplt( roller , 2, [0 4],'b' )
hold on
fnplt( roller, 2, [4 8], 'r')
plot3(0,0,0,'o')
hold off

Figure contains an axes. The axes contains 3 objects of type line.

Две половины кривой нанесены в разных цветах, и источник обозначен как средство визуализации этой двухкрылой кривой пространства.

Поверхности

Двухмерные тензорно-продуктивные сплайны со значениями в R ^ 3 дают поверхности. Например, вот хорошее приближение к тору.

x = 0:4;
y = -2:2;
R = 4;
r = 2;
v = zeros(3,5,5);
v(3,:,:) = [0 (R-r)/2 0 (r-R)/2 0].'*[1 1 1 1 1];
v(2,:,:) = [R (r+R)/2 r (r+R)/2 R].'*[0 1 0 -1 0];
v(1,:,:) = [R (r+R)/2 r (r+R)/2 R].'*[1 0 -1 0 1];
dough0 = csape({x,y},v,'periodic');
fnplt(dough0)
axis equal, axis off

Вот венец нормалей к этой поверхности.

nx = 43;
xy = [ones(1,nx); linspace(2,-2,nx)];
points = fnval(dough0,xy)';
ders = fnval(fndir(dough0,eye(2)),xy);
normals = cross(ders(4:6,:),ders(1:3,:));
normals = (normals./repmat(sqrt(sum(normals.*normals)),3,1))';
pn = [points;points+normals];
hold on
for j=1:nx
   plot3(pn([j,j+nx],1),pn([j,j+nx],2),pn([j,j+nx],3))
end
hold off

Наконец, вот его проекция на (x, y) -план.

fnplt(fncmb(dough0, [1 0 0; 0 1 0]))
axis([-5.25 5.25 -4.14 4.14]), axis off

Данные , имеющие разбросы

Также можно интерполировать к значениям, заданным в неискаженных сайтах данных в плоскости. Рассмотрим, для примера, задачу плавного отображения модуля квадрата на единичный диск. Мы создадим значения данных, отмеченные как круги, и соответствующие сайты данных, отмеченные как x's. Каждый сайт данных соединяется со своим связанным значением стрелой.

n = 64;
t = linspace(0,2*pi,n+1); t(end) = [];
values = [cos(t); sin(t)];
plot(values(1,:),values(2,:),'or')
axis equal, axis off

sites = values./repmat(max(abs(values)),2,1);
hold on
plot(sites(1,:),sites(2,:),'xk')
quiver(sites(1,:),sites(2,:), ...
       values(1,:)-sites(1,:), values(2,:)-sites(2,:))
hold off

Затем используйте tpaps для создания двухмерного интерполяционного векторного сплайна.

st = tpaps(sites, values, 1);

Сплайн действительно сопоставляет единичный квадрат плавно (приблизительно) с единичным диском, как его график через fnplt указывает. На график показано изображение равномерно разнесенной квадратной сетки под сплайн картой в st.

hold on
fnplt(st)
hold off