Asked by Akos Gyenge
on 14 Jun 2018

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...

Answer by John D'Errico
on 14 Jun 2018

Accepted 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.

Akos Gyenge
on 14 Jun 2018

Thank you very much John, for this pretty detailed help. I am sure, I'll find the solution now.

Also, great respect and thanks for this comment, especially for bringing up even more ways to solve my problem.

John D'Errico
on 14 Jun 2018

Great. You will need to decide how much you want to chase the bumps.

Image Analyst
on 14 Jun 2018

* WHY* the tangents at every point are wanted. It might help shape the answer. All too often someone asks "how do I do X" and then you tell them and they say "that doesn't work" and you then ask what they really want to do and they say "I need Z" and then you say "Well if you really want Z you don't do X at all, you do Y instead." I'm not saying that's the case here, but I do wonder why the tangents are really needed, or if there's a simpler or more direct way to do what you need to do.

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.