2
\$\begingroup\$

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: example 1 example 2 example 3

I can use the the atan2 function.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This quedtion would probably better housed in the mathematics-SE? \$\endgroup\$
    – JFBM
    Aug 20, 2014 at 18:41
  • \$\begingroup\$ "I can use the atan2 function" OK, so, what's the problem then? \$\endgroup\$
    – Anko
    Aug 20, 2014 at 19:34

2 Answers 2

1
\$\begingroup\$

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.
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 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) \$\endgroup\$
    – kr1zz
    Sep 4, 2014 at 9:08
  • \$\begingroup\$ 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. \$\endgroup\$
    – user41442
    Sep 5, 2014 at 0:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .