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

Этот пример показывает, как использовать 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

Для просмотра документации необходимо авторизоваться на сайте