MATLAB: Find tangent to set of 2D points

geometryinterpolationMATLABtangent

Hi All!
I have sets of 2D points, which form something like a circle, but NOT necessarily convex (see picture below). The points are given by two vectors (x and y coordinates), in clockwise order. Unfortunately, this is not a classic y=f(x) function, as there can be two y values to the same x. (Also there can be vertical lines).
I'd like to find a tangent vector for each point (preferably also in clockwise direction). Can you help me? I find none of MATLAB's interpolation functions useful, as they only work on functions, not on R->R^2 data.
I was thinking about using some sort of analytical solution, which uses e.g. 5 points, to calculate the tangent vector at the 3rd, or some sort of numerical differentiation method, but I couldn't find one. (I'm sure there has to be an algorithm out there for this…)
I think using interpolation for the whole set would be too much for this problem, but if nothing else works…

Best Answer

Your curve is somewhat noisy. I might think to point out that my interparc tool from the file exchange can be made to give estimates of the derivatives of the curve at any point along the curve. So it would return two numbers at a point that are essentially dx/dt and dy/dt. The ratio is the slope of the tangent line at that point.
The above works even for non-functional closed curves as you have, since interparc works in a parametric form. It computes a simple cumulative linear chordal arclength along the curve, then uses spline models x(t), y(t).
The problem is, your data is somewhat noisy, based on the curve we are shown. So that tangent line would be pointing all over the place.
Anyway, if you were to use interparc in that way, then it would be just as simple to do the work yourself. You do not provide your data. But, suppose you have data that is in the form of two vectors x and y, sorted in order along such a path in the (x,y) plane?
t = cumsum([0;diff(x(:)).^2 + diff(y(:)).^2)]);
So, t is the cumulative piecewise linear distance between each point, one to the next along your curve.
splx = spline(t,x);
sply = spline(t,y);
Differentiate each spline, then evaluate the ratio of the derivatives at the original points. That is the slope of the tangent line, at that point. If you have the curve fitting toolbox, you can use fnder to differentiate the splines.
tanslope = ppval(fnder(sply),t)./ppval(fnder(splx),t);
If no curvefitting toolbox, the derivative function is trivial to generate for the pp form that spline returns.
Again, the issue is that you may wish to produce a smoother estimate of the tangent slope. If you provide your data, and you need such a smoothed tangent line, just attach the data to a .mat file as a comment.