Difference Between Atan and Atan2 in C++

What is the difference between atan and atan2 in C++?

std::atan2 allows calculating the arctangent of all four quadrants. std::atan only allows calculating from quadrants 1 and 4.

Python atan or atan2, what should I use?

Atan takes single argument and Atan2 takes two arguments.The purpose of using two arguments instead of one is to gather information on the signs of the inputs in order to return the appropriate quadrant of the computed angle, which is not possible for the single-argument Atan

atan2 results for each x,y

Atan2 result is always between -pi and pi.

Reference:
https://en.wikipedia.org/wiki/Atan2

Convert from atan2 to atan

You can do the opposite from what was done in this question.

double myatan(double y, double x)
{
double pi = 3.14159265358979323846;
if (x >= 0)
return atan2(y, x);
else if (y >= 0)
return atan2(y, x) - pi;
else
return atan2(y, x) + pi;
}

How to convert from atan to atan2?

In a nutshell, math.atan only works for quadrants 1 and 4. For quadrants 2 and 3 (i.e. for x < 0), then you'd have to add or subtract pi (180 degrees) to get to quadrants 1 and 4 and find the respective value for the theta. In code, it means that

if (y < 0 and x < 0): 
print(math.atan(y/x) - math.pi)
elif (y > 0 and x < 0):
print(math.atan(y/x) + math.pi)

For more reference, take a look at atan2. The other two use cases are those in which x > 0, which works well with atan.

Signed Char ATAN2 and ATAN approximations

An outline follows. Below is additional information.

  1. The result angle (a Binary Angle Measure) exactly mathematically divides the unit circle into 8 wedges. Assuming -128 to 127 char, for atan2SC() the result of each octant is 33 integers: 0 to 32 + an offset. (0 to 32, rather than 0 to 31 due to rounding.) For atan2SC(), the result is 0 to 64. So just focus on calculating the result of 1 primary octant with x,y inputs and 0 to 64 result. atan2SC() and atan2SC() can both use this helper function at2(). For atan2SC(), to find the intermediate angle a, use a = at2(x,y)/2. For atanSC(), use a = at2(-128, y).

  2. Finding the integer quotient with a = divisionSC(x,y) and then a * (43 + 11 * A) loses too much information in the division. Need to find the atan2 approximation with an equation that uses x,y maybe in the form at2 = (a*y*y + b*y)/(c*x*x + d*x).

  3. Good to use negative absolute value as with nabsSC(). The negative range of integers meets or exceed the positive range. e.g. -128 to -1 vs 1 to 127. Use negative numbers and 0, when calling the at2().


[Edit]


  1. Below is code with a simplified octant selection algorithm. It is carefully constructed to insure any negation of x,y will result in the SCHAR_MIN,SCHAR_MAX range - assuming 2's complelment. All octants call the iat2() and here is where improvements can be made to improve precision. Note: iat2() division by x==0 is prevented as x is not 0 at this point. Depending on rounding mode and if this helper function is shared with atanSC() will dictate its details. Suggest a 2 piece wise linear table is wide integer math is not available, else a a linear (ay+b)/(cx+d). I may play with this more.

  2. The weight of precision vs. performance is a crucial one for OP's code, but not pass along well enough for me to derive an optimal answer. So I've posted a test driver below that assesses the precision of what ever detail of iat2() OP comes up with.

  3. 3 pitfalls exist. 1) When answer is to be +180 degree, OP appears to want -128 BAM. But atan2(-1, 0.0) comes up with +pi. This sign reversal may be an issue. Note: atan2(-1, -0.0) --> -pi. Ref. 2) When an answer is just slightly less than +180 degrees, depending on iat2() details, the integer BAM result is +128, which tends to wrap to -128. The atan2() result is just less than +pi or +128 BAM. This edge condition needs review inOP's final code. 3) The (x=0,y=0) case needs special handling. The octant selection code finds it.

  4. Code for a signed char atanSC(signed char x), if it needs to be fast, could use a few if()s and a 64 byte look-up table. (Assuming a 8 bit signed char). This same table could be used in iat2().

.

#include <stdio.h>
#include <stdlib.h>

// -x > -y >= 0, so divide by 0 not possible
static signed char iat2(signed char y, signed char x) {
// printf("x=%4d y=%4d\n", x, y); fflush(stdout);
return ((y*32+(x/2))/x)*2; // 3.39 mxdiff
// return ((y*64+(x/2))/x); // 3.65 mxdiff
// return (y*64)/x; // 3.88 mxdiff
}

signed char iatan2sc(signed char y, signed char x) {
// determine octant
if (y >= 0) { // oct 0,1,2,3
if (x >= 0) { // oct 0,1
if (x > y) {
return iat2(-y, -x)/2 + 0*32;
} else {
if (y == 0) return 0; // (x=0,y=0)
return -iat2(-x, -y)/2 + 2*32;
}
} else { // oct 2,3
// if (-x <= y) {
if (x >= -y) {
return iat2(x, -y)/2 + 2*32;
} else {
return -iat2(-y, x)/2 + 4*32;
}
}
} else { // oct 4,5,6,7
if (x < 0) { // oct 4,5
// if (-x > -y) {
if (x < y) {
return iat2(y, x)/2 + -4*32;
} else {
return -iat2(x, y)/2 + -2*32;
}
} else { // oct 6,7
// if (x <= -y) {
if (-x >= y) {
return iat2(-x, y)/2 + -2*32;
} else {
return -iat2(y, -x)/2 + -0*32;
}
}
}
}

#include <math.h>

static void test_iatan2sc(signed char y, signed char x) {
static int mn=INT_MAX;
static int mx=INT_MIN;
static double mxdiff = 0;

signed char i = iatan2sc(y,x);
static const double Pi = 3.1415926535897932384626433832795;
double a = atan2(y ? y : -0.0, x) * 256/(2*Pi);

if (i < mn) {
mn = i;
printf ("x=%4d,y=%4d --> %4d %f, mn %d mx %d mxdiff %f\n",
x,y,i,a,mn,mx,mxdiff);
}
if (i > mx) {
mx = i;
printf ("x=%4d,y=%4d --> %4d %f, mn %d mx %d mxdiff %f\n",
x,y,i,a,mn,mx,mxdiff);
}

double diff = fabs(i - a);
if (diff > 128) diff = fabs(diff - 256);

if (diff > mxdiff) {
mxdiff = diff;
printf ("x=%4d,y=%4d --> %4d %f, mn %d mx %d mxdiff %f\n",
x,y,i,a,mn,mx,mxdiff);
}
}


int main(void) {
int x,y;
int n = 127;
for (y = -n-1; y <= n; y++) {
for (x = -n-1; x <= n; x++) {
test_iatan2sc(y,x);
}
}
puts("Done");
return 0;
}

BTW: a fun problem.

Why is −π atan2(y, x) ≤ π while for lines we really need only from 0 to π?

One common application of atan2 is converting from cartesian coordinates to polar coordinates. And that it supports all angles is its reason of existance. Else you could just use atan(y/x).

Does atan2 required normalized vectors? Which is better to use acos or atan for angles between vectors?

No, atan2 does not require normalized vectors, and if your vectors are not already normalized you shouldn't pre-normalize them as that may slightly reduce precision. The function works correctly for any inputs other than (0,0).

You should never use acos for anything.

atan problems in c++

The standard atan and atan2 functions, as well as all other C functions that work with angles, work with radians, not degrees.

If you want your own function to output degrees, you have to multiply the return value from atanf with 180/pi; to keep everything in radians, add pi instead of 180.

Why are the arguments to atan2 Y,X rather than X,Y?

Because I believe it is related to arctan(y/x), so y appears on top.

Here's a nice link talking about it a bit: Angles and Directions



Related Topics



Leave a reply



Submit