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\$
  • 1
    \$\begingroup\$ This quedtion would probably better housed in the mathematics-SE? \$\endgroup\$ – J_F_B_M Aug 20 '14 at 18:41
  • \$\begingroup\$ "I can use the atan2 function" OK, so, what's the problem then? \$\endgroup\$ – Anko Aug 20 '14 at 19:34
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.
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\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 '14 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 '14 at 0:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.