How to use atan2() in combination with other Radian angle systems
Asked Answered
M

5

6

I am struggling with this in JavaScript, but this problem applies to many other languages/environments as well.

I want to have one object rotating towards the position of another object, and I use:

atan2(obj1.dy, obj1.dx) - obj2.getRotation()

to check if the second object should rotate clockwise or counterclockwise at a given time.

In KineticJS, the JS/HTML5/Canvas programming environment I am using, the angle is specified in radians from 0 to 2 pi starting at the positive Y axis and going clockwise. This behaviour is seen in many other programming environments as well.

However, when calculating the angle of movement from the second object with the Math.atan2(y,x) function, the angle is specified from -pi to pi, starting at the positive X axis, going counterclockwise.

To clarify:

Difference between normal radians and atan2()

The question:

How can I calculate an angle in normal radians from the result of the atan2() function?

Muire answered 10/7, 2013 at 15:15 Comment(2)
"In Javascript/HTML5/Canvas (as well as in lots of other programming environments), the angle is specified in radians from 0 to 2 pi starting at the positive Y axis and going clockwise." Are you sure this is a convention specified by the language, and not by your own code base? Last time I used canvas, I assumed radians started at the positive X axis and moved counterclockwise, and everything worked the way I expected.Lichi
Kevin, you might be right. Indeed I am using KineticJS for my current application, which behaves in the way I stated. I am not sure how this convention is specified in the original canvas context. Thank you for pointing this out, I will edit it.Muire
H
2

If you want the angle to increase clockwise from 0 on the y axis, calculate the angle as atan2(x,y). This however give negative angles for x<0, so you should add 2*pi in this case.

Honourable answered 10/7, 2013 at 15:30 Comment(0)
P
3

The values are the same in both cases, modulo 2*PI, and with an adjustment for the different sign and offset convention. Pseudo-code:

theta = 0.5*M_PI - atan2(y, x); // adjust for required sign/offset
theta = fmod(theta, 2.0*M_PI);  // make result modulo 2*PI
Prieto answered 10/7, 2013 at 15:19 Comment(2)
This seems correct, but the answer is still oriented counter-clockwise and rotated by .5pi radMuire
Missed that part, sorry - have now updated answer to cover this.Prieto
H
2

If you want the angle to increase clockwise from 0 on the y axis, calculate the angle as atan2(x,y). This however give negative angles for x<0, so you should add 2*pi in this case.

Honourable answered 10/7, 2013 at 15:30 Comment(0)
F
1

If your result is between 0 and Pi, then the result is pretty straight-forward. If your result is between -Pi and 0, then add 2*Pi to your result, this way you will have your result in the interval of 0, 2*Pi.

Of course, it would be nice if you would implement a separate function for this type of conversion, to not duplicate your code every now and then.

Foreshore answered 10/7, 2013 at 16:20 Comment(0)
B
0

Just use the condition

 var radians = Math.atan2(e.y - cy, e.x - cx);
 if(radians < 0 ) {radians += 2*Math.PI;}

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
canvas.onmousedown = function(e){
var rect = canvas.getBoundingClientRect();
var cx = rect.left + rect.width / 2, cy = rect.top + rect.height / 2;
var radians = Math.atan2(e.y - cy, e.x - cx);
if(radians < 0 ) {radians += 2*Math.PI;}
ctx.moveTo(cx,cy);
ctx.lineTo(cx + 100 * Math.cos(radians), cy + 100* Math.sin(radians));
ctx.stroke();
};
<canvas id="canvas" width="200px" height="200px" style="background-color: gold;"></canvas>
Bernetta answered 22/2, 2020 at 20:1 Comment(0)
I
0
float getAngle(float x, float y)
{
    float TAU=PI*2;
    return (atan2(x,y)+TAU)%TAU;
}
Ideally answered 10/5, 2023 at 17:22 Comment(1)
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?Retentive

© 2022 - 2024 — McMap. All rights reserved.