Find the Angle ( as Measured in Counter Clock Wise Direction) Between Two Edges

This is a similar question to this one, but slightly different.

The question is given two edges ($$e_1$$ and $$e_2$$, with the vertex coordinates known), how to find the angles from $$e_1$$ to $$e_2$$, with the angles measured in anti clock wise direction?

A diagram is shown below:

One way I can think of is to compute the cross and dot product of the two edge's unit vectors:

$$\sin\,\theta=\frac{|e_1\times e_2|}{|e_1||e_2|}$$ $$\cos\,\theta=\frac{e_1\cdot e_2}{||e_1|| ||e_2||}$$

And try to find the $$\theta$$, taken into account of whether $$\sin\theta$$ and $$\cos\theta$$ is $$>0$$ or $$<0$$. But this is very, very tedious and error-prone. Not to mention I'm not too sure whether the angle I get is always measured in counterclockwise direction or not.

Is there a single, clean formula that allows me to do what I want to do?

• The two-argument arctangent would be very useful here. – J. M. isn't a mathematician Dec 22 '10 at 7:41
• @J.M, would you like to post your comment as answer so that I can accept it? – Graviton Dec 29 '10 at 12:29
• Gimme a few minutes; my comment as it stands is not a proper answer. – J. M. isn't a mathematician Dec 29 '10 at 12:44
• @J.M., it's enough to point me into the right direction and find the solution. – Graviton Dec 29 '10 at 12:44

The way to get the smaller angle spanned by $\mathbf e_1=(x_1,y_1)$ and $\mathbf e_2=(x_2,y_2)$ is through the expression

$\min(|\arctan(x_1,y_1)-\arctan(x_2,y_2)|,2\pi-|\arctan(x_1,y_1)-\arctan(x_2,y_2)|)$

where $\arctan(x,y)$ is the two-argument arctangent.

The answer by J.M. is correct, but depending on how you are calculating these, it might be much more efficient to use the method you initially proposed. Specifically note that (as shown in your question) $$\sin\,\theta$$ is proportional to the magnitude of the cross product and $$\cos\,\theta$$ is proportional to the dot product. Importantly, the constant of proportionality is the same for both. Now, assume we construct a new vector: $$\mathbf {e_3}=(|e_1\cdot e_2|, |e_1\times e_2|)=(r \cos\,\theta, r \sin\,\theta) \quad \textrm{ where } \quad r={|e_1||e_2|}$$ It's clear from the above that $$\mathbf {e_3}$$ is a vector with magnitude $$r$$ oriented at angle $$\theta$$. So we can use the x and y components of $$\mathbf {e_3}$$ to calculate the angle.

dot = x1*x2 + y1*y2      # dot product of e1 and e2
det = x1*y2 - y1*x2      # determinant (same as magnitude of cross product)
angle = atan2(det, dot)  # atan2(y, x) or atan2(sin, cos)


Note that whereas J.M.'s answer makes 4 calls to atan2 (which could be reduced to 2), this method makes only one call, along with some simple operations. Thus it's likely to be more computationally efficient, but that depends on the calculation environment.

Note that atan2 has its arguments reversed in some calculation environments (e.g. Spreadsheets, etc): atan2(x, y), so make sure you are passing them in the right order: cos corresponds to x and sin corresponds to y.

Note

As others have pointed out, this method may in some cases cause overflow (due to the multiplication of coordinates) and/or precision loss (due to addition/subtraction of products that could have drastically different magnitudes). This again depends on the computation environment and the datatypes used to represent the numbers involved.

It might be necessary or desirable in some cases to check for the conditions that would result in overflow or precision loss and to use an alternative method (like the accepted answer) when necessary.

• Interesting. Notice that this implementation may cause overflow (products) and/or massive precision loss (addition/subtraction). Probably irrelevant here, but for a robust implementation, one would need some more safety checks. – Jean-Claude Arbaut Oct 12 '16 at 5:40
• As @Stay mentions, this is more vulnerable to subtractive cancellation or over/underflow, which is why I did not go with this version. – J. M. isn't a mathematician Apr 12 '20 at 22:51
• @JMi - Thanks for the caveats about overflow and precision-loss. Those are good points. For the sake of other users who find this answer, would it be possible for you or StayHomeSaveLives to post some examples of (1) Computations that suffer due to the problems you mention and (2) Potential safety checks that should be performed to decide whether to use this method or the less-efficient-but-more-accurate version that JMi posted? If you want, you can message me or start a discussion, and I will post an edit to my answer Thanks! – drwatsoncode Apr 14 '20 at 0:29