views:

218

answers:

6

I have a parametric curve, say two vectors of doubles where the parameter is the index, and I have to calculate the angle of the tangent to this curve at any given point (index).

Any suggestion or link about how to do that?

Thanks.

+1  A: 

Compute the first derivative: dy/dx. That gives you the tangent.

sisis
+3  A: 

The first problem you run into is to even define the tangent in one of the vertexes of the curve. Consider e.g. that you have the two arrays:

x = { 1.0, 2.0, 2.0 };
y = { 1.0, 1.0, 2.0 };

Then at the second vertex you have a 90-degree change of direction of the line. In that place the tangent isn't even defined mathematically.

Answer to gregseth's comment below

I guess in your example the "tangent" at the second point would be the line parallel to (P0,P2) passing through P1... which kind of give me the answer : for any point of index N the parallel to (N-1, N+1) passing through N. Would that be a not-too-bad approximation?
It depends on what you are using it for. Consider for example:

x = { 1.0, 2.0, 2.0 };
y = { 1.0, 1000000, 1000000 };

That is basically an L shape with a very high vertical line. In your suggestion it would give you an almost vertical tangent. Is that what you want, or do you rather want a 45-degree tangent in that case? It also depends on your input data how you sould define it.

One solution is get the two vectors connection to the vertex, normalize them and then use your algorithm. That way you would get a 45-degree tangent in the above example.

Anders Abel
+1: OP needs to clarify the definition of the tangent at the index points
High Performance Mark
I guess in your example the "tangent" at the second point would be the line parallel to (P0,P2) passing through P1... which kind of give me the answer : for any point of index N the parallel to (N-1, N+1) passing through N. Would that be a not-too-bad approximation?
gregseth
+3  A: 

I suggest you check out the Wikipedia article on numerical differentiation for a start. Before you go much further than that, decide what purposes you want the tangent for and decide whether or not you need to try more complex schemes than the simple ones in the article.

High Performance Mark
A: 

You can try to compute the tangent of an interpolating curve that passes through the given points (I'm thinking of a cubic spline, which is pretty easy to derive) or compute the tangent directly from the data points.

You can find a rough approximation of the derivative in the following manner Let a curve C pass through points p1,p2 and p3. At point p2 you have two possible tangents: t1=p2-p1 and t2=p3-p2. You can combine them by simply computing their average: 0.5*(t1+t2) or you can combine them according to their lengths (or their reciprocal 1/length)

Remember to normalize the resulting tangent.

In order to compute the angle between the tangent and the curve, remember that the dot product of two unit vectors gives the cosine of the angle between them. Take the resulting tangent t and the unit vector v2=|p3-p2|, and acos(dot(t,v2)) gives the angle you need.

pau.estalella
+1  A: 

The tangent to a smooth curve at a point P is the parametric straight line P + tV, where V is the derivative of the curve with respect to "the parameter". But here the parameter is just the index of an array, and numerical differentiation is a difficult problem, hence to approximate the tangent I would use (weighted) least squares approximation.

In other words, choose three or five points of the curve around your point of interest P (i.e. P[i-2], P[i-1], P[i], P[i+1], and P[i+2], if P==P[i]), and approximate them with a straight line, in the least squares sense. The more weight you assign to the middle point P, the more close the line will be to P; on the other hand, the more weight you assign to the extremal points, the more "tangent" the straight line will be, that is, the more nicely it will approximate you curve in the neighborhood of P.

For example, with respect to the following points:

x = [-1, 0, 1]
y = [ 0, 1, 0]

for which the tangent is not defined (as in Anders Abel's answer), this approach should yield a horizontal straight line close to the point (0,1).

Federico Ramponi
I like this approach but I'm not sure to get the weighing part.Am I right stating that since I'm only interested in the slope on the tangent (the angle with the X axis) I don't need to weight the values?
gregseth
+2  A: 

Here's a short formula, equivalent (I think) to pau.estalella's answer:

m[i] = (y[i+1] - y[i-1]) / (x[i+1] - x[i-1])

this approximates, reasonably well, the slope at the point (x[i], y[i]).

Your question mentions the "angle of the tangent". The tangent line, having slope m[i], makes angle arctangent(m[i]) with the positive x axis. If this is what you're after, you might use the two-argument arctangent, if it's available:

angle[i] = atan2(y[i+1] - y[i-1], x[i+1] - x[i-1])

this will work correctly, even when x[i+1] == x[i-1].

George Kangas