Сплайны в плоскости

В этом примере показано, как использовать spmak, spcrv, cscvn и rscvn команды от Curve Fitting Toolbox™, чтобы создать сплайновые кривые в плоскости. Это включает касательные графического вывода и вычисление области, заключенной кривой.

Простая сплайновая кривая

Curve Fitting Toolbox может обработать сплайны с векторным знаком. D-vector-valued одномерный сплайн обеспечивает кривую на d-пробеле. В этом режиме, d = 2 наиболее распространено, когда это дает плоские кривые.

Вот пример, в котором сплайн с 2-мерными коэффициентами создан и построен.

knots = [1,1:9,9];
curve = spmak( knots, repmat([ 0 0; 1 0; 1 1; 0 1 ], 2,1).' );

t = linspace(2,8,121);
values = fnval(curve,t);
plot(values(1,:),values(2,:),'LineWidth',2);
axis([-.4 1.4 -.2 1.2]), axis equal
title('A Spline Curve');
hold on

Предостережение

Вы, возможно, заметили, что этот пример не использовал fnplt построить кривую, но вместо этого построило некоторые точки на кривой, полученные fnval. Вот код снова:

  t = linspace(2,8,121);
  values = fnval(curve,t);
  plot(values(1,:),values(2,:),'LineWidth',2)

Используя fnplt непосредственно с этой конкретной сплайновой кривой дает красную кривую на рисунке ниже.

fnplt(curve,'r',.5);
title('The Full Spline Curve, in Red')

Объяснение?

Сплайн имеет порядок 4, все же узлы конца в последовательности узла

knots
knots =

     1     1     2     3     4     5     6     7     8     9     9

только имейте кратность 2. Поэтому все B-сплайны порядка 4 для этой последовательности узла 0 в конечных точках основного интервала. Это заставляет кривую запуститься и остановиться в (0,0).

Средство

С тех пор, в этом случае, мы интересуемся действительно только сегментом кривой, соответствующим интервалу параметра [3.. 7], мы можем использовать fnbrk чтобы извлечь ту часть, и затем не испытывают никаких затруднений при графическом выводе его, в желтом, с fnplt.

mycv = fnbrk(curve,[3 7]);
fnplt(mycv,'y',2.5);
title('The Spline Curve of Interest, in Yellow')

Область, вложенная этой кривой

Поскольку у вас теперь есть сплайн, а именно, mycv, это описывает кривую (и ничто иное), можно легко вычислить область, заключенную этой замкнутой кривой, можно следующим образом.

area = diff(fnval(fnint( ...
       fncmb(fncmb(mycv,[0 1]),'*',fnder(fncmb(mycv,[1 0]))) ...
                        ),fnbrk(mycv,'interval')))
area =

   -0.8333

С небольшим усилием можно распознать это значением интеграла

  int y(t) d(x(t)) = int y(t) Dx(t) dt

на основном интервале сплайна mycv, с (x(t),y(t)) := fnval(mycv,t) точка на кривой, соответствующая значению параметров t. Здесь, fncmb(mycv,[1,0]), fncmb(mycv,[0,1]) опишите два компонента сплайновой кривой, т.е. сплайны со скалярным знаком x и y.

Кроме того, кривая является примерно кругом с радиусом 1/2. Следовательно, вы ожидали бы область, примерно,

disp(pi/4)
    0.7854

Но почему вычисленная область отрицательна? Поскольку область, заключенная кривой, лжет левым, когда каждый перемещается на кривой с увеличением t. Чтобы проверить это, мы чертим некоторые векторы касательной.

Добавьте некоторые векторы касательной

Мы перерисовываем кривую и также чертим вектор касательной к кривой в некоторых точках.

hold off
fnplt(mycv,'y',2.5); hold on
t = 3:.4:6.2;
cv = fnval(curve, t);
cdv = fnval(fnder(curve), t);
quiver(cv(1,:),cv(2,:), cdv(1,:),cdv(2,:));
title('A Spline Curve With Some Tangents')
axis([-.4 1.4 -.2 1.2]), axis equal

Пересечение кривой прямой линией

Если вы хотели определить точки пересечения этой сплайновой кривой прямой линией y = x, следующий код дал бы их вам и построил бы сегмент той прямой линии в кривой:

cuts = fnval(mycv, ...
    mean(fnzeros(fncmb(fncmb(mycv,[0,1]),'-',fncmb(mycv,[1,0])))));
plot(cuts(1,:), cuts(2,:),'y','LineWidth',2.5)
hold off
title('A Spline Curve With Some Tangents and a Cut Across')

SPCRV: многоугольник управления и соответствующая сплайновая кривая

Сплайновые кривые используются экстенсивно в генерации рисунков, на которых требуются не что иное как плавная кривая определенной примерно предполагаемой формы. Для этого Curve Fitting Toolbox содержит специальную команду, spcrv, который может использоваться независимо от остальной части тулбокса.

Учитывая последовательность точек в плоскости и, опционально, порядок k, spcrv генерирует, повторной вставкой узла средней точки, сплайновой кривой порядка k чей многоугольник управления задан данной последовательностью.

Фигура ниже показов такой многоугольник управления и соответствующая сплайновая кривая порядка 3.

points = [0 0; 1 0; 1 1; 0 2; -1 1; -1 0; 0 -1; 0 -2].';
values = spcrv(points,3);

plot(points(1,:),points(2,:),'k');
axis([-2 2.25 -2.1 2.2]);
hold on
plot(values(1,:),values(2,:),'r','LineWidth',1.5);
legend({'Control Polygon' 'Quadratic Spline Curve'},  'location','SE');

Заметьте, что кривая касается каждого сегмента многоугольника управления в его средней точке и следует за формой, обрисованной в общих чертах многоугольником управления.

Повышение порядка

Повышение порядка k разделит кривую от многоугольника управления и сделает его более сглаженным, но также и короче. Здесь, мы добавили соответствующую сплайновую кривую порядка 4.

value4 = spcrv(points,4);
plot(value4(1,:),value4(2,:),'b','LineWidth',2);
legend({'Control Polygon' 'Quadratic Spline Curve' ...
        'Cubic Spline Curve'}, 'location','SE');

CSCVN

С другой стороны, чтобы получить кривую интерполяции, вы могли использовать cscvn команда, которая обеспечивает параметрическую 'естественную' кубическую сплайновую кривую.

fnplt(cscvn(points), 'g',1.5);
legend({'Control Polygon' 'Quadratic Spline Curve' ...
        'Cubic Spline Curve' 'Interpolating Spline Curve'}, ...
        'location','SE');

Путем добавления точки (.95,-.05) около второй контрольной точки, (1,0), мы можем создать сплайновую кривую интерполяции, которая становится быстрее там.

np = size(points, 2);
fnplt( cscvn([ points(:,1) [.95; -.05] points(:,2:np) ]), 'm',1.5);
plot(.95,-.05,'*');
legend({'Control Polygon' 'Quadratic Spline Curve' ...
        'Cubic Spline Curve' 'Interpolating Spline Curve' ...
        'Faster Turning Near (1,0)'}, ...
        'location','SE');
hold off

RSCVN

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

Например, следующее генерирует круг

c = rscvn([-1 1 -1;0 0 0],[1 1;0 0]);

когда его график показывает.

fnplt(c);
axis([-1.05 1.05 -1.05 1.05]), axis equal, axis off

c квадратичный рациональный сплайн, состоящий всего из двух частей, когда следующие команды ясно дают понять.

[form, order, breaks] = fnbrk(c,'f','o','b')
form =

    'rBform'


order =

     3


breaks =

     0     2     4

Легко сгенерировать поразительные шаблоны с этим инструментом с помощью всего нескольких точек данных. Например, вот версия проекта на Бронзовом Медальоне Triskele в Ольстерском Музее в Белфасте, предположительно, сделанном частями круговых дуг давным-давно.

pp =[zeros(1,7); 5.4, 3, 6.9, 2.75, 2.5, .5, 5];
alpha = 2*pi/3; ca = cos(alpha); sa = sin(alpha); c = [ca sa;-sa ca];
d = [0 0 .05 -.05;1 -1 .98 .98]; d = [d c*d];
yin = rscvn([pp(:,[7,1:3]),c*pp(:,3:4),pp(:,3)], d(:,[1 2 1 4 7 5 1]));
fnplt(yin), hold on, fnplt(fncmb(yin,c)), fnplt(fncmb(yin,c'))
yang = rscvn([pp(:,6),-pp(:,6),pp(:,5),c*pp(:,4)],[d(:,[2 1 1]),c(:,2)]);
fnplt(yang), fnplt(fncmb(yang,c)), fnplt(fncmb(yang,c'))
axis([-7.2 7.2 -7.2 7.2]), axis equal, axis off, hold off