Calculating angle a segment forms with a ray

I am given a point C and a ray r starting there. I know the coordinates (xc, yc) of the point C and the angle theta the ray r forms with the horizontal, theta in (-pi, pi]. I am also given another point P of which I know the coordinates (xp, yp): how do I calculate the angle alpha that the segment CP forms with the ray r, alpha in (-pi, pi]?

Some examples follow:

I can use the the atan2 function.

• This quedtion would probably better housed in the mathematics-SE? – J_F_B_M Aug 20 '14 at 18:41
• "I can use the atan2 function" OK, so, what's the problem then? – Anko Aug 20 '14 at 19:34

No conditions, you don't need normalised vectors, a single trig function:

Vector2 pc = p - c;
float crossp = pc.x * ray.direction.y - pc.y * ray.direction.x;
float dotp = pc.x * ray.direction.x + pc.y * ray.direction.y;
return Math.atan2(crossp, dotp);


Here is the explanation. A fast summary:

• Cross product between two vectors is the same as sin(theta) * len(v1) * len(v2)
• Dot product between two vectors is the same as cos(theta) * len(v1) * len(v2)
• Since atan2 requires two variables (the y and the x component), it already outputs detailed info (an angle on the ]-pi, +pi] range, so it gives sense of direction too)
• atan2(y, x) is simply atan(y / x), if you put the entire formula, atan((sin * len1 * len2) / (cos * len1 * len2)) you see that len1 and len2 cancel themselves, so we're just with atan(sin / cos). Since sin represents the vertical component of a triangle and cos represents the horizontal component of a triangle, everything goes well, no need to take a single sqrt and no need to use conditionals to change the range.

We find the vector from c to p (p - c), and compute its angle with the x-axis. Then we subtract, and put it into the right range.

theta2 = atan2(p_x - c_x, p_y - c_y)
alpha = theta2-theta
if (alpha > pi) alpha -= 2pi
if (alpha <= -pi) alpha += 2pi


This assumes that theta is in the range (-pi, pi], and atan2 gives its result in the range (-pi, pi] as well. Otherwise you can just make those while loops.

Note this is a signed angle, not an absolute one.

• I took some time to experiment. According to The correct formula appears to be as follows: theta2 = atan2(p_y - c_y, p_x - c_x) and not theta2 = atan2(p_x - c_x, p_y - c_y) – kr1zz Sep 4 '14 at 9:08
• Ah, there are differing conventions on the order of the arguments to atan2, as it is effectively arctan(y/x) with division by zero handled properly, but is it atan2(x,y) or atan2(y,x)? Different libraries make different choices. – user41442 Sep 5 '14 at 0:14