Reputation: 121
Say I've got a number of curves with different length (number of points in each curve and points distance are all vary). Could I find a curve in 3D space that fit best for this group of lines?
Code example in Matlab would be appreciated.
example data set:
the 1st curve has 10 points.
18.5860 18.4683 18.3576 18.2491 18.0844 17.9016 17.7709 17.6401 17.4617 17.2726
91.6178 91.5711 91.5580 91.5580 91.5701 91.6130 91.5746 91.5050 91.3993 91.2977
90.6253 91.1090 91.5964 92.0845 92.5565 93.0199 93.5010 93.9785 94.4335 94.8851
the 2nd curve has 8 points.
15.2091 15.0894 14.9765 14.8567 14.7360 14.6144 14.4695 14.3017
90.1138 89.9824 89.8683 89.7716 89.6889 89.6040 89.4928 89.3624
99.4393 99.9066 100.3802 100.8559 101.3340 101.8115 102.2770 102.7296
a desired curve is one that could represent these two exist curves.
I have thinking of make these curves as points scatters and fit a line out of them. But only a straight line can I get from many code snippet online.
So did I missing something or could someone provide some hint. Thanks.
Upvotes: 0
Views: 1019
Reputation: 236
Hard to come up with a bulletproof solution without more details, but here's an approach that works for the sample data provided. I found the line of best fit for all the points, and then parameterized all the points along that line of best fit. Then I did least-squares polynomial fitting for each dimension separately. This produced a three-dimensional parametric curve that seems to fit the data just fine. Note that curve fitting approaches other than polynomial least-squares might be better suited to some cases---just substitute the preferred fitting function for polyfit and polyval.
Hope this is helpful!
clear;
close all;
pts1=[18.5860 18.4683 18.3576 18.2491 18.0844 17.9016 17.7709 17.6401 17.4617 17.2726;
91.6178 91.5711 91.5580 91.5580 91.5701 91.6130 91.5746 91.5050 91.3993 91.2977;
90.6253 91.1090 91.5964 92.0845 92.5565 93.0199 93.5010 93.9785 94.4335 94.8851]';
pts2=[ 15.2091 15.0894 14.9765 14.8567 14.7360 14.6144 14.4695 14.3017;
90.1138 89.9824 89.8683 89.7716 89.6889 89.6040 89.4928 89.3624;
99.4393 99.9066 100.3802 100.8559 101.3340 101.8115 102.2770 102.7296]';
%Combine all of our curves into a single point cloud
X = [pts1;pts2];
%=======================================================
%We want to first find the line of best fit
%This line will provide a parameterization of the points
%See accepted answer to http://stackoverflow.com/questions/10878167/plot-3d-line-matlab
% calculate centroid
x0 = mean(X)';
% form matrix A of translated points
A = [(X(:, 1) - x0(1)) (X(:, 2) - x0(2)) (X(:, 3) - x0(3))];
% calculate the SVD of A
[~, S, V] = svd(A, 0);
% find the largest singular value in S and extract from V the
% corresponding right singular vector
[s, i] = max(diag(S));
a = V(:, i);
%=======================================================
a=a / norm(a);
%OK now 'a' is a unit vector pointing along the line of best fit.
%Now we need to compute a new variable, 't', for each point in the cloud
%This 't' value will parameterize the curve of best fit.
%Essentially what we're doing here is taking the dot product of each
%shifted point (contained in A) with the normal vector 'a'
t = A * a;
tMin = min(t);
tMax = max(t);
%This variable represents the order of our polynomial fit
%Use the smallest number that produces a satisfactory result
polyOrder = 8;
%Polynomial fit all three dimensions separately against t
pX = polyfit(t,X(:,1),polyOrder);
pY = polyfit(t,X(:,2),polyOrder);
pZ = polyfit(t,X(:,3),polyOrder);
%And that's our curve fit: (pX(t),pY(t),pZ(t))
%Now let's plot it.
tFine = tMin:.01:tMax;
fitXFine = polyval(pX,tFine);
fitYFine = polyval(pY,tFine);
fitZFine = polyval(pZ,tFine);
figure;
scatter3(X(:,1),X(:,2),X(:,3));
hold on;
plot3(fitXFine,fitYFine,fitZFine);
hold off;
Upvotes: 1