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

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

Простая сплайн

Curve Fitting Toolbox может обрабатывать векторные сплайны. Одномерный сплайн, оцененный d-вектором, обеспечивает кривую в 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 генерирует, путем повторной вставки узла средней точки, сплайна кривой порядок <reservedrangesplaceholder0> чей управляющий многоугольник задан заданной последовательностью.

Рисунок ниже показывает такой управляющий многоугольник и соответствующую сплайн порядка 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

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

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