Getting equation for a interpolated spline using csaps

1 visualizzazione (ultimi 30 giorni)
Hello good people
I have set of points (x,y,z) which form closed curves. I interpolated the points using MATLAB csaps to get the closed splines. I need the interpolated points to be at a certain equal angular distance suppose (360 degrees/N , N= being the the number of interpolated points on the closed curve) from the centroid of each spline.
  1. My first question is how do I do that?
  2. Can I get the spline equation from Matlab?
  3. For my reference I am attaching an image

Risposta accettata

John D'Errico
John D'Errico il 1 Mar 2023
Modificato: John D'Errico il 1 Mar 2023
I'll post this as a separate answer, since I did not use a spline at all to build the model, and so it does not get lost in the comments to my other answer.
As I said, the result will be hundreds of coefficients if you built this as a spline model. So nothing at all you can write down. I've attached your data as a .mat file to this comment.
load data.mat
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'-o')
box on
grid on
So we see a simple circular looking curve. But in fact, the points seem to lie exactly in a plane, although they are not in fact in a perfect circle in that plane. The curve is a bit egg shaped. That is, if I transform that 3-d set of points into a 2-d plane, we would see they lie almost perfectly in a palne, but not exactly so. The failure to lie exactly in a plane probably arises because you have written down the points with only 5 significant digits, and that is roughly the amount of error I see as a deviation from the plane.
xyzbar = mean(xyz,1);
svd(xyz - xyzbar)
ans = 3×1
175.7223 162.4791 0.0017
So the smallest singular value there is roughly 5 powers of 10 smaller than the largest singular value. Again, that is good evidence the deviation from a perfect plane lies in having rounded off the 5th decimal place in your numbers.
Anyway, we can now try to build a model for your data that will be roughly as accurate as your data. I could transform the problem into a 2-dimensional one. Or, simpler yet to follow, we can just work in cylindrical coordinates. Since you wanted points that were at a set of uniform angles, that may be best.
I notice that your first and last points were the same. That was done to fit the spline as a periodic function, I presume.
x = xyz(2:end,1); xbar = mean(x);
y = xyz(2:end,2); ybar = mean(y);
z = xyz(2:end,3);
[theta,R] = cart2pol(x-xbar,y-ybar);
plot(theta,[x,y,z])
grid on
legend('x','y','z')
xlabel 'Polar angle theta (in radians)'
Simplest now might be to just build a simple fourier series model for each of x, y, and z. Alternatively, I could have continurd to work in cylindrical coordinates, but the simple Fourier model for x(theta), y(theta), z(theta) will work nicely, and the added layer of complexity of working in cylindrical coordinates is not worth the effort.
mdl = fittype('b0+a1*sin(t)+b1*cos(t)+a2*sin(2*t)+b2*cos(2*t)+a3*sin(3*t)+b3*cos(3*t)+a4*sin(4*t)+b4*cos(4*t)+a5*sin(5*t)+b5*cos(5*t)+a6*sin(6*t)+b6*cos(6*t)','indep','t')
mdl =
General model: mdl(a1,a2,a3,a4,a5,a6,b0,b1,b2,b3,b4,b5,b6,t) = b0+a1*sin(t)+b1*cos(t)+a2*sin(2*t) +b2*cos(2*t)+a3*sin(3*t)+b3*cos(3*t)+a4*sin(4*t)+b4*cos(4*t) +a5*sin(5*t)+b5*cos(5*t)+a6*sin(6*t)+b6*cos(6*t)
[mdlx,goodnessx] = fit(theta,x,mdl)
Warning: Start point not provided, choosing random start point.
mdlx =
General model: mdlx(t) = b0+a1*sin(t)+b1*cos(t)+a2*sin(2*t)+b2*cos(2*t)+a3*sin(3*t)+b3*cos(3*t) +a4*sin(4*t)+b4*cos(4*t)+a5*sin(5*t)+b5*cos(5*t)+a6*sin(6*t) +b6*cos(6*t) Coefficients (with 95% confidence bounds): a1 = -2.003 (-2.034, -1.972) a2 = 0.3862 (0.3543, 0.4181) a3 = -2.032 (-2.064, -2.001) a4 = 0.2025 (0.1708, 0.2343) a5 = 0.01458 (-0.01682, 0.04598) a6 = -0.1871 (-0.2185, -0.1558) b0 = 20.76 (20.73, 20.78) b1 = 26.99 (26.96, 27.03) b2 = 0.2533 (0.2217, 0.285) b3 = -0.7179 (-0.7497, -0.6861) b4 = 0.3542 (0.3224, 0.3859) b5 = -0.2083 (-0.2397, -0.1769) b6 = 0.1204 (0.08905, 0.1518)
goodnessx = struct with fields:
sse: 0.2606 rsquare: 1.0000 dfe: 41 adjrsquare: 1.0000 rmse: 0.0797
The model has an RMSE of 0.0797, which is not quite as small as the noise in your data due to rounding. An extra trm or two in the model would decrease that error considerably. I'm not sure it is warranted. That would be your choice. The noise in your data due to rounding was on the oder of 10% or less of that number. Still it is probably adequate.
plot(mdlx,theta,x)
As you can see, the model fits quite nicely. As such, it gives you a nice function you can write down. As well, you can evaluate that model at a list of points in polar angle.
Next, build similar models for y and z.
mdly = fit(theta,y,mdl);
Warning: Start point not provided, choosing random start point.
mdlz = fit(theta,z,mdl);
Warning: Start point not provided, choosing random start point.
plot(mdly,theta,y)
plot(mdlz,theta,z)
Again, the y and z models seem entirely adequate for this data. Or you could add an extra pair of terms if you wanted more.
Each of these models are now easily written down, since they only required 13 terms to fit as Fourier series. And, we can now evaluate them easily enough.
T = (0:30:330)'; % degrees, to make it easier to follow
Trad = deg2rad(T);
table(T,mdlx(Trad),mdly(Trad),mdlz(Trad))
ans = 12×4 table
T Var2 Var3 Var4 ___ _______ _______ _______ 0 47.551 -50.113 -34.851 30 41.626 -38.113 -38.914 60 33.095 -28.523 -39.762 90 20.781 -22.634 -35.811 120 4.5568 -22.372 -25.73 150 -6.5076 -34.321 -10.964 180 -4.5821 -50.234 -1.828 210 0.56545 -61.678 2.3641 240 8.3695 -71.553 3.8563 270 20.693 -79.351 1.142 300 36.272 -77.142 -10.139 330 46.66 -65.124 -24.522
Finally, we can now return and plot the three curves in 3-d.
fplot3(@(t) mdlx(t),@(t) mdly(t),@(t) mdlz(t))
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments.
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments.
Warning: Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an output with the same size and shape as the input arguments.
hold on
plot3(x,y,z,'ro')
  1 Commento
mehlil ahmed
mehlil ahmed il 1 Mar 2023
Thank you so much for such a detail answer! This explains a lot. I really appreciate your help!

Accedi per commentare.

Più risposte (1)

John D'Errico
John D'Errico il 1 Mar 2023
Modificato: John D'Errico il 1 Mar 2023
Can you get the spline equation? No. There is no simple equation you can write down. Or, if you could write it down, it would involves at least many dozens of coefficients. This is perhaps the most common misunderstanding made by users about splines. They seem to think that all functions have some nice, simple form they can write down in a paper or report. No, you can't, at least not in general with a spline. (In a very simple case, where the spline was built from only 3 points or so, well, yes. Then you could. But that never actually happens. You would not be bothering to use a spline then anyway.)
Can you get a set of points at specific degree increments? Not directly, no, at least, not easily. (You COULD do it, but that would essentially involve calls to a tool like fzero to generate each point on the curve.) If you had generated the curves as a function of angle, then yes, you can do that trivially, because then the curves would be represented as a function of polar angle. And there should be no reason you could not have done that, but I gather you just started with (x,y,z) coordinates from your comments. But you could easily convert (x,y) into polar coordinates, then build the splines r(theta), z(theta). Now it would be trivial to compute points on the curve at a list of angles. The point being, you generated your splines the wrong way to achieve what you seem to want.
Anyway, we don't have your data, so I cannot give an example of what you might have done differently.
  1 Commento
mehlil ahmed
mehlil ahmed il 1 Mar 2023
Thank you so much for your answer. I really appreciate your time and help. I am posting here one set of my data for 1 closed curve to get an idea about what you just said. points(x,y,z)_
x y z
-4.79420000000000 -49.7660000000000 -1.99890000000000
-3.51370000000000 -53.3820000000000 -0.455070000000000
-1.96000000000000 -56.9280000000000 0.869740000000000
-0.158040000000000 -60.3630000000000 1.96590000000000
1.86730000000000 -63.6490000000000 2.82380000000000
4.09120000000000 -66.7470000000000 3.43380000000000
6.48870000000000 -69.6180000000000 3.78630000000000
9.03510000000000 -72.2220000000000 3.87150000000000
11.6760000000000 -74.4990000000000 3.68360000000000
14.4150000000000 -76.4410000000000 3.21660000000000
17.2290000000000 -78.0160000000000 2.46230000000000
20.0950000000000 -79.1860000000000 1.41260000000000
22.9900000000000 -79.9170000000000 0.0593040000000000
25.8900000000000 -80.1750000000000 -1.60580000000000
28.7830000000000 -79.9360000000000 -3.58910000000000
31.6180000000000 -79.2330000000000 -5.83820000000000
34.3570000000000 -78.1150000000000 -8.29590000000000
36.9600000000000 -76.6330000000000 -10.9050000000000
39.3880000000000 -74.8360000000000 -13.6090000000000
41.6030000000000 -72.7720000000000 -16.3510000000000
43.5630000000000 -70.4920000000000 -19.0730000000000
45.1960000000000 -68.1000000000000 -21.6610000000000
46.5230000000000 -65.5560000000000 -24.1550000000000
47.5200000000000 -62.8650000000000 -26.5350000000000
48.1600000000000 -60.0350000000000 -28.7810000000000
48.4170000000000 -57.0720000000000 -30.8710000000000
48.2640000000000 -53.9810000000000 -32.7850000000000
47.6770000000000 -50.7710000000000 -34.5030000000000
46.6060000000000 -47.3640000000000 -36.0430000000000
45.1080000000000 -43.9140000000000 -37.3400000000000
43.2410000000000 -40.5010000000000 -38.3810000000000
41.0660000000000 -37.2010000000000 -39.1530000000000
38.6420000000000 -34.0940000000000 -39.6420000000000
36.0280000000000 -31.2580000000000 -39.8360000000000
33.2840000000000 -28.7700000000000 -39.7210000000000
30.3560000000000 -26.6230000000000 -39.2670000000000
27.3550000000000 -24.9020000000000 -38.4900000000000
24.2830000000000 -23.5760000000000 -37.4120000000000
21.1440000000000 -22.6120000000000 -36.0550000000000
17.9410000000000 -21.9780000000000 -34.4430000000000
14.6750000000000 -21.6430000000000 -32.5980000000000
11.6080000000000 -21.5790000000000 -30.7010000000000
8.56280000000000 -21.7700000000000 -28.6530000000000
5.61430000000000 -22.2430000000000 -26.4820000000000
2.83570000000000 -23.0250000000000 -24.2170000000000
0.300690000000000 -24.1420000000000 -21.8890000000000
-1.91720000000000 -25.6210000000000 -19.5250000000000
-3.74440000000000 -27.4890000000000 -17.1550000000000
-5.17430000000000 -29.8670000000000 -14.7040000000000
-6.12780000000000 -32.6280000000000 -12.3050000000000
-6.63490000000000 -35.7040000000000 -9.98360000000000
-6.72520000000000 -39.0250000000000 -7.76590000000000
-6.42870000000000 -42.5220000000000 -5.67840000000000
-5.77510000000000 -46.1250000000000 -3.74730000000000
-4.79420000000000 -49.7660000000000 -1.99890000000000

Accedi per commentare.

Categorie

Scopri di più su Spline Postprocessing in Help Center e File Exchange

Prodotti


Release

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by