# 3D best fit curve from x,y and z data points

4 views (last 30 days)
Abbas Husain on 16 Apr 2021
Commented: Abbas Husain on 16 Apr 2021
I know this has been answered many times on this forum, but I'm really struggling to get what I want from the published answers (I'm a MATLAB novice).
My data is the following:
data = [
9 -13 86
8 -12 86
9 -12 86
8 -11 86
8 -10 86
8 -9 86
9 -12 87
8 -11 87
8 -10 87
8 -9 87
8 -8 87
8 -7 87
8 -6 87
8 -5 87
8 -4 87
7 -3 87
8 -3 87
7 -2 87
8 -2 87
7 -1 87
7 0 87
7 1 87
7 0 88
7 1 88
7 2 88
7 3 88
7 4 88
7 5 88
6 6 88
7 6 88
6 7 88
7 7 88
];
I want to extract a 3D curve of best fit ( I know this is a linear relationship here), but in future datasets it won't always be.
It's not an ideal dataset, there's noise and irregularity, but I need something to do this (see attached photo).
The datapoints are plotted in blue and the red line is drawn on, I want a function that describes this red line in 3D space.
It doesn't have to extrapolate beyond the data range.
I will need to evaluate the length of this line, hence the desire to describe it with a function.
Again, I'm a novice, so any advice you have in refining the approach/ordering the data beforehand etc will be of use.
Abbas Husain on 16 Apr 2021
Hi,
Thanks for getting back to me!
In this example, the data should resemble a straight line upwards in y, but generally, there is no assumed trend. I plan to produce larger datasets with more points such that trends can be more easily extracted. I will update the thread in due course!
Thanks again :)

Matt J on 16 Apr 2021
Edited: Matt J on 16 Apr 2021
For the linear case, you can use linear3dFit from this FEX submission. As the others have said, however, we need to know the specific model the points are supposed to follow before making recommendations for the nonlinear case.
fobj=linear3dFit(data.');
line_length=norm(fobj.p1-fobj.p2),
plot(fobj)
axis([-5.0838 26.9941 -21.1570 10.7368 69.1209 99.3109]);
view([-80,15])
Abbas Husain on 16 Apr 2021
Thanks Matt, super helpful and a great first step for this problem. Like I mentioned to @the cyclist, I will produce some datasets with more points such that (non-linear) trends are more easily identifiable. I think this will be helpful, though I may well be wrong.

John D'Errico on 16 Apr 2021
Edited: John D'Errico on 16 Apr 2021
You may think it is easy, if only you can find someone who has the magic touch.
Sorry, but not so easy.
If the curve is presumed to be a straight line, this is an errors in variables problem, often called total least squares. That part is solvable without a great deal of difficulty. The trick is to use PCA. HOWEVER, this data does not fall on anything like a line.
data = [
9 -13 86
8 -12 86
9 -12 86
8 -11 86
8 -10 86
8 -9 86
9 -12 87
8 -11 87
8 -10 87
8 -9 87
8 -8 87
8 -7 87
8 -6 87
8 -5 87
8 -4 87
7 -3 87
8 -3 87
7 -2 87
8 -2 87
7 -1 87
7 0 87
7 1 87
7 0 88
7 1 88
7 2 88
7 3 88
7 4 88
7 5 88
6 6 88
7 6 88
6 7 88
7 7 88];
x = data(:,1);
y = data(:,2);
z = data(:,3);
Just looking at your data, it is not very clean.
plot3(x,y,z,'o')
box on
grid on
So we see points at very discrete levels, scattered throughout space. I have no idea what line it is that you think represents that data. It also looks nothing at all like the picture you posted.
Even if we find that you posted the wrong data, there is still the problem of choosing a model. Until you choose some nonlinear model, there is no chance at all of finding "THE" function that represents it.
And then worst, nonlinear total least squares can be a difficult problem to solve.
I wish you luck, but there ain't no magic formula. And until you decide what the correct data is, and what model you expect to apply to approximate that data, you cannot find "THE" function that fits the data.