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