How to find the minimum distance between two fitted curves

47 vues (au cours des 30 derniers jours)
Raffaele Russo
Raffaele Russo le 23 Avr 2019
Modifié(e) : John D'Errico le 24 Avr 2019
I have the following problem:
I use the fit commands
curve1 = fit(x1,y1,'smoothspline')
curve2= fit(x1,y2,'smoothspline')
Now I obtain a plot like the attached image. How do I find the minumum difference between the two curves? I can't use
[M,I] = min(abs(curve1-curve2));
because matlab says: Undefined operator '-' for input arguments of type 'cfit'
If you see the attached image I want the min distance between the green and the red line.
untitled.jpg
  2 commentaires
Image Analyst
Image Analyst le 23 Avr 2019
Can you attach a .mat file with all your x and y arrays?
Raffaele Russo
Raffaele Russo le 24 Avr 2019
this is my script with all plots, here my aim is to find the minimum vertical distance between f5 and f6

Connectez-vous pour commenter.

Réponse acceptée

John D'Errico
John D'Errico le 24 Avr 2019
Modifié(e) : John D'Errico le 24 Avr 2019
Not impossible to do. I can think of two ways to do this. You give no data, so let me make some up.
x1 = sort(rand(100,1))-.5;
y1 = sin(6*x1)/2 + randn(size(x1))/1000;
x2 = sort(rand(100,1))-.5;
y2 = cos(x2) + randn(size(x2))/1000;
curve1 = fit(x1,y1,'smoothingspline');
curve2 = fit(x2,y2,'smoothingspline');
plot(curve1)
hold on
plot(curve2)
Note that fit requires 'smoothingspline'. 'smoothspline' will just give you an error.
As I said, the closest point between the two curves can be found in several ways. Simple is to just sample a zillion points on the two curves, then find the one which minimizes the Euclidean distance. Thus...
nint = 1000;
xint = linspace(-.5,.5,nint)';
y1int = curve1(xint);
y2int = curve2(xint);
% interpoint distance matrix:
% Note: this uses a feature of R2016b or later.
% Older releases will find bsxfun useful.
d = sqrt((xint - xint.').^2 + (y1int - y2int.').^2);
d = d + diag(repmat(inf,nint,1));
[mind,ind] = min(d(:));
[i1,i2] = ind2sub([nint,nint],ind);
plot([xint(i1),xint(i2)],[y1int(i1),y2int(i2)],'-bo')
axis equal
untitled.jpg
Note my use of axis equal in there, to force the axes to have the same units. That makes it clear this really is the pair of points with minimium distance between the curves.
Another point worth noting, is IF you really wanted to just find the point with minimum vertical distance between the curves, it would have been far easier to compute. But your statement said the minimum distance between the curves.
Can you do this more exactly? Well, yes. But is the exact solution it really, truly important? That is especially true, when those curves are just smoothing splines.
How would I find the exact solution?
For that, I would need to extract each polynomial segment from the splines. Then compute the minimum distance between each pair of those segments. This reduces to essentially a polynomial rootfinding problem, although the polynomials involved will be of sufficiently high order that a numerical solver will be needed. I seriously doubt you need that much accuracy though.
  3 commentaires
Raffaele Russo
Raffaele Russo le 24 Avr 2019
unfortunately i have a problem with your solution, when i apply it to my script i can find only one point of minimum distance but because my curves have 2 intersection points the points are two and i need to know both (for me would be good to have the ascissa of minimum distance as output of the function).
John D'Errico
John D'Errico le 24 Avr 2019
Modifié(e) : John D'Errico le 24 Avr 2019
I hate moving targets. First minimum distance. Then we are told it is vertical distance you wanted. But in reality, maybe you want the intersection points, and you want to find them all.
So, which is it? Do you want to find the minimum vertical distance between f5 and g6? Or the intersection points of f5 and f6? I'll assume that now you mean to look for intersection points.
Use Doug Schwarz's utility: intersections. It is found on the file exchange for download.
Since I still have seen no data from you, you will need to do it yourself.
xint = linspace(min(LF),max(LF),1000);
y5int = f5(xint);
y6int = f6(xint);
[X0,Y0] = intersections(xint,y5int,xint,y6int);

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Get Started with Curve Fitting Toolbox dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by