Plotting a smooth curve from points

54 visualizaciones (últimos 30 días)
Osama Anwar
Osama Anwar el 23 de En. de 2021
Comentada: Osama Anwar el 27 de En. de 2021
I'm trying to plot a smooth line for 6 points in such a way that slope at each is zero. I have successfully achieved it for middle points using 'pchip' but I also want it for extreme points i.e. x=0 and x=15 which I am unable to do while using 'pchip'.
Here is my code
clear
clc
x = [0;3;6;9;12;15];
y = [0;1.9190;-3.2287;3.5133;-2.6825;1];
xi = linspace(min(x), max(x), 150); % Evenly-Spaced Interpolation Vector
yi = interp1(x, y, xi, 'pchip');
figure
plot(x, y, 'b')
hold on
plot(xi, yi, '-r')
hold off
grid
xlabel('X')
ylabel('Y')
legend('Original Data', 'Interpolation', 'Location', 'NE')
  3 comentarios
Osama Anwar
Osama Anwar el 23 de En. de 2021
1) It seems very much zero to me. if you increase points from 150 to say 15000 and zoom in at say 3 then you would find line flattening that is one indication.
2) It is a mode shape of building. It will be used to find displacements and at max displacements your velocity is zero.
Adam Danz
Adam Danz el 23 de En. de 2021
Editada: Adam Danz el 23 de En. de 2021
The slopes are very close to 0. Vertical lines show the original x-values without the endpoints.
x = [0;3;6;9;12;15];
y = [0;1.9190;-3.2287;3.5133;-2.6825;1];
xi = linspace(min(x), max(x), 150);
yi = interp1(x, y, xi, 'pchip');
% compute slopes
s = gradient(yi, 150);
plot(xi,s)
yline(0)
arrayfun(@xline, x(2:end-1)

Iniciar sesión para comentar.

Respuesta aceptada

Bruno Luong
Bruno Luong el 24 de En. de 2021
Editada: Bruno Luong el 24 de En. de 2021
Direct analytic method using piecewise cublic polynomial. The curve is first-order differentiable, but not second order differentiable (as with sublic spline or result with my first answer using BSFK)
x = [0;3;6;9;12;15];
y = [0;1.9190;-3.2287;3.5133;-2.6825;1];
[xx,is] = sort(x(:));
yy = y(is);
yy = yy(:);
dx = diff(xx);
dy = diff(yy);
y0 = yy(1:end-1);
n = numel(xx)-1;
coefs = [-2*dy./(dx.^3), 3*dy./(dx.^2), 0*dy, y0];
pp = struct('form', 'pp',...
'breaks', xx(:)',...
'coefs', coefs,...
'pieces', n, ...
'order', 4,...
'dim', 1);
figure
xi = linspace(min(x),max(x));
yi = ppval(pp,xi);
plot(x,y,'b-o',xi,yi,'r');
xlim([min(x),max(x)])
grid on
Propably this is how John generates his curve
x = [0 1 1.5 2 4];
y = x;
  10 comentarios
Bruno Luong
Bruno Luong el 27 de En. de 2021
Sorry you are on your own if you use symbolic variables. Once you modify/adap the code it's yours.
I don't have this toolbox to help, even if I want to .
Osama Anwar
Osama Anwar el 27 de En. de 2021
Ok no problem Thanks.

Iniciar sesión para comentar.

Más respuestas (2)

Adam Danz
Adam Danz el 23 de En. de 2021
Editada: Adam Danz el 23 de En. de 2021
You could add values to the beginning and end to make the curve continuing in both directions. The example below uses hard-coded values but it wouldn't be difficult to programmatically extend the trend in the opposite y-direction on each side of X.
x = [-3;0;3;6;9;12;15;18];
% ^^ ^^ added
y = [2;0;1.9190;-3.2287;3.5133;-2.6825;1;-2];
% ^ ^^ added
xi = linspace(min(x), max(x), 150);
yi = interp1(x, y, xi, 'pchip');
% Trim the additions
rmIdx = xi<0 | xi>15;
xi(rmIdx) = [];
yi(rmIdx) = [];
x([1,end]) = [];
y([1,end]) = [];
figure
plot(x, y, 'b')
hold on
plot(xi, yi, '-r')
hold off
grid
xlabel('X')
ylabel('Y')
legend('Original Data', 'Interpolation', 'Location', 'NE')
  13 comentarios
Adam Danz
Adam Danz el 24 de En. de 2021
Yeah, it's not a robust hack.
I'm following the conversation. John and Bruno have great points.
Osama Anwar
Osama Anwar el 24 de En. de 2021
Yeah I get your point.

Iniciar sesión para comentar.


Bruno Luong
Bruno Luong el 24 de En. de 2021
Editada: Bruno Luong el 24 de En. de 2021
No extra points needed (but you might add to twist the shape of the curve in the first and last interval),
Spline order >= 8th is needed using my FEX
x = [0;3;6;9;12;15];
y = [0;1.9190;-3.2287;3.5133;-2.6825;1];
interp = struct('p', 0, 'x', x, 'v', y);
slope0 = struct('p', 1, 'x', x, 'v', 0*x);
% Download BSFK function here
% https://www.mathworks.com/matlabcentral/fileexchange/25872-free-knot-spline-approximation
pp = BSFK(x,y, 9, length(x)-1, [], struct('KnotRemoval', 'none', 'pntcon', [interp slope0]));
% Check
figure
xi = linspace(min(x),max(x));
yi = ppval(pp,xi);
plot(x,y,'b',xi,yi,'r');
for xb=pp.breaks
xline(xb);
end
grid on
  4 comentarios
Osama Anwar
Osama Anwar el 24 de En. de 2021
1st and 3rd are not the one I need. 2nd one without Adam addition would do the trick. Thanks for taking out time to answer. Very much appreciated
Bruno Luong
Bruno Luong el 25 de En. de 2021
Editada: Bruno Luong el 26 de En. de 2021
The shape might not meet your (un-written) expectation but it definitively meets every requiremenrs you state in the question. The interpolating solution is trully "smooth" (I believe up to the 7th derivative order is continue) with zero slope at the give abscissa.
This illustres one of the difficulty using spline fitting/interpolating: the chosen boundary conditions affects globally the shape of the interpolation.
It might be still useful for futur readers.

Iniciar sesión para comentar.

Categorías

Más información sobre Preprocessing Data en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by