0

I'm trying to identify the angle between two points via a central point using c++. I'm using std::atan2(y,x) to obtain the angle. For brevity, I'm converting the radians to degrees. This is working fine.

However, my problems lie with the sign change when the position of the two points change. The angle given is either -200 or 160. Of course, this is the same angle just 360 degrees out. I'd rather just have the same value to make comparison checks sane. How can I do this?

The function that I'm using to calculate the angle, and convert to degrees:

static double computeAngleFromCenter(cv::Point center, cv::Point p, bool asDegrees = false)
{
    double angle = std::atan2(p.y - center.y, p.x - center.x);

    if (asDegrees)
        angle *= 180 / 3.1415926;

    return angle;
}

The obvious answer is to just add 360 if the angle < 0, but is this the best way?

user3791372
  • 4,445
  • 6
  • 44
  • 78

5 Answers5

1

According to the documentation:

Return Value:
Principal arc tangent of y/x, in the interval [-pi,+pi] radians. One radian is equivalent to 180/PI degrees.

If you would rather have it return a value on the interval [0, +2pi], then yes, you're going to need to apply a little fixup.

antiduh
  • 11,853
  • 4
  • 43
  • 66
1

You could use fmod before conditionally converting to degrees:

angle = fmod( angle + PI * 2, PI * 2 );

Depending on the compiler and math library, it may be faster or slower than the more straight-forward code that is easier to read:

if (angle < 0)
    angle += PI * 2;

If this code is only used hundreds of times per second on a desktop machine, I doubt you would even notice the difference. For a phone/tablet, maybe I would set that limit at dozens of times per second.

edit: negative angle needs PI * 2 added, not just PI.

Khouri Giordano
  • 1,426
  • 15
  • 17
0

According to the documentation for atan2 the return is always in the range [-pi, pi] so I don't think you would ever see a -200 deg as you were suggesting. That said it does still return results in the 3rd and 4th quadrants as negative values. Since the function explicitly calls out this behavior, the most straightforward solution is to add 2pi radians to a negative return result.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

More straight possible:

static double computeAngleFromCenter(cv::Point center, cv::Point p, bool asDegrees = false)
{
    double angle = std::atan2(p.y - center.y, p.x - center.x);

    if (asDegrees)
        angle *= 180 / 3.1415926;

    return angle + 360; // [180, 540] Always positive.
}
0
static double computeAngleFromCenter(cv::Point center, cv::Point p, bool asDegrees = false)

{
    double angle = std::atan2(p.y - center.y, p.x - center.x);

    if (asDegrees)
        angle *= 180 / 3.1415926;
        if(angle<0)angle+=360;
    return angle;
}