Kangqiao Zhao
Kangqiao Zhao

Reputation: 121

curve fitting: a number of curves with different length/number of points into one curve in 3D in Matlab

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

Answers (1)

Thomas Hardin
Thomas Hardin

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;

Curve fit

Upvotes: 1

Related Questions