exponenta event banner

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

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

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

Панель инструментов фитинга кривой может обрабатывать векторные сплайны. Одномерный сплайн с 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: управляющий полигон и соответствующая сплайновая кривая

Сплайновые кривые широко используются при создании иллюстраций, в которых требуется не что иное, как гладкая кривая определенной грубо воображаемой формы. Для этого панель инструментов фитинга кривой содержит специальную команду: 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

С помощью этого инструмента легко создавать ударные шаблоны, используя всего несколько точек данных. Например, вот вариант конструкции на медальоне Bronze 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