# How can i compute an interpolated curve?

6 views (last 30 days)
Chris Topher on 21 Sep 2020
Commented: Chris Topher on 23 Sep 2020
Hello,
i have a bunch of lift cs. drag polars with fixed speed. Now i want to create an interpolated polar at a certain speed between two of them. Is there any built in function in Matlab to achieve this? I dont know how to do it with the interp functions.

Ameer Hamza on 21 Sep 2020
Can you further explain the question? perhaps with some sample data points.
Chris Topher on 21 Sep 2020
Sure. Here in this picture are two of the given curves (yellow and blue). Yellow line is 10m/s, blue 15m/s. The picture is not from Matlab, but they are imported as an Array with a few more coefficients via readmatrix. I just want to create data like the pink dots in Matlab (not in the middle) by linear interpolating the two curves to a given speed between 10 and 15m/s. John D'Errico on 21 Sep 2020
Edited: John D'Errico on 21 Sep 2020
You don't provide the actual data. But you are asking to do something which is trivially easy for the eye to do, more difficult for the computer.
This is not a question of linearly interpolating the two curves. It is of finding a sequence of midpoints that are visually midway between the curves, thus equidistant. But what is the distance between two curves? How will you define that distance?
In fact, this is a difficult problem. Consider two nonlinear curves, I'll call them A and B. Given any pooint on A, we might decide to find the closest point on curve B, then take the midpoint of the resulting line segment. The problem is, If we had started with the SAME point on curve B, and then found the closest point on curve A? It need not necessarily be the original point!
Do you see that the act of finding the closest point on a curve is not a commutative operator? That very claim means finding the midpoint between two curves is not a trivial task.
Regardless, that is how I would solve your problem. Given curves A and B, I would start with a sequence of points on curve A. For each such point, I would find the closest point on curve B. Then find the midpoint of each line segment. Use that as your mid-curve.
If I wanted to improve this scheme, I might then start with a similar sequence of points on curve B, now finding the sequence of closest points on curve A. Again, find the midpoint of each line segment. As I said, these two operations will generally NOT result in the same mid-curve! The two curves may be reasonably close though, at least if A and B are not too noisy.
Finally, though I would repeat the process, now finding the mid-curve between each of the last two curves. This iterative scheme should eventually approach a happy medium.
The nice thing is, you can do it all using two simple functions I have provided on the file exchange - distance2curve and interparc. (I'll get links for them in a second.)
First, an example. Two simple curves, since I lack your data.
x1 = linspace(-1,1,20);
F1 = @(x) 0.1*x.^3 + x.^2 + 1;
y1 = F1(x1);
x2 = linspace(-1.1,1.2,15);
F2 = @(x) 1.1 - cos(x);
y2 = F2(x2);
plot(x1,y1,'r-o',x2,y2,'bs--')
legend(func2str(F1),func2str(F2)) So two curves, sampled at a different number of points, not even over the same domain. And that means finding the mid-curve will be far more difficult than just interpolating the two curves at a list of points. Had I made the two curves such that they were not even single valued functions, it would be more difficult yet.
Finding the mid-curve between the two curves is not something as simple as just finding the average of the two curves, not in any respect. And it is NOT something that simple interpolation can handle. Interp1 would fail, for example, on the curves drawn in your figure, since they are not single-valued functions of x.
So how would I treat this?
First, I would choose a sequence of points equally spaced along curve 1. My interparc utility will do that nicely.
Then find the closest point for each on curve 2 for every such point from the first step. Find the midpoint of each indicated line segment between the two curves.
Repeat the process, starting with points on curve 2, finding the closest point on curve 1.
Finally, I'll draw the two mid-curves. We can see if they are reasonably close to being the same. If not, then we might consider repeating the process.
I'll write the entire thing as a function, since we will need to do it more than once.
function xymid = midcurve(xref,yref,xtarg,ytarg,n)
% two curves, one called the reference curve, the other the target.
% n is the number of points to generate along the reference curve.
% in come cases, there may be one or two more points appended to the
% ends of the mid curve. So the resulting curve may have n, n+1, or n+2
% total points on the curve.
% interpolate n points, equidistant on the reference curve.
xyrefint = interparc(n,xref,yref,'spline');
% For each of those points, find the CLOSEST point on the target curve.
[xytargint,D] = distance2curve([xtarg(:),ytarg(:)],xyrefint,'spline');
% get a measure of the overall distance between the two curves, to
% create a tolerance for the final step.
tol = mean(D)*1e-14;
% find the midpoint of each line segment connecting the curves
xymid = (xyrefint + xytargint)/2;
% was the first point the average of the first two points form the target
% and reference curves? If not, then extend the mid-curve by one point.
% Do so at each end if necessary.
if norm(xymid(1,:) - [(xref(1) + xtarg(1))/2,(yref(1) + ytarg(1))/2]) > tol
% appending a point at the start of the curve.
xymid = [(xref(1) + xtarg(1))/2,(yref(1) + ytarg(1))/2;xymid];
end
if norm(xymid(end,:) - [(xref(end) + xtarg(end))/2,(yref(end) + ytarg(end))/2]) > tol
% appending a point at the end of the curve.
xymid = [xymid;(xref(end) + xtarg(end))/2,(yref(end) + ytarg(end))/2];
end
end
That seems to work reasonably well. I have verified that if I swap the reference and target curves for the process, I do get subtly different results, but the distinction is not immense. Of course, these two test curves were not too nasty in shape.
xymid12 = midcurve(x1,y1,x2,y2,50);
xymid21 = midcurve(x2,y2,x1,y1,50);
plot(x1,y1,'k-o',x2,y2,'k-o',xymid12(:,1),xymid12(:,2),'ro-',xymid21(:,1),xymid21(:,2),'gs--') So I did get two subtly different mid-curves. Not too bad. I could repeat the process with those two curves and it would quickly converge.
Find the tools distance2curve and interparc on the file exchange, here:
So in the end, not too difficult. It took some care in the writing, but almost all of the work was done in my two utilities, so I had to write relatively little new code.

#### 1 Comment

Chris Topher on 23 Sep 2020
Thank you so much! I thought this was more like an easy task... It took me a while, but it seems to work.The results make sense.

Ameer Hamza on 21 Sep 2020
Check this code
% generating curves
x = linspace(1, 2, 100);
y1 = x.^3 + 2 + rand(size(x))*0.1; % let t=10 for this curve
y2 = x.^2 + 1 + rand(size(x))*0.1; % let t=15 for this curve
Y = [y1(:) y2(:)].';
ym = interp1([10 15], Y, 12); % interpolate at t=12
plot(x, y1, 'b-', x, y2, 'r-', x, ym, 'k--'); Image Analyst on 21 Sep 2020
Since the blue and yellow x,y vectors may not be the same length, you can't simply use interp1(). An approach I think might work is to use a scatteredInterpolant (demo attached). Another way might be to scan one vector, finding the closest point in the other vector and then take the midpoint.
Attach your data if you want more help.