4
$\begingroup$

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 vector

$$\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 counter clock wise direction or not.

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

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

2 Answers 2

2

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.

2

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 proporationality 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 arithmatic. Thus it 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.

  • 0
    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.2016-10-12